UNPKG

devextreme

Version:

HTML5 JavaScript Component Suite for Responsive Web Development

207 lines (201 loc) • 7.18 kB
/** * DevExtreme (viz/core/renderers/animation.js) * Version: 18.2.18 * Build date: Tue Oct 18 2022 * * Copyright (c) 2012 - 2022 Developer Express Inc. ALL RIGHTS RESERVED * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/ */ "use strict"; var animationFrame = require("../../../animation/frame"), noop = function() {}, easingFunctions = { easeOutCubic: function(pos, start, end) { return 1 === pos ? end : (1 - Math.pow(1 - pos, 3)) * (end - start) + +start }, linear: function(pos, start, end) { return 1 === pos ? end : pos * (end - start) + +start } }; exports.easingFunctions = easingFunctions; var animationSvgStep = { segments: function segments(elem, params, progress, easing, currentParams) { var curSeg, seg, i, j, from = params.from, to = params.to, segments = []; for (i = 0; i < from.length; i++) { curSeg = from[i]; seg = [curSeg[0]]; if (curSeg.length > 1) { for (j = 1; j < curSeg.length; j++) { seg.push(easing(progress, curSeg[j], to[i][j])) } } segments.push(seg) } currentParams.segments = params.end && 1 === progress ? params.end : segments; elem.attr({ segments: segments }) }, arc: function(elem, params, progress, easing) { var from = params.from, to = params.to, current = {}; for (var i in from) { current[i] = easing(progress, from[i], to[i]) } elem.attr(current) }, transform: function(elem, params, progress, easing, currentParams) { var from = params.from, to = params.to, current = {}; for (var i in from) { current[i] = currentParams[i] = easing(progress, from[i], to[i]) } elem.attr(current) }, base: function(elem, params, progress, easing, currentParams, attributeName) { var obj = {}; obj[attributeName] = currentParams[attributeName] = easing(progress, params.from, params.to); elem.attr(obj) }, _: noop, complete: function(element, currentSettings) { element.attr(currentSettings) } }; function step(now) { var attrName, that = this, animateStep = that._animateStep; that._progress = that._calcProgress(now); for (attrName in that.params) { var anim = animateStep[attrName] || animateStep.base; anim(that.element, that.params[attrName], that._progress, that._easing, that._currentParams, attrName) } that.options.step && that.options.step(that._easing(that._progress, 0, 1), that._progress); if (1 === that._progress) { return that.stop() } return true } function delayTick(now) { if (now - this._startTime >= this.delay) { this.tick = step } return true } function start(now) { this._startTime = now; this.tick = this.delay ? delayTick : step; return true } function Animation(element, params, options) { var that = this; that._progress = 0; that.element = element; that.params = params; that.options = options; that.duration = options.partitionDuration ? options.duration * options.partitionDuration : options.duration; that.delay = options.delay && options.duration * options.delay || 0; that._animateStep = options.animateStep || animationSvgStep; that._easing = easingFunctions[options.easing] || easingFunctions.easeOutCubic; that._currentParams = {}; that.tick = start } Animation.prototype = { _calcProgress: function(now) { return Math.min(1, (now - this.delay - this._startTime) / this.duration) }, stop: function(disableComplete) { var that = this, options = that.options, animateStep = that._animateStep; that.stop = that.tick = noop; animateStep.complete && animateStep.complete(that.element, that._currentParams); options.complete && !disableComplete && options.complete() } }; function AnimationController(element) { var that = this; that._animationCount = 0; that._timerId = null; that._animations = {}; that.element = element } exports.AnimationController = AnimationController; AnimationController.prototype = { _loop: function() { var an, that = this, animations = that._animations, activeAnimation = 0, now = (new Date).getTime(), endAnimation = that._endAnimation; for (an in animations) { if (!animations[an].tick(now)) { delete animations[an] } activeAnimation++ } if (0 === activeAnimation) { that.stop(); that._endAnimationTimer = endAnimation && setTimeout(function() { if (0 === that._animationCount) { endAnimation(); that._endAnimation = null } }); return } that._timerId = animationFrame.requestAnimationFrame.call(null, function() { that._loop() }, that.element) }, addAnimation: function(animation) { var that = this; that._animations[that._animationCount++] = animation; clearTimeout(that._endAnimationTimer); if (!that._timerId) { clearTimeout(that._startDelay); that._startDelay = setTimeout(function() { that._timerId = 1; that._loop() }, 0) } }, animateElement: function(elem, params, options) { if (elem && params && options) { elem.animation && elem.animation.stop(); this.addAnimation(elem.animation = new Animation(elem, params, options)) } }, onEndAnimation: function(endAnimation) { this._animationCount ? this._endAnimation = endAnimation : endAnimation() }, dispose: function() { this.stop(); this.element = null }, stop: function() { var that = this; that._animations = {}; that._animationCount = 0; animationFrame.cancelAnimationFrame(that._timerId); clearTimeout(that._startDelay); clearTimeout(that._endAnimationTimer); that._timerId = null }, lock: function() { var an, unstoppable, hasUnstoppableInAnimations, animations = this._animations; for (an in animations) { unstoppable = animations[an].options.unstoppable; hasUnstoppableInAnimations = hasUnstoppableInAnimations || unstoppable; if (!unstoppable) { animations[an].stop(true); delete animations[an] } }!hasUnstoppableInAnimations && this.stop() } }; exports.animationSvgStep = animationSvgStep;