Upstream motiondivision/motion state of the touched files before 46bc6e6fee
This commit is contained in:
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"
|
||||
}
|
||||
Reference in new issue
Block a user