UNPKG

itowns

Version:

A JS/WebGL framework for 3D geospatial data visualization

276 lines (234 loc) 8.03 kB
"use strict"; var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard"); var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports["default"] = exports.AnimatedExpression = exports.Animation = void 0; var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck")); var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass")); var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn")); var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf")); var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits")); var THREE = _interopRequireWildcard(require("three")); var FRAMERATE = 60; var FRAME_DURATION = 1000 / FRAMERATE; // player statut var PLAYER_STATE = { // player is stopped STOP: 0, // player plays animation PLAY: 1, // player is at the end of an animation END: 2, // player is paused PAUSE: 3 }; // Private functions // stop timer and re-init parameter var resetTimer = function (player) { if (player.id) { clearInterval(player.id); player.id = undefined; } if (player.waitTimer) { clearInterval(player.waitTimer); player.waitTimer = undefined; } player.keyframe = 0; }; // finish animation and re-init parameter var finishAnimation = function (player) { resetTimer(player); if (player.isEnded()) { player.dispatchEvent({ type: 'animation-ended', animation: player.animation }); } player.dispatchEvent({ type: 'animation-stopped', animation: player.animation }); player.animation = null; if (player.resolve) { player.resolve(); player.resolve = null; player.promise = null; } }; /** * It can play, pause or stop Animation or AnimationExpression (See below). * AnimationPlayer is needed to use Animation or AnimationExpression * AnimationPlayer emits events : * - for each animation's frame; * - when Animation is stopped * - when Animation is ending */ var AnimationPlayer = /*#__PURE__*/ function (_THREE$EventDispatche) { (0, _inherits2["default"])(AnimationPlayer, _THREE$EventDispatche); function AnimationPlayer() { var _this; (0, _classCallCheck2["default"])(this, AnimationPlayer); _this = (0, _possibleConstructorReturn2["default"])(this, (0, _getPrototypeOf2["default"])(AnimationPlayer).call(this)); _this.id = null; _this.keyframe = 0; _this.animation = null; _this.resolve = null; _this.promise = null; _this.state = PLAYER_STATE.STOP; _this.waitTimer = null; return _this; } (0, _createClass2["default"])(AnimationPlayer, [{ key: "isPlaying", value: function isPlaying() { return this.state === PLAYER_STATE.PLAY; } }, { key: "isStopped", value: function isStopped() { return this.state === PLAYER_STATE.STOP; } }, { key: "isEnded", value: function isEnded() { return this.state === PLAYER_STATE.END; } // Public functions /** * Play one animation. * If another animation is playing, it's stopped and the new animation is played. * * @param {Animation} animation - The animation to play * @return {Promise<void>} - Promise is resolved when animation is stopped or finished */ }, { key: "play", value: function play(animation) { var _this2 = this; this.animation = animation; this.dispatchEvent({ type: 'animation-started', animation: animation }); this.state = PLAYER_STATE.PLAY; resetTimer(this); this.id = setInterval(this.frame.bind(this), FRAME_DURATION); this.promise = new Promise(function (r) { _this2.resolve = r; }); return this.promise; } /** * Play an animation after a number of frames. * * @param {Animation} animation The animation to play * @param {number} waitingFrame The waiting time before start animation (time in frame) * @return {Promise<void>} Promise is resolved when animation is stopped or finished */ }, { key: "playLater", value: function playLater(animation, waitingFrame) { var _this3 = this; this.resolveWait = null; var promise = new Promise(function (r) { _this3.resolveWait = r; }); var timew = Math.floor(FRAME_DURATION * waitingFrame); window.clearInterval(this.waitTimer); var self = this; this.waitTimer = window.setTimeout(function () { self.play(animation).then(function () { return self.resolveWait(); }); }, timew); return promise; } /** * Stop the current animation. * * @return {Promise<void>} Promise is resolved when animation is stopped or finished */ }, { key: "stop", value: function stop() { this.state = PLAYER_STATE.STOP; finishAnimation(this); // needed to return promise to wait sync return Promise.resolve(); } /** * Executed for each frame. * * @private */ }, { key: "frame", value: function frame() { if (this.keyframe < this.animation.duration) { if (this.animation.animate) { this.animation.animate(this.keyframe); } this.keyframe++; this.dispatchEvent({ type: 'animation-frame' }); } else { this.state = PLAYER_STATE.END; finishAnimation(this); } } }]); return AnimationPlayer; }(THREE.EventDispatcher); /** * Animation is played by the AnimationPlayer during the time of duration * During playback, the AnimationPlayer emits events for each frame * Animation is used to execute a callback to each frame */ var Animation = /** * @param {Object} params * @param {?number} params.duration - The animation's duration in number of frames. {@link FRAMERATE} is number of frames in one seconde. * @param {string} params.name - The animation's name. It's used for debug message. */ function Animation(params) { (0, _classCallCheck2["default"])(this, Animation); this.duration = params.duration || FRAMERATE; this.name = params.name; }; /** * AnimatedExpression is played by the AnimationPlayer during the time of duration * During playback, the AnimationPlayer emits event for each frame and * it applies expression on root. * AnimatedExpression is used to change object's values for each frame */ exports.Animation = Animation; var AnimatedExpression = /*#__PURE__*/ function (_Animation) { (0, _inherits2["default"])(AnimatedExpression, _Animation); /** * @param {Object} params * @param {?number} params.duration - Duration in number of frames. {@link FRAMERATE} is number of frames in one seconde. * @param {Object} params.root - Object in scene to animate * @param {function(Object,number):void} params.expression - Function applied to root for each frame, arguments are the root object and the ratio of completion. * @param {string} params.name - The animation's name. It's used for debug message */ function AnimatedExpression(params) { var _this4; (0, _classCallCheck2["default"])(this, AnimatedExpression); _this4 = (0, _possibleConstructorReturn2["default"])(this, (0, _getPrototypeOf2["default"])(AnimatedExpression).call(this, params)); _this4.root = params.root; _this4.expression = params.expression; return _this4; } (0, _createClass2["default"])(AnimatedExpression, [{ key: "animate", value: function animate(keyFrame) { this.expression(this.root, keyFrame / (this.duration - 1)); } }]); return AnimatedExpression; }(Animation); exports.AnimatedExpression = AnimatedExpression; var _default = AnimationPlayer; exports["default"] = _default;