canvas序列帧动画 & pixi.js
方法一:基于canvas实现多个人物序列帧切换 (原生写法)
class cavasAnimate { constructor(id, activeRw) { this.id = id; this.sourcesRw = {}; this.canvas = null; this.ctx = null; this.timer = null; this.loadedImages = 0; this.numImages = 0; this.images = []; this.activeRw = activeRw; this.init(id) this.sourceImg = {} this.existKey = [] } init(id) { //创建画布 this.canvas = document.getElementById(id); this.canvas.width = this.activeRw.width; this.canvas.height = this.activeRw.height; this.ctx = this.canvas.getContext("2d"); this.changeRw(this.activeRw, id); } changeRw(activeRw) { console.log(this.sourceImg); // this.timer = null; clearInterval(this.timer); this.sourcesRw = []; this.canvas.width = activeRw.width; this.canvas.height = activeRw.height; this.ctx.clearRect(0, 0, this.activeRw.width, this.activeRw.height); setTimeout(() => { console.log(5, Array.isArray(this.sourceImg), this.sourceImg, this.sourceImg.length) }, 10000) //执行图片预加载,加载完成后播放图片 this.loadImg(this.sourcesRw, activeRw, (images) => { // console.log(1,this.sourcesRw) this.activeRw = activeRw; clearInterval(this.timer) this.playImg(images) }); } loadImg(sourcesRw, activeRw, callback) { this.loadedImages = 0; this.numImages = 0; this.images = []; this.numImages = this.sourcesRw.length; console.log('load') if (this.sourceImg) { this.existKey = [] for (let i in this.sourceImg) { console.log(i); this.existKey.push(i) } console.log('this.existKey', this.existKey) } if (this.existKey && this.existKey.indexOf(activeRw.key) > -1) { callback(this.sourceImg[activeRw.key]); return; } for (let i = 0; i <= activeRw.num; i++) { this.sourcesRw[i] = require('@/assets/images/' + activeRw.key + '/' + activeRw.key + i + '.png'); } for (let i = 0, len = sourcesRw.length; i < len; i++) { this.images[i] = new Image(); //当一张图片加载完成时执行 this.images[i].onload = () => { //当所有图片加载完成时,执行回调函数callback this.loadedImages++; if (this.loadedImages >= this.numImages) { callback(this.images); this.sourceImg[activeRw.key] = this.images } }; //把sourcesRw中的图片信息导入images数组 this.images[i].src = this.sourcesRw[i]; } } playImg(images) { let imageNum = images.length; let imageNow = 0; this.timer = setInterval(() => { this.ctx.clearRect(0, 0, this.activeRw.width, this.activeRw.height); // this.ctx.globalAlpha=0.9 this.ctx.drawImage(images[imageNow], 0, 0, this.activeRw.width, this.activeRw.height); if (document.getElementById(this.id).parentElement.style.background !== "none") { document.getElementById(this.id).parentElement.style.background = "none"; } imageNow++; if (imageNow >= imageNum) { imageNow = 0; } }, 70) } resize() { } } const animateObj = (id, rwList) => { return new cavasAnimate(id, rwList); }; export default animateObj;
data() {
return {
canvasAniObj: null,
activeIndex: 0,
timer: null,
rwArr: [
{
key: 'hu',
width: 1400,
height: 1308,
num: 107
}, {
key: 'al',
width: 950,
height: 1628,
num: 66
},
{
key: 'll',
width: 1400,
height: 1564,
num: 67
}
],
loaded: false
};
},
watch: {},
methods: {
chooseRw(index) {
console.log(index)
this.activeIndex = index;
this.canvasAniObj.changeRw(this.rwArr[index])
let imgUrl = require('@/assets/images/' + this.rwArr[index].key + '/' + this.rwArr[index].key + '0.png');
document.getElementById('animation_canvas').parentElement.style.backgroundImage = 'url(' + imgUrl + ')';
}
},
mounted() {
this.canvasAniObj = cavasAnimation("animation_canvas", this.rwArr[0]
}
方法一:基于 pixi.js 实现多个人物序列帧切换
import * as PIXI from "pixi.js-legacy"; class animate { constructor(id, idGroup, picInfo) { if (window.pixiStore === undefined) { window.pixiStore = { urlList: {}, callbackID: { part1: 0, part5: 0 } }; } this.idGroup = idGroup; this.picInfo = picInfo; this.id = id; this.app = new PIXI.Application({ transparent: true, forceCanvas: true }); this.anim = null; document.getElementById(this.id).innerHTML = ""; document.getElementById(this.id).appendChild(this.app.view); } animation(type, retryTimes, callbackID) { this.app.stage.removeChild(this.anim); let imgs = []; let frames = []; for (let $i = 0; $i <= this.picInfo[type].imgnum; $i++) { let imgUrl = require("@/assets/rw/" + this.picInfo[type].folderu + type + $i + ".png"); if ( window.pixiStore.urlList[imgUrl] === undefined || window.pixiStore.urlList[imgUrl] === false ) { window.pixiStore.urlList[imgUrl] = true; imgs.push(imgUrl); } } this.app.loader.reset(); this.app.loader.add(imgs).load(() => { if ( window.pixiStore.callbackID[this.idGroup[this.id]] !== callbackID ) { return; } let dirty = false; for (let $i = 0; $i <= this.picInfo[type].imgnum; $i++) { let imgUrl = require("@/assets/rw/" + this.picInfo[type].folderu + type + $i + ".png"), textrue = PIXI.Texture.from(imgUrl); if (textrue.orig.width === 1) { window.pixiStore.urlList[imgUrl] = false; PIXI.Texture.removeFromCache(imgUrl); if (dirty === false) { dirty = true; } } frames.push(textrue); } if (dirty && retryTimes < 1) { retryTimes++; this.animation(type, retryTimes, callbackID); return; } else if (dirty && retryTimes >= 1) { return; } this.app.stage.removeChild(this.anim); this.resize(type); document.getElementById(this.id).style.background = "none"; this.anim = new PIXI.AnimatedSprite(frames); this.anim.animationSpeed = 20 / 60; this.app.stage.addChild(this.anim); this.anim.play(); }); } render(type) { document.getElementById(this.id).style.background = ""; let retryTimes = 0; window.pixiStore.callbackID[this.idGroup[this.id]]++; this.animation( type, retryTimes, window.pixiStore.callbackID[this.idGroup[this.id]] ); } resize(type) { let width = document.getElementById(this.id).offsetWidth; let height = document.getElementById(this.id).offsetHeight; this.app.renderer.resize(width, height); this.app.stage.scale.x = this.app.renderer.width / this.picInfo[type].width; this.app.stage.scale.y = this.app.renderer.height / this.picInfo[type].height; } } const animateObj = (id, idGroup, picInfo) => { return new animate(id, idGroup, picInfo); }; export default animateObj;
mofeiList: [
{
key: "mofei_1",
key2: "hu",
name: "阿狐",
txt:
"澈底的及時享樂主義者,中意一切「風流」的東西:月、酒、花與刀。<br/> 最喜歡的是在盛放中飄散的櫻花。"
},
{
key: "mofei_2",
key2: "al",
name: "埃里克",
txt:
"高能,冰冷、嚴厲、無情的終極兵器機械少女。不過, 倘若這些只是自我掩飾的面具……?"
},
{
key: "mofei_3",
name: "芬德爾",
key2: "fd",
txt:
"濕噠噠黏糊糊的奇異生物。將自己的身體設定成了人類的少女形態,對此非常自得。"
},
},
idGroup: {
"part1-ani": "part1",
part5rw: "part5",
part52rw: "part5"
},
picInfo: {
hu: {
width: 1400,
height: 1308,
folderu: "hu/",
imgnum: 107
},
al: {
width: 950,
height: 1628,
folderu: "al/",
imgnum: 65
},
fd: {
width: 850,
height: 1460,
folderu: "fd/",
imgnum: 83
}
},
methods: {
chooseTab(tab) {
this.activeTab = tab;
this.showAni = false;
setTimeout(() => {
this.showAni = true;
}, 50);
if (tab == "buxia") {
this.rwList = this.buxiaList;
} else {
this.rwList = this.mofeiList;
}
this.$nextTick(() => {
this.animateObj.render(this.animateType.key2);
});
},
chooseRw(idx) {
this.currentRwIndex = idx;
this.showAni = false;
setTimeout(() => {
this.showAni = true;
}, 50);
this.$nextTick(() => {
this.animateObj.render(this.animateType.key2);
});
}
},
created() {
this.rwList = this.mofeiList;
},
mounted() {
console.log(this.animateType);
this.$nextTick(() => {
this.animateObj = animate("part5rw", this.idGroup, this.picInfo);
this.animateObj.render(this.animateType.key2);
});
}