Skip to content

Commit

Permalink
feat: perfect discolorate animation
Browse files Browse the repository at this point in the history
  • Loading branch information
sheepbox8646 committed Nov 30, 2024
1 parent 044fbf0 commit bbd8acd
Show file tree
Hide file tree
Showing 3 changed files with 157 additions and 48 deletions.
104 changes: 82 additions & 22 deletions packages/lib/src/animations/color.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,13 @@ export interface Colorable {
color?: string;
}

export interface colorableMixin {
discolorate: (on: "fill" | "border" | "color", offset: string) => void;
discolorateTo: (on: "fill" | "border" | "color", to: string) => void;
export interface ColorableMixin {
discolorate: (offset: string) => void;
discolorateTo: (to: string) => void;
discolorateBorder: (offset: string) => void;
discolorateBorderTo: (to: string) => void;
discolorateFill: (offset: string) => void;
discolorateFillTo: (to: string) => void;
}

interface RGB {
Expand Down Expand Up @@ -101,49 +105,105 @@ export const discolorate = defineAnimation<
{
from?: string;
offset?: string;
on: "fill" | "border" | "color";
}
>((target, context) => {
const propertyMap = {
fill: "fillColor",
border: "borderColor",
color: "color",
};
const property = propertyMap[context.on] as keyof Colorable;

const fromColor = context.from || target[property] || "#000000";
const currentColor = target.color;
const fromColor = context.from || currentColor || "#000000";
const toColor = context.offset
? shiftColor(fromColor, context.offset)
: target[property] || "#000000";
: currentColor || "#000000";

return (progress) => {
target[property] = interpolateColor(fromColor, toColor, progress);
target.color = interpolateColor(fromColor, toColor, progress);
};
});

export const discolorateTo = defineAnimation<
Colorable,
{
to: string;
on: "fill" | "border" | "color";
}
>((target, context) => {
const propertyMap = {
fill: "fillColor",
border: "borderColor",
color: "color",
const currentColor = target.color;
const fromColor = currentColor
? findColor(currentColor as keyof typeof colorTable) || currentColor
: "#000000";
const toColor =
findColor(context.to as keyof typeof colorTable) || context.to;

return (progress) => {
target.color = interpolateColor(fromColor, toColor, progress);
};
});

export const discolorateBorder = defineAnimation<
Colorable,
{
from?: string;
offset?: string;
}
>((target, context) => {
const currentColor = target.borderColor;
const fromColor = context.from || currentColor || "#000000";
const toColor = context.offset
? shiftColor(fromColor, context.offset)
: currentColor || "#000000";

return (progress) => {
target.borderColor = interpolateColor(fromColor, toColor, progress);
};
const property = propertyMap[context.on] as keyof Colorable;
});

const currentColor = target[property];
export const discolorateBorderTo = defineAnimation<
Colorable,
{
to: string;
}
>((target, context) => {
const currentColor = target.borderColor;
const fromColor = currentColor
? findColor(currentColor as keyof typeof colorTable) || currentColor
: "#000000";
const toColor =
findColor(context.to as keyof typeof colorTable) || context.to;

return (progress) => {
target.borderColor = interpolateColor(fromColor, toColor, progress);
};
});

export const discolorateFill = defineAnimation<
Colorable,
{
from?: string;
offset?: string;
}
>((target, context) => {
const currentColor = target.fillColor;
const fromColor = context.from || currentColor || "#000000";
const toColor = context.offset
? shiftColor(fromColor, context.offset)
: currentColor || "#000000";

return (progress) => {
target.fillColor = interpolateColor(fromColor, toColor, progress);
};
});

export const discolorateFillTo = defineAnimation<
Colorable,
{
to: string;
}
>((target, context) => {
const currentColor = target.fillColor;
const fromColor = currentColor
? findColor(currentColor as keyof typeof colorTable) || currentColor
: "#000000";
const toColor =
findColor(context.to as keyof typeof colorTable) || context.to;

return (progress) => {
target[property] = interpolateColor(fromColor, toColor, progress);
target.fillColor = interpolateColor(fromColor, toColor, progress);
};
});
95 changes: 70 additions & 25 deletions packages/lib/src/widgets/widget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,15 @@ import {
zoomOut,
zoomTo,
} from "../animations";
import type { Colorable, colorableMixin } from "../animations/color";
import { discolorate, discolorateTo } from "../animations/color";
import type { Colorable, ColorableMixin } from "../animations/color";
import {
discolorate,
discolorateBorder,
discolorateBorderTo,
discolorateFill,
discolorateFillTo,
discolorateTo,
} from "../animations/color";
import type {
Animation,
AnimationInstance,
Expand All @@ -59,7 +66,7 @@ export type WidgetMixin = WidgetOptions &
HasScaleMixin &
StrokableMixin &
HasOpacityMixin &
colorableMixin &
ColorableMixin &
GrowableMixin & {
parallel: (
...animations: ((
Expand Down Expand Up @@ -237,54 +244,92 @@ export function widget(options: WidgetOptions) {
by: params?.by ?? ((x) => x),
});
});
registerAnimation<Colorable>(
"discolorate",
registerAnimation<Positional>(
"moveOnPath",
(path: string, params?: AnimationParams) => {
return (manager) =>
manager.animate(moveOnPath, {
path,
duration: params?.duration ?? defaultDuration,
by: params?.by ?? ((x) => x),
});
},
);
registerAnimation<Positional>(
"moveOnFunction",
(
on: "fill" | "border" | "color",
offset: string,
path: (progress: number) => { x: number; y: number },
params?: AnimationParams,
) => {
return (manager) =>
manager.animate(discolorate, {
offset,
on,
manager.animate(moveOnFunction, {
path,
duration: params?.duration ?? defaultDuration,
by: params?.by ?? ((x) => x),
});
},
);
registerAnimation<Positional>(
"moveOnPath",
(path: string, params?: AnimationParams) => {
registerAnimation<Colorable>(
"discolorate",
(offset: string, params?: AnimationParams) => {
return (manager) =>
manager.animate(moveOnPath, {
path,
manager.animate(discolorate, {
offset,
duration: params?.duration ?? defaultDuration,
by: params?.by ?? ((x) => x),
});
},
);
registerAnimation<Colorable>(
"discolorateTo",
(on: "fill" | "border" | "color", to: string, params?: AnimationParams) => {
(to: string, params?: AnimationParams) => {
return (manager) =>
manager.animate(discolorateTo, {
to,
on,
duration: params?.duration ?? defaultDuration,
by: params?.by ?? ((x) => x),
});
},
);
registerAnimation<Positional>(
"moveOnFunction",
(
path: (progress: number) => { x: number; y: number },
params?: AnimationParams,
) => {
registerAnimation<Colorable>(
"discolorateBorder",
(offset: string, params?: AnimationParams) => {
return (manager) =>
manager.animate(moveOnFunction, {
path,
manager.animate(discolorateBorder, {
offset,
duration: params?.duration ?? defaultDuration,
by: params?.by ?? ((x) => x),
});
},
);
registerAnimation<Colorable>(
"discolorateBorderTo",
(to: string, params?: AnimationParams) => {
return (manager) =>
manager.animate(discolorateBorderTo, {
to,
duration: params?.duration ?? defaultDuration,
by: params?.by ?? ((x) => x),
});
},
);
registerAnimation<Colorable>(
"discolorateFill",
(offset: string, params?: AnimationParams) => {
return (manager) =>
manager.animate(discolorateFill, {
offset,
duration: params?.duration ?? defaultDuration,
by: params?.by ?? ((x) => x),
});
},
);
registerAnimation<Colorable>(
"discolorateFillTo",
(to: string, params?: AnimationParams) => {
return (manager) =>
manager.animate(discolorateFillTo, {
to,
duration: params?.duration ?? defaultDuration,
by: params?.by ?? ((x) => x),
});
Expand Down
6 changes: 5 additions & 1 deletion test/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,11 @@ onMounted(() => {
by: easeInOutCirc,
},
);
rect.discolorateTo("fill", "skyblue");
rect.parallel(
(r) => r.discolorateFillTo("skyblue"),
(r) => r.discolorateBorderTo("yellow"),
(r) => r.move(-200, -200),
);
play();
});
</script>
Expand Down

0 comments on commit bbd8acd

Please sign in to comment.