From 86e061aab097f28c7322e7632aa4e9aee14fa21e Mon Sep 17 00:00:00 2001 From: William Candillon Date: Sun, 29 Aug 2021 12:52:47 +0200 Subject: [PATCH] =?UTF-8?q?fix(=F0=9F=A7=AE):=20Fix=202d=20transform=20typ?= =?UTF-8?q?e=20(#464)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Matrix3.ts | 134 ++++++++++++++++++++++++++-------- src/Transforms.ts | 15 ++++ src/__tests__/Matrix3.test.ts | 2 +- tsconfig.json | 2 +- 4 files changed, 120 insertions(+), 33 deletions(-) diff --git a/src/Matrix3.ts b/src/Matrix3.ts index 273dc6b..2151b5b 100644 --- a/src/Matrix3.ts +++ b/src/Matrix3.ts @@ -5,24 +5,22 @@ export type Vec3 = readonly [number, number, number]; export type Matrix3 = readonly [Vec3, Vec3, Vec3]; -type Transform2dName = - | "translateX" - | "translateY" - | "scale" - | "skewX" - | "skewY" - | "scaleX" - | "scaleY" - | "rotateZ" - | "rotate"; - export interface TransformProp { transform: Transforms2d; } type Transformations = { - [Name in Transform2dName]: number; + translateX: number; + translateY: number; + scale: number; + skewX: string; + skewY: string; + scaleX: number; + scaleY: number; + rotateZ: string; + rotate: string; }; + export type Transforms2d = ( | Pick | Pick @@ -32,9 +30,82 @@ export type Transforms2d = ( | Pick | Pick | Pick + | Pick )[]; +export const parseAngle = (angle: string) => { + "worklet"; + if (angle.endsWith("deg")) { + return parseFloat(angle) * (Math.PI / 180); + } + return parseFloat(angle); +}; + +export const isTranslateX = ( + transform: Transforms2d[0] +): transform is Pick => { + "worklet"; + return Object.keys(transform).indexOf("translateX") !== -1; +}; + +export const isTranslateY = ( + transform: Transforms2d[0] +): transform is Pick => { + "worklet"; + return Object.keys(transform).indexOf("translateY") !== -1; +}; + +export const isScale = ( + transform: Transforms2d[0] +): transform is Pick => { + "worklet"; + return Object.keys(transform).indexOf("scale") !== -1; +}; + +export const isScaleX = ( + transform: Transforms2d[0] +): transform is Pick => { + "worklet"; + return Object.keys(transform).indexOf("scaleX") !== -1; +}; + +export const isScaleY = ( + transform: Transforms2d[0] +): transform is Pick => { + "worklet"; + return Object.keys(transform).indexOf("scaleY") !== -1; +}; + +export const isSkewX = ( + transform: Transforms2d[0] +): transform is Pick => { + "worklet"; + return Object.keys(transform).indexOf("skewX") !== -1; +}; + +export const isSkewY = ( + transform: Transforms2d[0] +): transform is Pick => { + "worklet"; + return Object.keys(transform).indexOf("skewY") !== -1; +}; + +export const isRotate = ( + transform: Transforms2d[0] +): transform is Pick => { + "worklet"; + return Object.keys(transform).indexOf("rotate") !== -1; +}; + +export const isRotateZ = ( + transform: Transforms2d[0] +): transform is Pick => { + "worklet"; + return Object.keys(transform).indexOf("rotateZ") !== -1; +}; + const exhaustiveCheck = (a: never): never => { + "worklet"; throw new Error(`Unexhaustive handling for ${a}`); }; @@ -151,33 +222,34 @@ export const serializeToSVGMatrix = (m: Matrix3) => { export const processTransform2d = (transforms: Transforms2d) => { "worklet"; return transforms.reduce((acc, transform) => { - const key = Object.keys(transform)[0] as Transform2dName; - const value = (transform as Pick)[key]; - if (key === "translateX") { - return multiply3(acc, translateXMatrix(value)); + if (isTranslateX(transform)) { + return multiply3(acc, translateXMatrix(transform.translateX)); + } + if (isTranslateY(transform)) { + return multiply3(acc, translateYMatrix(transform.translateY)); } - if (key === "translateY") { - return multiply3(acc, translateYMatrix(value)); + if (isScale(transform)) { + return multiply3(acc, scaleMatrix(transform.scale)); } - if (key === "scale") { - return multiply3(acc, scaleMatrix(value)); + if (isScaleX(transform)) { + return multiply3(acc, scaleXMatrix(transform.scaleX)); } - if (key === "scaleX") { - return multiply3(acc, scaleXMatrix(value)); + if (isScaleY(transform)) { + return multiply3(acc, scaleYMatrix(transform.scaleY)); } - if (key === "scaleY") { - return multiply3(acc, scaleYMatrix(value)); + if (isSkewX(transform)) { + return multiply3(acc, skewXMatrix(parseAngle(transform.skewX))); } - if (key === "skewX") { - return multiply3(acc, skewXMatrix(value)); + if (isSkewY(transform)) { + return multiply3(acc, skewYMatrix(parseAngle(transform.skewY))); } - if (key === "skewY") { - return multiply3(acc, skewYMatrix(value)); + if (isRotate(transform)) { + return multiply3(acc, rotateZMatrix(parseAngle(transform.rotate))); } - if (key === "rotate" || key === "rotateZ") { - return multiply3(acc, rotateZMatrix(value)); + if (isRotateZ(transform)) { + return multiply3(acc, rotateZMatrix(parseAngle(transform.rotateZ))); } - return exhaustiveCheck(key); + return exhaustiveCheck(transform); }, identityMatrix); }; diff --git a/src/Transforms.ts b/src/Transforms.ts index 906bbf5..b2ceccc 100644 --- a/src/Transforms.ts +++ b/src/Transforms.ts @@ -1,6 +1,7 @@ import type { TransformsStyle } from "react-native"; import type { Vector } from "./Vectors"; +import type { Transforms2d } from "./Matrix3"; type RNTransform = Exclude; @@ -17,3 +18,17 @@ export const transformOrigin = ( { translateY: -y }, ]; }; + +export const transformOrigin2d = ( + { x, y }: Vector, + transformations: Transforms2d +): Transforms2d => { + "worklet"; + return [ + { translateX: x }, + { translateY: y }, + ...transformations, + { translateX: -x }, + { translateY: -y }, + ]; +}; diff --git a/src/__tests__/Matrix3.test.ts b/src/__tests__/Matrix3.test.ts index 691eaec..7602048 100644 --- a/src/__tests__/Matrix3.test.ts +++ b/src/__tests__/Matrix3.test.ts @@ -8,7 +8,7 @@ test("processTransform3d()", () => { processTransform2d([ { translateX: width / 2 }, { translateY: height / 2 }, - { rotate: Math.PI / 2 }, + { rotate: `${Math.PI / 2}rad` }, { translateX: -width / 2 }, { translateY: -height / 2 }, ]) diff --git a/tsconfig.json b/tsconfig.json index f7b3aec..7cbe634 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,6 +1,6 @@ { "compilerOptions": { - "target": "es2017", + "target": "esnext", "lib": ["es6"], "jsx": "react-native", "strict": true,