| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130 |
- import { isNone } from '../../animation/utils/is-none.mjs';
- import { positionalKeys } from '../html/utils/keys-position.mjs';
- import { makeNoneKeyframesAnimatable } from '../html/utils/make-none-animatable.mjs';
- import { KeyframeResolver } from '../utils/KeyframesResolver.mjs';
- import { getVariableValue } from './utils/css-variables-conversion.mjs';
- import { isCSSVariableToken } from './utils/is-css-variable.mjs';
- import { isNumOrPxType, positionalValues } from './utils/unit-conversion.mjs';
- import { findDimensionValueType } from './value-types/dimensions.mjs';
- class DOMKeyframesResolver extends KeyframeResolver {
- constructor(unresolvedKeyframes, onComplete, name, motionValue, element) {
- super(unresolvedKeyframes, onComplete, name, motionValue, element, true);
- }
- readKeyframes() {
- const { unresolvedKeyframes, element, name } = this;
- if (!element || !element.current)
- return;
- super.readKeyframes();
- /**
- * If any keyframe is a CSS variable, we need to find its value by sampling the element
- */
- for (let i = 0; i < unresolvedKeyframes.length; i++) {
- let keyframe = unresolvedKeyframes[i];
- if (typeof keyframe === "string") {
- keyframe = keyframe.trim();
- if (isCSSVariableToken(keyframe)) {
- const resolved = getVariableValue(keyframe, element.current);
- if (resolved !== undefined) {
- unresolvedKeyframes[i] = resolved;
- }
- if (i === unresolvedKeyframes.length - 1) {
- this.finalKeyframe = keyframe;
- }
- }
- }
- }
- /**
- * Resolve "none" values. We do this potentially twice - once before and once after measuring keyframes.
- * This could be seen as inefficient but it's a trade-off to avoid measurements in more situations, which
- * have a far bigger performance impact.
- */
- this.resolveNoneKeyframes();
- /**
- * Check to see if unit type has changed. If so schedule jobs that will
- * temporarily set styles to the destination keyframes.
- * Skip if we have more than two keyframes or this isn't a positional value.
- * TODO: We can throw if there are multiple keyframes and the value type changes.
- */
- if (!positionalKeys.has(name) || unresolvedKeyframes.length !== 2) {
- return;
- }
- const [origin, target] = unresolvedKeyframes;
- const originType = findDimensionValueType(origin);
- const targetType = findDimensionValueType(target);
- /**
- * Either we don't recognise these value types or we can animate between them.
- */
- if (originType === targetType)
- return;
- /**
- * If both values are numbers or pixels, we can animate between them by
- * converting them to numbers.
- */
- if (isNumOrPxType(originType) && isNumOrPxType(targetType)) {
- for (let i = 0; i < unresolvedKeyframes.length; i++) {
- const value = unresolvedKeyframes[i];
- if (typeof value === "string") {
- unresolvedKeyframes[i] = parseFloat(value);
- }
- }
- }
- else {
- /**
- * Else, the only way to resolve this is by measuring the element.
- */
- this.needsMeasurement = true;
- }
- }
- resolveNoneKeyframes() {
- const { unresolvedKeyframes, name } = this;
- const noneKeyframeIndexes = [];
- for (let i = 0; i < unresolvedKeyframes.length; i++) {
- if (isNone(unresolvedKeyframes[i])) {
- noneKeyframeIndexes.push(i);
- }
- }
- if (noneKeyframeIndexes.length) {
- makeNoneKeyframesAnimatable(unresolvedKeyframes, noneKeyframeIndexes, name);
- }
- }
- measureInitialState() {
- const { element, unresolvedKeyframes, name } = this;
- if (!element || !element.current)
- return;
- if (name === "height") {
- this.suspendedScrollY = window.pageYOffset;
- }
- this.measuredOrigin = positionalValues[name](element.measureViewportBox(), window.getComputedStyle(element.current));
- unresolvedKeyframes[0] = this.measuredOrigin;
- // Set final key frame to measure after next render
- const measureKeyframe = unresolvedKeyframes[unresolvedKeyframes.length - 1];
- if (measureKeyframe !== undefined) {
- element.getValue(name, measureKeyframe).jump(measureKeyframe, false);
- }
- }
- measureEndState() {
- const { element, name, unresolvedKeyframes } = this;
- if (!element || !element.current)
- return;
- const value = element.getValue(name);
- value && value.jump(this.measuredOrigin, false);
- const finalKeyframeIndex = unresolvedKeyframes.length - 1;
- const finalKeyframe = unresolvedKeyframes[finalKeyframeIndex];
- unresolvedKeyframes[finalKeyframeIndex] = positionalValues[name](element.measureViewportBox(), window.getComputedStyle(element.current));
- if (finalKeyframe !== null && this.finalKeyframe === undefined) {
- this.finalKeyframe = finalKeyframe;
- }
- // If we removed transform values, reapply them before the next render
- if (this.removedTransforms?.length) {
- this.removedTransforms.forEach(([unsetTransformName, unsetTransformValue]) => {
- element
- .getValue(unsetTransformName)
- .set(unsetTransformValue);
- });
- }
- this.resolveNoneKeyframes();
- }
- }
- export { DOMKeyframesResolver };
|