123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175 |
- import { getRect, css, matrix, isRectEqual, indexOfObject } from './utils.js';
- import Sortable from './Sortable.js';
- export default function AnimationStateManager() {
- let animationStates = [],
- animationCallbackId;
- return {
- captureAnimationState() {
- animationStates = [];
- if (!this.options.animation) return;
- let children = [].slice.call(this.el.children);
- children.forEach(child => {
- if (css(child, 'display') === 'none' || child === Sortable.ghost) return;
- animationStates.push({
- target: child,
- rect: getRect(child)
- });
- let fromRect = { ...animationStates[animationStates.length - 1].rect };
- // If animating: compensate for current animation
- if (child.thisAnimationDuration) {
- let childMatrix = matrix(child, true);
- if (childMatrix) {
- fromRect.top -= childMatrix.f;
- fromRect.left -= childMatrix.e;
- }
- }
- child.fromRect = fromRect;
- });
- },
- addAnimationState(state) {
- animationStates.push(state);
- },
- removeAnimationState(target) {
- animationStates.splice(indexOfObject(animationStates, { target }), 1);
- },
- animateAll(callback) {
- if (!this.options.animation) {
- clearTimeout(animationCallbackId);
- if (typeof(callback) === 'function') callback();
- return;
- }
- let animating = false,
- animationTime = 0;
- animationStates.forEach((state) => {
- let time = 0,
- animatingThis = false,
- target = state.target,
- fromRect = target.fromRect,
- toRect = getRect(target),
- prevFromRect = target.prevFromRect,
- prevToRect = target.prevToRect,
- animatingRect = state.rect,
- targetMatrix = matrix(target, true);
- if (targetMatrix) {
- // Compensate for current animation
- toRect.top -= targetMatrix.f;
- toRect.left -= targetMatrix.e;
- }
- target.toRect = toRect;
- if (target.thisAnimationDuration) {
- // Could also check if animatingRect is between fromRect and toRect
- if (
- isRectEqual(prevFromRect, toRect) &&
- !isRectEqual(fromRect, toRect) &&
- // Make sure animatingRect is on line between toRect & fromRect
- (animatingRect.top - toRect.top) /
- (animatingRect.left - toRect.left) ===
- (fromRect.top - toRect.top) /
- (fromRect.left - toRect.left)
- ) {
- // If returning to same place as started from animation and on same axis
- time = calculateRealTime(animatingRect, prevFromRect, prevToRect, this.options);
- }
- }
- // if fromRect != toRect: animate
- if (!isRectEqual(toRect, fromRect)) {
- target.prevFromRect = fromRect;
- target.prevToRect = toRect;
- if (!time) {
- time = this.options.animation;
- }
- this.animate(
- target,
- animatingRect,
- toRect,
- time
- );
- }
- if (time) {
- animating = true;
- animationTime = Math.max(animationTime, time);
- clearTimeout(target.animationResetTimer);
- target.animationResetTimer = setTimeout(function() {
- target.animationTime = 0;
- target.prevFromRect = null;
- target.fromRect = null;
- target.prevToRect = null;
- target.thisAnimationDuration = null;
- }, time);
- target.thisAnimationDuration = time;
- }
- });
- clearTimeout(animationCallbackId);
- if (!animating) {
- if (typeof(callback) === 'function') callback();
- } else {
- animationCallbackId = setTimeout(function() {
- if (typeof(callback) === 'function') callback();
- }, animationTime);
- }
- animationStates = [];
- },
- animate(target, currentRect, toRect, duration) {
- if (duration) {
- css(target, 'transition', '');
- css(target, 'transform', '');
- let elMatrix = matrix(this.el),
- scaleX = elMatrix && elMatrix.a,
- scaleY = elMatrix && elMatrix.d,
- translateX = (currentRect.left - toRect.left) / (scaleX || 1),
- translateY = (currentRect.top - toRect.top) / (scaleY || 1);
- target.animatingX = !!translateX;
- target.animatingY = !!translateY;
- css(target, 'transform', 'translate3d(' + translateX + 'px,' + translateY + 'px,0)');
- repaint(target); // repaint
- css(target, 'transition', 'transform ' + duration + 'ms' + (this.options.easing ? ' ' + this.options.easing : ''));
- css(target, 'transform', 'translate3d(0,0,0)');
- (typeof target.animated === 'number') && clearTimeout(target.animated);
- target.animated = setTimeout(function () {
- css(target, 'transition', '');
- css(target, 'transform', '');
- target.animated = false;
- target.animatingX = false;
- target.animatingY = false;
- }, duration);
- }
- }
- };
- }
- function repaint(target) {
- return target.offsetWidth;
- }
- function calculateRealTime(animatingRect, fromRect, toRect, options) {
- return (
- Math.sqrt(Math.pow(fromRect.top - animatingRect.top, 2) + Math.pow(fromRect.left - animatingRect.left, 2)) /
- Math.sqrt(Math.pow(fromRect.top - toRect.top, 2) + Math.pow(fromRect.left - toRect.left, 2))
- ) * options.animation;
- }
|