@antv/x6
Version:
JavaScript diagramming library that uses SVG and HTML for rendering
172 lines • 6.24 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Animation = void 0;
const common_1 = require("../../common");
const animationEvent_1 = require("./animationEvent");
const utils_1 = require("./utils");
/**
* Web Animation API 的 Animation 实现,功能完善实现中
* 参考: https://developer.mozilla.org/en-US/docs/Web/API/Animation
*/
class Animation {
constructor(effect, timeline) {
this._effect = null;
this._currentTime = null;
this._playbackRate = 1;
this._playState = 'idle';
this._rafId = null;
this._startTime = null;
this._pausedTime = null;
this._timeline = null;
this.id = '';
this.onfinish = null;
this.oncancel = null;
this._effect = effect;
this._timeline = timeline !== null && timeline !== void 0 ? timeline : document.timeline;
}
get effect() {
return this._effect;
}
get currentTime() {
return this._currentTime;
}
set currentTime(value) {
const now = this._timeline.currentTime;
if (!common_1.NumberExt.isNumber(now))
return;
this._startTime = now - value;
this._currentTime = value;
}
get playbackRate() {
return this._playbackRate;
}
set playbackRate(value) {
const oldRate = this._playbackRate;
this._playbackRate = value;
const now = this._timeline.currentTime;
// 如果正在运行,调整开始时间以保持视觉连续性
if (this._playState === 'running' &&
this._startTime != null &&
common_1.NumberExt.isNumber(now)) {
const currentTime = (now - this._startTime) * oldRate;
this._startTime = now - currentTime / value;
}
}
get playState() {
return this._playState;
}
get timeline() {
return this._timeline;
}
play() {
if (this._playState === 'running' || !this._effect)
return;
const now = this._timeline.currentTime;
if (!common_1.NumberExt.isNumber(now))
return;
if (this._playState === 'paused') {
// 从暂停状态恢复
this._startTime = now - this._pausedTime / this._playbackRate;
this._pausedTime = null;
}
else {
// 新开始播放
this._currentTime = 0;
this._startTime = now;
}
this._playState = 'running';
this._tick();
}
pause() {
if (this._playState !== 'running')
return;
if (this._rafId) {
cancelAnimationFrame(this._rafId);
this._rafId = null;
}
this._pausedTime = this._currentTime;
this._playState = 'paused';
}
finish() {
var _a;
if (!this._effect)
return;
const timing = this._effect.getComputedTiming();
const reversePlaybackRate = this._playbackRate < 0;
const { duration, endTime, direction, fill, iterations } = timing;
// 根据 fill 模式设置最终状态
if (fill === 'forwards' || fill === 'both') {
const lastIteration = reversePlaybackRate ? 0 : iterations - 1;
const reverseDirection = (0, utils_1.isReverseDirection)(direction, lastIteration);
this._effect.apply(reverseDirection || reversePlaybackRate ? 0 : duration);
}
// 清除所有动画效果
else if (fill === 'none' || fill === 'backwards') {
this._effect.apply(null);
}
this._currentTime = reversePlaybackRate ? 0 : endTime;
this._playState = 'finished';
if (this._rafId) {
cancelAnimationFrame(this._rafId);
this._rafId = null;
}
const event = new animationEvent_1.AnimationPlaybackEvent(this, 'finish', this._currentTime, this._timeline.currentTime);
(_a = this.onfinish) === null || _a === void 0 ? void 0 : _a.call(this, event);
this._effect.target.notify('animation:finish', event);
}
cancel() {
var _a;
if (!this._effect)
return;
if (this._rafId) {
cancelAnimationFrame(this._rafId);
this._rafId = null;
}
this._playState = 'idle';
this._currentTime = null;
this._startTime = null;
this._pausedTime = null;
this._effect.apply(null);
const event = new animationEvent_1.AnimationPlaybackEvent(this, 'cancel', this._currentTime, this._timeline.currentTime);
(_a = this.oncancel) === null || _a === void 0 ? void 0 : _a.call(this, event);
this._effect.target.notify('animation:cancel', event);
}
updatePlaybackRate(playbackRate) {
this.playbackRate = playbackRate;
}
reverse() {
this.playbackRate = this.playbackRate * -1;
}
_tick() {
const now = this._timeline.currentTime;
if (this._playState !== 'running' ||
!this._effect ||
!common_1.NumberExt.isNumber(now)) {
return;
}
const timing = this._effect.getComputedTiming();
const { duration, delay, iterations, direction, endTime } = timing;
const currentTime = (now - this._startTime) * this._playbackRate;
const elapsed = currentTime - delay;
let currentIteration = Math.floor(elapsed / duration);
if (currentTime >= endTime || currentTime < 0 || duration <= 0) {
this.finish();
return;
}
if (currentTime >= delay) {
// 计算当前迭代的进度
let iterationTime = elapsed % duration;
currentIteration = Math.min(currentIteration, iterations - 1);
// 处理播放方向
if ((0, utils_1.isReverseDirection)(direction, currentIteration)) {
iterationTime = duration - iterationTime;
}
// 应用动画效果
this._effect.apply(iterationTime);
}
this._currentTime = currentTime;
this._rafId = requestAnimationFrame(() => this._tick());
}
}
exports.Animation = Animation;
//# sourceMappingURL=animation.js.map