You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
79 lines
2.5 KiB
JavaScript
79 lines
2.5 KiB
JavaScript
var raf = requestAnimationFrame || setTimeout;
|
|
var nextFrame = function(fn) { raf(function() { raf(fn); }); };
|
|
|
|
function setNextFrame(obj, prop, val) {
|
|
nextFrame(function() { obj[prop] = val; });
|
|
}
|
|
|
|
var removed, created;
|
|
|
|
function pre(oldVnode, vnode) {
|
|
removed = {};
|
|
created = [];
|
|
}
|
|
|
|
function create(oldVnode, vnode) {
|
|
var hero = vnode.data.hero;
|
|
if (hero && hero.id) {
|
|
created.push(hero.id);
|
|
created.push(vnode);
|
|
}
|
|
}
|
|
|
|
function destroy(vnode) {
|
|
var hero = vnode.data.hero;
|
|
if (hero && hero.id) {
|
|
removed[hero.id] = vnode;
|
|
}
|
|
}
|
|
|
|
function post() {
|
|
var i, id, newElm, oldVnode, oldElm, hRatio, wRatio,
|
|
oldRect, newRect, dx, dy, origTransform, origTransition,
|
|
newStyle, oldStyle;
|
|
for (i = 0; i < created.length; i += 2) {
|
|
id = created[i];
|
|
newElm = created[i+1].elm;
|
|
oldVnode = removed[id];
|
|
if (oldVnode) {
|
|
newStyle = newElm.style;
|
|
oldElm = oldVnode.elm;
|
|
oldStyle = oldElm.style;
|
|
newRect = newElm.getBoundingClientRect();
|
|
oldRect = oldElm.getBoundingClientRect();
|
|
dx = oldRect.left - newRect.left;
|
|
dy = oldRect.top - newRect.top;
|
|
wRatio = newRect.width / (Math.max(oldRect.width, 1));
|
|
hRatio = newRect.height / (Math.max(oldRect.height, 1));
|
|
// Animate new element
|
|
origTransform = newStyle.transform;
|
|
origTransition = newStyle.transition;
|
|
newStyle.transition = origTransition + 'transform 0s';
|
|
newStyle.transformOrigin = '0 0';
|
|
newStyle.opacity = '0';
|
|
newStyle.transform = origTransform + 'translate('+dx+'px, '+dy+'px) ' +
|
|
'scale('+1/wRatio+', '+1/hRatio+')';
|
|
setNextFrame(newStyle, 'transition', origTransition);
|
|
setNextFrame(newStyle, 'transform', origTransform);
|
|
setNextFrame(newStyle, 'opacity', '1');
|
|
// Animate old element
|
|
oldStyle.position = 'absolute';
|
|
oldStyle.top = newRect.top + 'px';
|
|
oldStyle.left = newRect.left + 'px';
|
|
oldStyle.transformOrigin = '0 0';
|
|
oldStyle.transform = 'translate('+dx+'px, '+dy+'px)';
|
|
oldStyle.opacity = '1';
|
|
document.body.appendChild(oldElm);
|
|
setNextFrame(oldStyle, 'transform', 'scale('+wRatio+', '+hRatio+')');
|
|
setNextFrame(oldStyle, 'opacity', '0');
|
|
oldElm.addEventListener('transitionend', function(ev) {
|
|
if (ev.propertyName === 'transform')
|
|
document.body.removeChild(ev.target);
|
|
});
|
|
}
|
|
}
|
|
removed = created = undefined;
|
|
}
|
|
|
|
module.exports = {pre: pre, create: create, destroy: destroy, post: post};
|