UNPKG

motion-dom

Version:
74 lines (71 loc) • 3.29 kB
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