UNPKG

svelte-motion

Version:

Svelte animation library based on the React library framer-motion.

112 lines (109 loc) 4.08 kB
/** based on framer-motion@4.0.3, Copyright (c) 2018 Framer B.V. */ import {fixed} from '../../../utils/fix-process-env'; import { complex, px } from 'style-value-types'; import { mix } from 'popmotion'; import { cssVariableRegex } from '../utils/css-variables-conversion.js'; function pixelsToPercent(pixels, axis) { return (pixels / (axis.max - axis.min)) * 100; } /** * We always correct borderRadius as a percentage rather than pixels to reduce paints. * For example, if you are projecting a box that is 100px wide with a 10px borderRadius * into a box that is 200px wide with a 20px borderRadius, that is actually a 10% * borderRadius in both states. If we animate between the two in pixels that will trigger * a paint each time. If we animate between the two in percentage we'll avoid a paint. */ function correctBorderRadius(latest, _layoutState, _a) { var target = _a.target; /** * If latest is a string, if it's a percentage we can return immediately as it's * going to be stretched appropriately. Otherwise, if it's a pixel, convert it to a number. */ if (typeof latest === "string") { if (px.test(latest)) { latest = parseFloat(latest); } else { return latest; } } /** * If latest is a number, it's a pixel value. We use the current viewportBox to calculate that * pixel value as a percentage of each axis */ var x = pixelsToPercent(latest, target.x); var y = pixelsToPercent(latest, target.y); return x + "% " + y + "%"; } var varToken = "_$css"; function correctBoxShadow(latest, _a) { var delta = _a.delta, treeScale = _a.treeScale; var original = latest; /** * We need to first strip and store CSS variables from the string. */ var containsCSSVariables = latest.includes("var("); var cssVariables = []; if (containsCSSVariables) { latest = latest.replace(cssVariableRegex, function (match) { cssVariables.push(match); return varToken; }); } var shadow = complex.parse(latest); // TODO: Doesn't support multiple shadows if (shadow.length > 5) return original; var template = complex.createTransformer(latest); var offset = typeof shadow[0] !== "number" ? 1 : 0; // Calculate the overall context scale var xScale = delta.x.scale * treeScale.x; var yScale = delta.y.scale * treeScale.y; shadow[0 + offset] /= xScale; shadow[1 + offset] /= yScale; /** * Ideally we'd correct x and y scales individually, but because blur and * spread apply to both we have to take a scale average and apply that instead. * We could potentially improve the outcome of this by incorporating the ratio between * the two scales. */ var averageScale = mix(xScale, yScale, 0.5); // Blur if (typeof shadow[2 + offset] === "number") shadow[2 + offset] /= averageScale; // Spread if (typeof shadow[3 + offset] === "number") shadow[3 + offset] /= averageScale; var output = template(shadow); if (containsCSSVariables) { var i_1 = 0; output = output.replace(varToken, function () { var cssVariable = cssVariables[i_1]; i_1++; return cssVariable; }); } return output; } var borderCorrectionDefinition = { process: correctBorderRadius, }; var defaultScaleCorrectors = { borderRadius: Object.assign(Object.assign({}, borderCorrectionDefinition), { applyTo: [ "borderTopLeftRadius", "borderTopRightRadius", "borderBottomLeftRadius", "borderBottomRightRadius", ] }), borderTopLeftRadius: borderCorrectionDefinition, borderTopRightRadius: borderCorrectionDefinition, borderBottomLeftRadius: borderCorrectionDefinition, borderBottomRightRadius: borderCorrectionDefinition, boxShadow: { process: correctBoxShadow, }, }; export { correctBorderRadius, correctBoxShadow, defaultScaleCorrectors, pixelsToPercent };