motion-dom
Version:
74 lines (71 loc) • 3.29 kB
JavaScript
import { angleTransforms } from '../utils/has-transform.mjs';
function buildProjectionTransform(delta, treeScale, latestTransform) {
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) `;
}
let angles = "";
if (latestTransform) {
const { transformPerspective } = latestTransform;
if (transformPerspective)
transform = `perspective(${transformPerspective}px) ${transform}`;
for (let i = 0; i < angleTransforms.length; i++) {
const key = angleTransforms[i];
const value = latestTransform[key];
if (value)
angles += `${key}(${value}deg) `;
// Additive `rotate()` so user `rotate` isn't clobbered.
if (!i && latestTransform.pathRotation)
angles += `rotate(${latestTransform.pathRotation}deg) `;
}
}
if (angles) {
/**
* 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}) `;
}
transform += angles;
/**
* 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})`;
}
}
else if (delta.x.scale !== 1 || delta.y.scale !== 1) {
/**
* With no rotation or skew between them, the tree scale correction
* (1 / treeScale) and the element scale (delta.scale * treeScale)
* combine into a single scale. A shorter transform is quicker for
* the browser to parse, which matters when it's set every frame.
*/
transform += `scale(${delta.x.scale}, ${delta.y.scale})`;
}
else if (!transform && (treeScale.x !== 1 || treeScale.y !== 1)) {
/**
* Inside a scaled tree the transform must never be "none", even when
* this element's own delta is the identity: scale correction for
* borderRadius and boxShadow is skipped for "none", and the element
* would gain and lose its stacking context as the delta snaps.
*/
transform = "scale(1, 1)";
}
return transform || "none";
}
export { buildProjectionTransform };
//# sourceMappingURL=transform.mjs.map