UNPKG

motion

Version:

The Motion library for the web

153 lines (148 loc) 6.54 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var data = require('./data.cjs.js'); var cssVar = require('./utils/css-var.cjs.js'); var noop = require('../../utils/noop.cjs.js'); var time = require('./utils/time.cjs.js'); var transforms = require('./utils/transforms.cjs.js'); var stopAnimation = require('./utils/stop-animation.cjs.js'); var easing = require('./utils/easing.cjs.js'); var featureDetection = require('./utils/feature-detection.cjs.js'); var apply = require('./utils/apply.cjs.js'); var animateNumber = require('../js/animate-number.cjs.js'); var keyframes = require('./utils/keyframes.cjs.js'); var style = require('./style.cjs.js'); var defaults = require('./utils/defaults.cjs.js'); function animateStyle(element, name, keyframesDefinition, options = {}) { let { duration = defaults.defaults.duration, delay = defaults.defaults.delay, endDelay = defaults.defaults.endDelay, repeat = defaults.defaults.repeat, easing: easing$1 = defaults.defaults.easing, direction, offset, allowWebkitAcceleration = false, } = options; const data$1 = data.getAnimationData(element); let canAnimateNatively = featureDetection.supports.waapi(); let render = noop.noop; const valueIsTransform = transforms.isTransform(name); /** * If this is an individual transform, we need to map its * key to a CSS variable and update the element's transform style */ if (valueIsTransform) { if (transforms.transformAlias[name]) name = transforms.transformAlias[name]; transforms.addTransformToElement(element, name); name = transforms.asTransformCssVar(name); } /** * Get definition of value, this will be used to convert numerical * keyframes into the default value type. */ const definition = transforms.transformPropertyDefinitions.get(name); /** * Replace null values with the previous keyframe value, or read * it from the DOM if it's the first keyframe. * * TODO: This needs to come after the valueIsTransform * check so it can correctly read the underlying value. * Should make a test for this. */ let keyframes$1 = keyframes.hydrateKeyframes(keyframes.keyframesList(keyframesDefinition), element, name); stopCurrentAnimation(data$1, name); /** * If this is a CSS variable we need to register it with the browser * before it can be animated natively. We also set it with setProperty * rather than directly onto the element.style object. */ if (cssVar.isCssVar(name)) { render = apply.createCssVariableRenderer(element, name); if (featureDetection.supports.cssRegisterProperty()) { cssVar.registerCssVariable(name); } else { canAnimateNatively = false; } } else { render = apply.createStyleRenderer(element, name); } let animation; /** * If we can animate this value with WAAPI, do so. Currently this only * feature detects CSS.registerProperty but could check WAAPI too. */ if (canAnimateNatively) { /** * Convert numbers to default value types. Currently this only supports * transforms but it could also support other value types. */ if (definition) { keyframes$1 = keyframes$1.map((value) => typeof value === "number" ? definition.toDefaultUnit(value) : value); } if (!featureDetection.supports.partialKeyframes() && keyframes$1.length === 1) { keyframes$1.unshift(style.style.get(element, name)); } const animationOptions = { delay: time.ms(delay), duration: time.ms(duration), endDelay: time.ms(endDelay), easing: !easing.isEasingList(easing$1) ? easing.convertEasing(easing$1) : undefined, direction, iterations: repeat + 1, }; animation = element.animate({ [name]: keyframes$1, offset, easing: easing.isEasingList(easing$1) ? easing$1.map(easing.convertEasing) : undefined, }, animationOptions); /** * Polyfill finished Promise in browsers that don't support it */ if (!animation.finished) { animation.finished = new Promise((resolve, reject) => { animation.onfinish = resolve; animation.oncancel = reject; }); } const target = keyframes$1[keyframes$1.length - 1]; animation.finished.then(() => render(target)).catch(noop.noop); /** * This forces Webkit to run animations on the main thread by exploiting * this condition: * https://trac.webkit.org/browser/webkit/trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp?rev=281238#L1099 * * This fixes Webkit's timing bugs, like accelerated animations falling * out of sync with main thread animations and massive delays in starting * accelerated animations in WKWebView. */ if (!allowWebkitAcceleration) animation.playbackRate = 1.000001; } else if (valueIsTransform && keyframes$1.every(isNumber)) { if (keyframes$1.length === 1) { keyframes$1.unshift(style.style.get(element, name) || (definition === null || definition === void 0 ? void 0 : definition.initialValue) || 0); } /** * Transform styles are currently only accepted as numbers of * their default value type, so here we loop through and map * them to numbers. */ keyframes$1 = keyframes$1.map((value) => typeof value === "string" ? parseFloat(value) : value); if (definition) { const applyStyle = render; render = (v) => applyStyle(definition.toDefaultUnit(v)); } animation = animateNumber.animateNumber(render, keyframes$1, options); } else { const target = keyframes$1[keyframes$1.length - 1]; render(definition && typeof target === "number" ? definition.toDefaultUnit(target) : target); } data$1.activeAnimations[name] = animation; return animation; } function stopCurrentAnimation(data, name) { if (data.activeAnimations[name]) { stopAnimation.stopAnimation(data.activeAnimations[name]); data.activeAnimations[name] = undefined; } } const isNumber = (value) => typeof value === "number"; exports.animateStyle = animateStyle;