| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| |
| import Element, { ElementProps } from 'zrender/src/Element'; |
| import { ZREasing } from './types'; |
| import { AnimationEasing } from 'zrender/src/animation/easing'; |
| |
| interface AnimationWrapStorage { |
| el: Element; |
| target: ElementProps; |
| duration: number; |
| delay: number; |
| easing: AnimationEasing |
| } |
| type AnimationWrapDoneCallback = () => void; |
| |
| /** |
| * Animate multiple elements with a single done-callback. |
| * |
| * @example |
| * animation |
| * .createWrap() |
| * .add(el1, {x: 10, y: 10}) |
| * .add(el2, {shape: {width: 500}, style: {fill: 'red'}}, 400) |
| * .done(function () { // done }) |
| * .start('cubicOut'); |
| */ |
| class AnimationWrap { |
| |
| private _storage = [] as AnimationWrapStorage[]; |
| private _elExistsMap: { [elId: string]: boolean } = {}; |
| private _finishedCallback: AnimationWrapDoneCallback; |
| |
| /** |
| * Caution: a el can only be added once, otherwise 'done' |
| * might not be called. This method checks this (by el.id), |
| * suppresses adding and returns false when existing el found. |
| * |
| * @return Whether adding succeeded. |
| */ |
| add( |
| el: Element, |
| target: ElementProps, |
| duration?: number, |
| delay?: number, |
| easing?: ZREasing |
| ): boolean { |
| if (this._elExistsMap[el.id]) { |
| return false; |
| } |
| this._elExistsMap[el.id] = true; |
| |
| this._storage.push({ |
| el: el, |
| target: target, |
| duration: duration, |
| delay: delay, |
| easing: easing |
| }); |
| |
| return true; |
| } |
| |
| /** |
| * Only execute when animation done/aborted. |
| */ |
| finished(callback: AnimationWrapDoneCallback): AnimationWrap { |
| this._finishedCallback = callback; |
| return this; |
| } |
| |
| /** |
| * Will stop exist animation firstly. |
| */ |
| start(): AnimationWrap { |
| let count = this._storage.length; |
| |
| const checkTerminate = () => { |
| count--; |
| if (count <= 0) { // Guard. |
| this._storage.length = 0; |
| this._elExistsMap = {}; |
| this._finishedCallback && this._finishedCallback(); |
| } |
| }; |
| |
| for (let i = 0, len = this._storage.length; i < len; i++) { |
| const item = this._storage[i]; |
| item.el.animateTo(item.target, { |
| duration: item.duration, |
| delay: item.delay, |
| easing: item.easing, |
| setToFinal: true, |
| done: checkTerminate, |
| aborted: checkTerminate |
| }); |
| } |
| |
| return this; |
| } |
| } |
| |
| export function createWrap(): AnimationWrap { |
| return new AnimationWrap(); |
| } |