Upstream motiondivision/motion state of the touched files before 46bc6e6fee

This commit is contained in:
upstream committed 2026-09-11 23:06:36 +02:00
commit 1ba1c99cc1
6 files changed
+6391

No files matched your search

@@ -0,0 +1,105 @@
import { buildProjectionTransform } from "../transform"
import { createDelta } from "../../geometry/models"
describe("buildProjectionTransform", () => {
it("Returns 'none' when no transform required", () => {
expect(buildProjectionTransform(createDelta(), { x: 1, y: 1 })).toEqual(
"none"
)
})
it("Creates the expected transform for the provided arguments", () => {
const delta = {
x: {
translate: 100,
scale: 2,
origin: 0.5,
originPoint: 100,
},
y: {
translate: 300,
scale: 4,
origin: 0.5,
originPoint: 100,
},
}
expect(buildProjectionTransform(delta, { x: 1, y: 1 })).toEqual(
"translate3d(100px, 300px, 0px) scale(2, 4)"
)
expect(buildProjectionTransform(delta, { x: 2, y: 0.5 })).toEqual(
"translate3d(50px, 600px, 0px) scale(0.5, 2) scale(4, 2)"
)
expect(
buildProjectionTransform(delta, { x: 2, y: 0.5 }, { rotate: 45 })
).toEqual(
"translate3d(50px, 600px, 0px) scale(0.5, 2) rotate(45deg) scale(4, 2)"
)
expect(
buildProjectionTransform(
{
x: {
translate: 100,
scale: 0.5,
origin: 0.5,
originPoint: 100,
},
y: {
translate: 300,
scale: 0.5,
origin: 0.5,
originPoint: 100,
},
},
{ x: 2, y: 2 },
{ rotate: 90 }
)
).toEqual(
"translate3d(50px, 150px, 0px) scale(0.5, 0.5) rotate(90deg) "
)
})
it("Doesn't apply unneccessary translation", () => {
const delta = {
x: {
translate: 0,
scale: 2,
origin: 0.5,
originPoint: 100,
},
y: {
translate: 0,
scale: 4,
origin: 0.5,
originPoint: 100,
},
}
expect(
buildProjectionTransform(delta, { x: 2, y: 4 }, { rotate: 10 })
).toEqual("scale(0.5, 0.25) rotate(10deg) scale(4, 16)")
})
it("Doesn't apply unneccessary tree scale", () => {
const delta = {
x: {
translate: 100,
scale: 2,
origin: 0.5,
originPoint: 100,
},
y: {
translate: 100,
scale: 4,
origin: 0.5,
originPoint: 100,
},
}
expect(
buildProjectionTransform(delta, { x: 1, y: 1 }, { rotate: 10 })
).toEqual("translate3d(100px, 100px, 0px) rotate(10deg) scale(2, 4)")
})
})
@@ -0,0 +1,64 @@
import type { Delta, Point } from "motion-utils"
import type { ResolvedValues } from "../../node/types"
export function buildProjectionTransform(
delta: Delta,
treeScale: Point,
latestTransform?: ResolvedValues
): string {
let transform = ""
/**
* The translations we use to calculate are always relative to the viewport coordinate space.
* But when we apply scales, we also scale the coordinate space of an element and its children.
* For instance if we have a treeScale (the culmination of all parent scales) of 0.5 and we need
* to move an element 100 pixels, we actually need to move it 200 in within that scaled space.
*/
const xTranslate = delta.x.translate / treeScale.x
const yTranslate = delta.y.translate / treeScale.y
const zTranslate = latestTransform?.z || 0
if (xTranslate || yTranslate || zTranslate) {
transform = `translate3d(${xTranslate}px, ${yTranslate}px, ${zTranslate}px) `
}
/**
* Apply scale correction for the tree transform.
* This will apply scale to the screen-orientated axes.
*/
if (treeScale.x !== 1 || treeScale.y !== 1) {
transform += `scale(${1 / treeScale.x}, ${1 / treeScale.y}) `
}
if (latestTransform) {
const {
transformPerspective,
rotate,
pathRotation,
rotateX,
rotateY,
skewX,
skewY,
} = latestTransform
if (transformPerspective)
transform = `perspective(${transformPerspective}px) ${transform}`
if (rotate) transform += `rotate(${rotate}deg) `
// Additive `rotate()` so user `rotate` isn't clobbered.
if (pathRotation) transform += `rotate(${pathRotation}deg) `
if (rotateX) transform += `rotateX(${rotateX}deg) `
if (rotateY) transform += `rotateY(${rotateY}deg) `
if (skewX) transform += `skewX(${skewX}deg) `
if (skewY) transform += `skewY(${skewY}deg) `
}
/**
* Apply scale to match the size of the element to the size we want it.
* This will apply scale to the element-orientated axes.
*/
const elementScaleX = delta.x.scale * treeScale.x
const elementScaleY = delta.y.scale * treeScale.y
if (elementScaleX !== 1 || elementScaleY !== 1) {
transform += `scale(${elementScaleX}, ${elementScaleY})`
}
return transform || "none"
}