UNPKG

framer-motion

Version:

A simple and powerful JavaScript animation library

74 lines (71 loc) 3.08 kB
import { getValueTransition, frame } from 'motion-dom'; import { positionalKeys } from '../../render/html/utils/keys-position.mjs'; import { setTarget } from '../../render/utils/setters.mjs'; import { addValueToWillChange } from '../../value/use-will-change/add-will-change.mjs'; import { getOptimisedAppearId } from '../optimized-appear/get-appear-id.mjs'; import { animateMotionValue } from './motion-value.mjs'; /** * Decide whether we should block this animation. Previously, we achieved this * just by checking whether the key was listed in protectedKeys, but this * posed problems if an animation was triggered by afterChildren and protectedKeys * had been set to true in the meantime. */ function shouldBlockAnimation({ protectedKeys, needsAnimating }, key) { const shouldBlock = protectedKeys.hasOwnProperty(key) && needsAnimating[key] !== true; needsAnimating[key] = false; return shouldBlock; } function animateTarget(visualElement, targetAndTransition, { delay = 0, transitionOverride, type } = {}) { let { transition = visualElement.getDefaultTransition(), transitionEnd, ...target } = targetAndTransition; if (transitionOverride) transition = transitionOverride; const animations = []; const animationTypeState = type && visualElement.animationState && visualElement.animationState.getState()[type]; for (const key in target) { const value = visualElement.getValue(key, visualElement.latestValues[key] ?? null); const valueTarget = target[key]; if (valueTarget === undefined || (animationTypeState && shouldBlockAnimation(animationTypeState, key))) { continue; } const valueTransition = { delay, ...getValueTransition(transition || {}, key), }; /** * If this is the first time a value is being animated, check * to see if we're handling off from an existing animation. */ let isHandoff = false; if (window.MotionHandoffAnimation) { const appearId = getOptimisedAppearId(visualElement); if (appearId) { const startTime = window.MotionHandoffAnimation(appearId, key, frame); if (startTime !== null) { valueTransition.startTime = startTime; isHandoff = true; } } } addValueToWillChange(visualElement, key); value.start(animateMotionValue(key, value, valueTarget, visualElement.shouldReduceMotion && positionalKeys.has(key) ? { type: false } : valueTransition, visualElement, isHandoff)); const animation = value.animation; if (animation) { animations.push(animation); } } if (transitionEnd) { Promise.all(animations).then(() => { frame.update(() => { transitionEnd && setTarget(visualElement, transitionEnd); }); }); } return animations; } export { animateTarget };