123 lines
3.0 KiB
JavaScript
123 lines
3.0 KiB
JavaScript
// Leveraging SMIL Animations
|
|
|
|
import { REPLACE_ALL_NEW_DUR } from './animate';
|
|
|
|
const EASING = {
|
|
ease: "0.25 0.1 0.25 1",
|
|
linear: "0 0 1 1",
|
|
// easein: "0.42 0 1 1",
|
|
easein: "0.1 0.8 0.2 1",
|
|
easeout: "0 0 0.58 1",
|
|
easeinout: "0.42 0 0.58 1"
|
|
};
|
|
|
|
function animateSVGElement(element, props, dur, easingType="linear", type=undefined, oldValues={}) {
|
|
|
|
let animElement = element.cloneNode(true);
|
|
let newElement = element.cloneNode(true);
|
|
|
|
for(var attributeName in props) {
|
|
let animateElement;
|
|
if(attributeName === 'transform') {
|
|
animateElement = document.createElementNS("http://www.w3.org/2000/svg", "animateTransform");
|
|
} else {
|
|
animateElement = document.createElementNS("http://www.w3.org/2000/svg", "animate");
|
|
}
|
|
let currentValue = oldValues[attributeName] || element.getAttribute(attributeName);
|
|
let value = props[attributeName];
|
|
|
|
let animAttr = {
|
|
attributeName: attributeName,
|
|
from: currentValue,
|
|
to: value,
|
|
begin: "0s",
|
|
dur: dur/1000 + "s",
|
|
values: currentValue + ";" + value,
|
|
keySplines: EASING[easingType],
|
|
keyTimes: "0;1",
|
|
calcMode: "spline",
|
|
fill: 'freeze'
|
|
};
|
|
|
|
if(type) {
|
|
animAttr["type"] = type;
|
|
}
|
|
|
|
for (var i in animAttr) {
|
|
animateElement.setAttribute(i, animAttr[i]);
|
|
}
|
|
|
|
animElement.appendChild(animateElement);
|
|
|
|
if(type) {
|
|
newElement.setAttribute(attributeName, `translate(${value})`);
|
|
} else {
|
|
newElement.setAttribute(attributeName, value);
|
|
}
|
|
}
|
|
|
|
return [animElement, newElement];
|
|
}
|
|
|
|
export function transform(element, style) { // eslint-disable-line no-unused-vars
|
|
element.style.transform = style;
|
|
element.style.webkitTransform = style;
|
|
element.style.msTransform = style;
|
|
element.style.mozTransform = style;
|
|
element.style.oTransform = style;
|
|
}
|
|
|
|
function animateSVG(svgContainer, elements) {
|
|
let newElements = [];
|
|
let animElements = [];
|
|
|
|
elements.map(element => {
|
|
let obj = element[0];
|
|
let parent = obj.unit.parentNode;
|
|
|
|
let animElement, newElement;
|
|
|
|
element[0] = obj.unit;
|
|
[animElement, newElement] = animateSVGElement(...element);
|
|
|
|
newElements.push(newElement);
|
|
animElements.push([animElement, parent]);
|
|
|
|
parent.replaceChild(animElement, obj.unit);
|
|
|
|
if(obj.array) {
|
|
obj.array[obj.index] = newElement;
|
|
} else {
|
|
obj.object[obj.key] = newElement;
|
|
}
|
|
});
|
|
|
|
let animSvg = svgContainer.cloneNode(true);
|
|
|
|
animElements.map((animElement, i) => {
|
|
animElement[1].replaceChild(newElements[i], animElement[0]);
|
|
elements[i][0] = newElements[i];
|
|
});
|
|
|
|
return animSvg;
|
|
}
|
|
|
|
export function runSMILAnimation(parent, svgElement, elementsToAnimate) {
|
|
if(elementsToAnimate.length === 0) return;
|
|
|
|
let animSvgElement = animateSVG(svgElement, elementsToAnimate);
|
|
if(svgElement.parentNode == parent) {
|
|
parent.removeChild(svgElement);
|
|
parent.appendChild(animSvgElement);
|
|
|
|
}
|
|
|
|
// Replace the new svgElement (data has already been replaced)
|
|
setTimeout(() => {
|
|
if(animSvgElement.parentNode == parent) {
|
|
parent.removeChild(animSvgElement);
|
|
parent.appendChild(svgElement);
|
|
}
|
|
}, REPLACE_ALL_NEW_DUR);
|
|
}
|