sprite-frame-animation
Version:
A user-friendly Sprite frame animation library
344 lines (340 loc) • 11.7 kB
JavaScript
/*!
* sprite-frame-animation 1.0.0 (https://github.com/CNLHB/spriteFrame)
* API https://github.com/CNLHB/spriteFrame/blob/master/doc/api.md
* Copyright 2017-2025 CNLHB. All Rights Reserved
* Licensed under MIT (https://github.com/CNLHB/spriteFrame/blob/master/LICENSE)
*/
import _asyncToGenerator from '@babel/runtime-corejs3/helpers/asyncToGenerator';
import _classCallCheck from '@babel/runtime-corejs3/helpers/classCallCheck';
import _createClass from '@babel/runtime-corejs3/helpers/createClass';
import _regeneratorRuntime from '@babel/runtime-corejs3/regenerator';
import _Map from '@babel/runtime-corejs3/core-js-stable/map';
import _forEachInstanceProperty from '@babel/runtime-corejs3/core-js-stable/instance/for-each';
import _setTimeout from '@babel/runtime-corejs3/core-js-stable/set-timeout';
import _Promise from '@babel/runtime-corejs3/core-js-stable/promise';
import _concatInstanceProperty from '@babel/runtime-corejs3/core-js-stable/instance/concat';
import _Date$now from '@babel/runtime-corejs3/core-js-stable/date/now';
var SPRITE_FRAME_ANIMATION_VERSION = '1.0.0';
var SPRITE_FRAME_ANIMATION_NAME = '_SPRITE_FRAME_ANIMATION_NAME_';
var SpriteFrameAnimation = /*#__PURE__*/function () {
function SpriteFrameAnimation(options) {
_classCallCheck(this, SpriteFrameAnimation);
this.version = SPRITE_FRAME_ANIMATION_VERSION;
this.initParam();
this.reset(options);
this.init(options);
this.validateName();
}
_createClass(SpriteFrameAnimation, [{
key: "validateName",
value: function validateName() {
var key = SPRITE_FRAME_ANIMATION_NAME + this.name;
this.key = key;
var oldInstace = window[key];
if (this.name && !oldInstace) {
window[this.key] = this;
} else {
console.warn('The animation name already exists', oldInstace);
}
}
}, {
key: "initParam",
value: function initParam() {
this.name = ''; //动画名称
this.width = 0; //帧动画每帧的宽度
this.height = 0; //帧动画每帧的高度
this.img = 0; //一个动画的完整序列帧url
this.orient = 'left-right'; //关键帧图片的排列方式
this.count = 0; //动画循环次数
this.delay = 0; //动画延时多久开始
this.duration = 1000; //动画持续时间ms
this.autoplay = true;
this.currentKey = 0; //开始索引帧
this.totalKeyNum = 0; //总帧数据
this.paramMd5 = '';
this.delayFunc = [];
this.spriteArray = [];
this.interval = 0; //动画执行间隔时间
this.isAnimating = false;
this.isLoadingImage = true;
this.image = null; // 图片实例
this.fImage = null; // 首次渲染图片实例
this.eventMap = new _Map();
}
}, {
key: "reset",
value: function reset(options) {
var isReload = options.img && this.img && options.img !== this.img;
//ani上的属性,全部赋值一遍
for (var attr in options) {
this[attr] = options[attr];
}
if (isReload) {
console.log('Reload animation resources', options.img);
this.init(options);
}
}
}, {
key: "initElement",
value: function () {
var _initElement = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee(options) {
var container, fImg;
return _regeneratorRuntime.wrap(function _callee$(_context) {
while (1) switch (_context.prev = _context.next) {
case 0:
if (!this.canvasRef) {
container = options.container;
if (options.firstImg && !this.image) {
fImg = document.createElement('img');
fImg.style.width = '100%';
fImg.style.height = '100%';
fImg.src = options.firstImg;
container.appendChild(fImg);
this.fImage = fImg;
}
this.canvasRef = document.createElement('canvas');
this.canvasRef.width = this.width;
this.canvasRef.height = this.height;
this.canvasRef.style.width = '100%';
this.canvasRef.style.height = '100%';
container.appendChild(this.canvasRef);
}
case 1:
case "end":
return _context.stop();
}
}, _callee, this);
}));
function initElement(_x) {
return _initElement.apply(this, arguments);
}
return initElement;
}()
}, {
key: "getCurrentImage",
value: function () {
var _getCurrentImage = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee2() {
return _regeneratorRuntime.wrap(function _callee2$(_context2) {
while (1) switch (_context2.prev = _context2.next) {
case 0:
if (!(this.image && this.image.src === this.img)) {
_context2.next = 2;
break;
}
return _context2.abrupt("return", this.image);
case 2:
_context2.t0 = this.image;
if (_context2.t0) {
_context2.next = 7;
break;
}
_context2.next = 6;
return getImgData(this.img);
case 6:
_context2.t0 = _context2.sent;
case 7:
return _context2.abrupt("return", _context2.t0);
case 8:
case "end":
return _context2.stop();
}
}, _callee2, this);
}));
function getCurrentImage() {
return _getCurrentImage.apply(this, arguments);
}
return getCurrentImage;
}()
}, {
key: "init",
value: function () {
var _init = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee3(options) {
var _this = this;
var imageInstce, idx, _context3;
return _regeneratorRuntime.wrap(function _callee3$(_context4) {
while (1) switch (_context4.prev = _context4.next) {
case 0:
this.initElement(options);
this.clearFrame();
if (this.img) {
_context4.next = 4;
break;
}
return _context4.abrupt("return", false);
case 4:
_context4.next = 6;
return this.getCurrentImage();
case 6:
imageInstce = _context4.sent;
if (imageInstce) {
_context4.next = 10;
break;
}
console.error("".concat(this.img, " load failed"));
return _context4.abrupt("return", false);
case 10:
this.isLoadingImage = false;
this.image = imageInstce;
//持续时间
// if (typeof this.duration === 'string') {
// let duration = this.duration.match(/^([\d|.]+)ms|([\d|.]+)s$/i);
// duration = duration[1] || duration[2] * 1000;
// this.duration = +duration;
// }
//持续时间
// if (typeof this.interval === 'string') {
// let interval = this.interval.match(/^([\d|.]+)ms|([\d|.]+)s$/i);
// interval = interval[1] || interval[2] * 1000;
// this.interval = +interval;
// }
//每帧的坐标信息
for (idx = 0; idx < this.totalKeyNum; ++idx) {
if (this.orient === 'left-right') {
this.spriteArray.push({
x: idx * this.width,
y: 0
});
} else {
this.spriteArray.push({
x: 0,
y: idx * this.height
});
}
}
this.showCover();
if (this.autoplay) {
this.start();
} else {
_forEachInstanceProperty(_context3 = this.delayFunc).call(_context3, function (fn) {
fn.call(_this);
});
}
case 15:
case "end":
return _context4.stop();
}
}, _callee3, this);
}));
function init(_x2) {
return _init.apply(this, arguments);
}
return init;
}()
}, {
key: "start",
value: function start() {
var _this2 = this;
if (!this.image) {
this.delayFunc.push(this.start);
return;
}
var ctx = this.canvasRef.getContext('2d');
var aniTimes = 0;
//开始动画吧
if (this.isAnimating) {
return; // 防止重复启动
}
this.isAnimating = true;
this[this.key] = _setTimeout(function () {
drawImg(_this2, ctx);
}, this.delay);
function drawImg(self, ctx) {
var end = false;
ctx.clearRect(0, 0, self.width, self.height);
ctx.drawImage(self.image, self.spriteArray[self.currentKey].x, self.spriteArray[self.currentKey].y, self.width, self.height, 0, 0, self.width, self.height);
if (self.currentKey !== self.totalKeyNum - 1) {
//到了最后一帧
self.currentKey++;
} else {
self.currentKey = 2;
aniTimes++;
end = true;
if (self.count && aniTimes >= self.count) {
//动画结束
self.emitEnd();
return;
}
}
self[self.key] = _setTimeout(function () {
drawImg(self, ctx);
}, end && self.interval ? self.interval : self.duration / self.totalKeyNum);
}
}
}, {
key: "showCover",
value: function showCover() {
var canvas = this.canvasRef;
if (!canvas) return;
var ctx = canvas.getContext('2d');
//先画封面
ctx.drawImage(this.image, 0, 0, this.width, this.height, 0, 0, this.width, this.height);
// 显示完封面,删除
if (this.fImage) {
this.fImage.remove();
}
}
}, {
key: "stop",
value: function stop() {
this.clearFrame();
}
}, {
key: "clearFrame",
value: function clearFrame() {
console.log('clearFrame');
this.isLoadingImage = true;
this.isAnimating = false;
clearTimeout(this[this.key]);
}
}, {
key: "destroy",
value: function destroy() {
this.stop();
this.canvasRef.remove();
if (this.fImage) {
this.fImage.remove();
}
window[this.key] = null;
}
/**
* 简单实现事件监听
* @param {*} type
* @param {*} fn
*/
}, {
key: "on",
value: function on(type, fn) {
var oldEvents = this.eventMap.get(type);
if (oldEvents) {
oldEvents.push(fn);
} else {
var events = [fn];
this.eventMap.set(type, events);
}
}
}, {
key: "emitEnd",
value: function emitEnd() {
var _context5;
this.eventMap.get('end') && _forEachInstanceProperty(_context5 = this.eventMap.get('end')).call(_context5, function (fn) {
return fn();
});
}
}]);
return SpriteFrameAnimation;
}(); // 获取图片数据
function getImgData(url, isNeedCross) {
return new _Promise(function (resolve) {
var _context6;
var image = new Image();
image.onload = function () {
resolve(image);
};
image.onerror = function () {
resolve(null);
};
image.src = _concatInstanceProperty(_context6 = "".concat(url, "?")).call(_context6, _Date$now());
});
}
export { SpriteFrameAnimation as default };
//# sourceMappingURL=index.mjs.map