securityos/node_modules/framer-motion/dist/es/projection/animation/mix-values.mjs

94 lines
3.7 KiB
JavaScript
Raw Normal View History

2024-09-06 15:32:35 +00:00
import { circOut } from '../../easing/circ.mjs';
import { progress } from '../../utils/progress.mjs';
import { mix } from '../../utils/mix.mjs';
import { noop } from '../../utils/noop.mjs';
import { percent, px } from '../../value/types/numbers/units.mjs';
const borders = ["TopLeft", "TopRight", "BottomLeft", "BottomRight"];
const numBorders = borders.length;
const asNumber = (value) => typeof value === "string" ? parseFloat(value) : value;
const isPx = (value) => typeof value === "number" || px.test(value);
function mixValues(target, follow, lead, progress, shouldCrossfadeOpacity, isOnlyMember) {
if (shouldCrossfadeOpacity) {
target.opacity = mix(0,
// TODO Reinstate this if only child
lead.opacity !== undefined ? lead.opacity : 1, easeCrossfadeIn(progress));
target.opacityExit = mix(follow.opacity !== undefined ? follow.opacity : 1, 0, easeCrossfadeOut(progress));
}
else if (isOnlyMember) {
target.opacity = mix(follow.opacity !== undefined ? follow.opacity : 1, lead.opacity !== undefined ? lead.opacity : 1, progress);
}
/**
* Mix border radius
*/
for (let i = 0; i < numBorders; i++) {
const borderLabel = `border${borders[i]}Radius`;
let followRadius = getRadius(follow, borderLabel);
let leadRadius = getRadius(lead, borderLabel);
if (followRadius === undefined && leadRadius === undefined)
continue;
followRadius || (followRadius = 0);
leadRadius || (leadRadius = 0);
const canMix = followRadius === 0 ||
leadRadius === 0 ||
isPx(followRadius) === isPx(leadRadius);
if (canMix) {
target[borderLabel] = Math.max(mix(asNumber(followRadius), asNumber(leadRadius), progress), 0);
if (percent.test(leadRadius) || percent.test(followRadius)) {
target[borderLabel] += "%";
}
}
else {
target[borderLabel] = leadRadius;
}
}
/**
* Mix rotation
*/
if (follow.rotate || lead.rotate) {
target.rotate = mix(follow.rotate || 0, lead.rotate || 0, progress);
}
}
function getRadius(values, radiusName) {
return values[radiusName] !== undefined
? values[radiusName]
: values.borderRadius;
}
// /**
// * We only want to mix the background color if there's a follow element
// * that we're not crossfading opacity between. For instance with switch
// * AnimateSharedLayout animations, this helps the illusion of a continuous
// * element being animated but also cuts down on the number of paints triggered
// * for elements where opacity is doing that work for us.
// */
// if (
// !hasFollowElement &&
// latestLeadValues.backgroundColor &&
// latestFollowValues.backgroundColor
// ) {
// /**
// * This isn't ideal performance-wise as mixColor is creating a new function every frame.
// * We could probably create a mixer that runs at the start of the animation but
// * the idea behind the crossfader is that it runs dynamically between two potentially
// * changing targets (ie opacity or borderRadius may be animating independently via variants)
// */
// leadState.backgroundColor = followState.backgroundColor = mixColor(
// latestFollowValues.backgroundColor as string,
// latestLeadValues.backgroundColor as string
// )(p)
// }
const easeCrossfadeIn = compress(0, 0.5, circOut);
const easeCrossfadeOut = compress(0.5, 0.95, noop);
function compress(min, max, easing) {
return (p) => {
// Could replace ifs with clamp
if (p < min)
return 0;
if (p > max)
return 1;
return easing(progress(min, max, p));
};
}
export { mixValues };