Skip to content

Commit

Permalink
feat(📈): mixPath() and parse() (#347)
Browse files Browse the repository at this point in the history
  • Loading branch information
wcandillon authored Sep 23, 2020
1 parent fb92e50 commit 2ec4846
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 22 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
"@types/color": "^3.0.0",
"@types/jest": "^25.1.4",
"@types/react": "*",
"@types/react-native": "^0.60.25",
"@types/react-native": "0.63.20",
"babel-jest": "^24.9.0",
"babel-preset-expo": "^8.0.0",
"eslint": "^7.8.1",
Expand Down
8 changes: 4 additions & 4 deletions src/Colors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export const blue = (c: number) => {
return c & 255;
};

export const color = (r: number, g: number, b: number, alpha = 1) => {
export const color = (r: number, g: number, b: number, alpha = 1): Color => {
"worklet";
if (Platform.OS === "web" || !_WORKLET) {
return `rgba(${r}, ${g}, ${b}, ${alpha})`;
Expand Down Expand Up @@ -86,7 +86,7 @@ export const hsv2rgb = (h: number, s: number, v: number) => {
};
};

export const hsv2color = (h: number, s: number, v: number) => {
export const hsv2color = (h: number, s: number, v: number): Color => {
"worklet";
const { r, g, b } = hsv2rgb(h, s, v);
return color(r, g, b);
Expand Down Expand Up @@ -203,7 +203,7 @@ export const interpolateColor = (
inputRange: number[],
rawOutputRange: Color[],
colorSpace: ColorSpace = ColorSpace.RGB
) => {
): Color => {
"worklet";
const outputRange = rawOutputRange.map((c) =>
typeof c === "number" ? c : processColor(c)
Expand All @@ -220,7 +220,7 @@ export const mixColor = (
color1: Color,
color2: Color,
colorSpace: ColorSpace = ColorSpace.RGB
) => {
): Color => {
"worklet";
return interpolateColor(value, [0, 1], [color1, color2], colorSpace);
};
50 changes: 43 additions & 7 deletions src/Paths.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
import { interpolate } from "react-native-reanimated";
import parseSVG from "parse-svg-path";
import absSVG from "abs-svg-path";
import normalizeSVG from "normalize-svg-path";

import { Vector } from "./Vectors";

type SVGCloseCommand = ["Z"];
type SVGMoveCommand = ["M", number, number];
type SVGCurveCommand = ["C", number, number, number, number, number, number];
type SVGNormalizedCommands = [
SVGMoveCommand | SVGCurveCommand | SVGCloseCommand
];

export enum SVGCommand {
MOVE,
CURVE,
Expand Down Expand Up @@ -78,17 +88,38 @@ export const serialize = (path: SVGSegment[]) => {
.reduce((acc, c) => acc + c);
};

interface PathInterpolation<T extends number[]> {
inputRange: T;
outputRange: { [K in keyof T]: SVGSegment[] };
}
export const parse = (d: string): SVGSegment[] => {
const segments: SVGNormalizedCommands = normalizeSVG(absSVG(parseSVG(d)));
return segments.map((segment) => {
if (segment[0] === "M") {
return move(segment[1], segment[2]);
} else if (segment[0] === "Z") {
return close();
} else {
return curve({
c1: {
x: segment[1],
y: segment[2],
},
c2: {
x: segment[3],
y: segment[4],
},
to: {
x: segment[5],
y: segment[6],
},
});
}
});
};

export const interpolatePath = <T extends number[]>(
export const interpolatePath = (
value: number,
config: PathInterpolation<T>
inputRange: number[],
outputRange: SVGSegment[][]
) => {
"worklet";
const { inputRange, outputRange } = config;
const path = outputRange[0].map((segment, index) => {
if (isMove(segment)) {
const points = outputRange.map((p) => {
Expand Down Expand Up @@ -172,6 +203,11 @@ export const interpolatePath = <T extends number[]>(
return serialize(path);
};

export const mixPath = (value: number, paths: [SVGSegment[], SVGSegment[]]) => {
"worklet";
return interpolatePath(value, [0, 1], paths);
};

export const move = (x: number, y: number) => {
"worklet";
return { type: SVGCommand.MOVE as const, x, y };
Expand Down
18 changes: 18 additions & 0 deletions src/__tests__/Paths.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { serialize, parse } from "../Paths";

test("parse()", () => {
const path =
"M150,0 C150,0 0,75 200,75 C75,200 200,225 200,225 C225,200 200,150 0,150 ";
expect(serialize(parse(path))).toBe(path);
});

/*
test("serialize()", () => {
const p1 =
"M150,0 C150,0 0,75 200,75 C75,200 200,225 200,225 C225,200 200,150 0,150 ";
const p2 =
"M150,0 C150,0 0,75 200,75 C75,200 200,225 200,225 C225,200 200,150 0,150 ";
const aPath = interpolatePath(1, [0, 1], [parse(p1), parse(p2)]);
expect(aPath).toBe(p2);
});
*/
11 changes: 6 additions & 5 deletions src/v1/Colors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ const {
cond,
} = Animated;

type Color = Animated.Adaptable<string> | Animated.Adaptable<number>;
// type Color = Animated.Adaptable<string> | Animated.Adaptable<number>;
type StaticColor = string | number;

export const opacity = (c: number) => ((c >> 24) & 255) / 255;
export const red = (c: number) => (c >> 16) & 255;
Expand Down Expand Up @@ -172,7 +173,7 @@ const interpolateColorsRGB = (

interface ColorInterpolationConfig {
inputRange: readonly Animated.Adaptable<number>[];
outputRange: Color[];
outputRange: StaticColor[];
}

export const interpolateColor = (
Expand All @@ -182,7 +183,7 @@ export const interpolateColor = (
): Animated.Node<number> => {
const { inputRange } = config;
const outputRange = config.outputRange.map((c) =>
typeof c === "number" ? c : processColor(c)
typeof c === "number" ? c : (processColor(c) as number)
);
if (colorSpace === "hsv") {
return interpolateColorsHSV(value, inputRange, outputRange);
Expand All @@ -192,8 +193,8 @@ export const interpolateColor = (

export const mixColor = (
value: Animated.Adaptable<number>,
color1: Color,
color2: Color,
color1: StaticColor,
color2: StaticColor,
colorSpace: "hsv" | "rgb" = "rgb"
) =>
interpolateColor(
Expand Down
9 changes: 4 additions & 5 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1671,12 +1671,11 @@
resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.3.tgz#2ab0d5da2e5815f94b0b9d4b95d1e5f243ab2ca7"
integrity sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==

"@types/react-native@^0.60.25":
version "0.60.31"
resolved "https://registry.yarnpkg.com/@types/react-native/-/react-native-0.60.31.tgz#a7af12197f884ad8dd22cda2df9862ed72973ded"
integrity sha512-Y0Q+nv50KHnLL+jM0UH68gQQv7Wt6v2KuNepiHKwK1DoWGVd1oYun/GJCnvUje+/V8pMQQWW6QuBvHZz1pV7tQ==
"@types/react-native@0.63.20":
version "0.63.20"
resolved "https://registry.yarnpkg.com/@types/react-native/-/react-native-0.63.20.tgz#15ccf000bf849d867b15d14d2b4acc364fb7fa27"
integrity sha512-APnxRTDxbWw/IYjvwvXkhYJiz1gahyVA579pJqAVsEfZ+ZUwUHZpWKnexobyH5NmRJHuA/8LrThyps/BW3SYXA==
dependencies:
"@types/prop-types" "*"
"@types/react" "*"

"@types/react@*":
Expand Down

0 comments on commit 2ec4846

Please sign in to comment.