just-animate
Version:
_Making Animation Simple_
102 lines (101 loc) • 3.32 kB
JavaScript
import { interpolator } from '../lib/core/interpolate';
import { _ } from '../lib/utils/constants';
import { isDOM } from '../lib/utils/inspect';
import { hyphenate } from '../lib/utils/strings';
import { includes } from '../lib/utils/lists';
const PROPERTY = 0;
const ATTRIBUTE = 1;
const ATTRIBUTE_HYPHENATE = 2;
const CSSVAR = 3;
const cssVarExp = /^\-\-[a-z0-9\-]+$/i;
const viewbox = 'viewBox';
const svgReadonly = 'rx ry viewBox transform x x1 x2 y y1 y2'.split(' ');
const noHyphenate = [viewbox];
export const propsPlugin = {
name: 'props',
animate(effect) {
const { target, prop } = effect;
const interpolate = interpolator(effect.to - effect.from, effect.keyframes);
const propSetter = getTargetSetter(target, prop);
const propGetter = getTargetGetter(target, prop);
let initial = _;
return {
cancel() {
if (initial !== _) {
propSetter(initial);
}
initial = _;
},
update(localTime, _playbackRate, _isActive) {
if (initial === _) {
initial = propGetter();
}
propSetter(interpolate(localTime));
}
};
},
getValue(target, prop) {
return getTargetGetter(target, prop)();
}
};
function getTargetType(target, prop) {
if (!isDOM(target)) {
return PROPERTY;
}
if (cssVarExp.test(prop)) {
return CSSVAR;
}
if (typeof target[prop] !== 'undefined' && !includes(svgReadonly, prop)) {
return PROPERTY;
}
if (includes(noHyphenate, prop)) {
return ATTRIBUTE;
}
return ATTRIBUTE_HYPHENATE;
}
function getTargetGetter(target, prop) {
const targetType = getTargetType(target, prop);
return targetType === CSSVAR
? getVariable(target, prop)
: targetType === ATTRIBUTE
? getAttribute(target, prop)
: targetType === ATTRIBUTE_HYPHENATE
? getAttributeHyphenate(target, prop)
: getProperty(target, prop);
}
function getTargetSetter(target, prop) {
const targetType = getTargetType(target, prop);
return targetType === CSSVAR
? setVariable(target, prop)
: targetType === ATTRIBUTE
? setAttribute(target, prop)
: targetType === ATTRIBUTE_HYPHENATE
? setAttributeHyphenate(target, prop)
: setProperty(target, prop);
}
function getAttribute(target, name) {
return () => target.getAttribute(name);
}
function setAttribute(target, name) {
return (value) => target.setAttribute(name, value);
}
function setAttributeHyphenate(target, name) {
const attName = hyphenate(name);
return (value) => target.setAttribute(attName, value);
}
function getAttributeHyphenate(target, name) {
const attName = hyphenate(name);
return () => target.getAttribute(attName);
}
function getVariable(target, name) {
return () => target.style.getPropertyValue(name);
}
function setVariable(target, name) {
return (value) => target.style.setProperty(name, value ? value + '' : '');
}
function setProperty(target, name) {
return (value) => (target[name] = value);
}
function getProperty(target, name) {
return () => target[name];
}