[英]Single canvas sprite animation works, but not if there's two canvases
使用canvas元素處理一些動畫精靈。
我設法設置了一個出色的測試用例,但是只有一個canvas元素,最后會有任意數量的動畫精靈。
不知道為什么嗎?
<canvas id="video1"></canvas>
<input type="button" onclick="PS.draw(1)" value="Play">
<input type="button" onclick="PS.stop(1)" value="Stop">
<canvas id="video2"></canvas>
<input type="button" onclick="PS.draw(2)" value="Play">
<input type="button" onclick="PS.stop(2)" value="Stop">
<script>
var PS = {
init: function(id) { // setup the premise for the canvases, this data is needed to animate the sprites.
var sprites = [];
var context = document.getElementById(src.entries[id].file.ios.filename);
$(context).attr('width', src.entries[id].file.ios.width);
$(context).attr('height', src.entries[id].file.ios.height);
context = context.getContext('2d');
var array = src.entries[id].file.ios.sprite;
for (var i = 0; i < array.length; i++) {
sprites[i] = new Sprite(array[i], { frameW: src.entries[id].file.ios.width, frameH: src.entries[id].file.ios.height, interval: src.entries[id].file.ios.framerate, useTimer: false }); // sprite.js, associates each sprite with given settings.
}
var activeSprite = sprites[0];
var framesDrawn = 0;
var f = 0;
var sprite = 0;
//var filename = src.entries[id].file.ios.filename
window['sprite' + id] = {
"context" : context,
"activeSprite" : activeSprite,
"framesDrawn" : framesDrawn,
"f" : f,
"sprites" : sprites,
"sprite" : sprite,
"framerate" : src.entries[id].file.ios.framerate,
"frames" : src.entries[id].file.ios.frames,
};
},
/*
^ How do I pass this on to draw()? Global vars?
*/
draw: function(id) {
//var filename = src.entries[id].file.ios.filename;
//console.log(window.filename.context);
//console.log(window.sprite+id);
window['sprite' + id ].player = setTimeout(function() { // I'm here to throttle to approriate framerate
requestAnimationFrame(function() {
PS.draw(id);
});
window['sprite' + id ].framesDrawn++;
window['sprite' + id ].f++;
window['sprite' + id ].activeSprite.draw(window['sprite' + id ].context, 0, 0);
if(window['sprite' + id ].f == window['sprite' + id ].frames) { // you've reached the total frames of animation, reset to first spritesheet
window['sprite' + id ].sprite = 0;
window['sprite' + id ].activeSprite = window['sprite' + id ].sprites[window['sprite' + id ].sprite];
window['sprite' + id ].framesDrawn = 0;
window['sprite' + id ].f = 0;
}
if(window['sprite' + id ].framesDrawn == 50) { // each sprite contains 50 images, thus change to new spritesheet
window['sprite' + id ].sprite++;
window['sprite' + id ].activeSprite = window['sprite' + id ].sprites[window['sprite' + id ].sprite];
window['sprite' + id ].framesDrawn = 0;
}
}, 1000 / window['sprite' + id ].framerate);
},
stop: function(id) {
//var filename = src.entries[id].file.ios.filename;
clearTimeout(window['sprite' + id ].player); // some other better way?
}
}
var src ={
"entries":{
"1":{
"file":{
"ios":{
"filename":"video1",
"sprite":["https:\/\/dl.dropboxusercontent.com\/u\/3618143\/sprite1.jpg","https:\/\/dl.dropboxusercontent.com\/u\/3618143\/sprite2.jpg","https:\/\/dl.dropboxusercontent.com\/u\/3618143\/sprite3.jpg"],
"frames":"115",
"framerate":"23.976",
"width":"426",
"height":"240"
}
}
},
"2":{
"file":{
"ios":{
"filename":"video2",
"sprite":["https:\/\/dl.dropboxusercontent.com\/u\/3618143\/sprite1.jpg","https:\/\/dl.dropboxusercontent.com\/u\/3618143\/sprite2.jpg","https:\/\/dl.dropboxusercontent.com\/u\/3618143\/sprite3.jpg"],
"frames":"115",
"framerate":"23.976",
"width":"426",
"height":"240"
}
}
},
}
}
setTimeout(function() {
PS.init(1);
PS.init(2);
},500)
</script>
我還不能弄清楚為什么會這樣,但是問題是sprite.js使用圖像的緩存和預加載來初始化Sprite
。 由於兩個canvas
元素都顯示同一組圖像,因此在初始化第二個畫布時它們會相互沖突,因此它會以某種方式被削弱。
最簡單的解決方案似乎是禁用Sprite圖片緩存:
// override Sprite caching to prevent images conflicting
Sprite.getImageFromCache = function(src) {
//return images[src] ? images[src] : null;
return null;
};
Sprite.saveImageToCache = function(src, image) {
//images[src] = image;
};
這是一個更新的小提琴,顯示了它的工作原理。 http://jsfiddle.net/xbcw7sbb/4/
請注意,我還重命名了一些變量,以使它更容易理解什么,並將filename
作為data()
對象附加到畫布中,以將其保持在一起。
再加上兩次單擊“ 播放”會導致動畫循環在畫布中運行兩次的問題,因此我創建了一個start(id)
方法,如果未運行,則僅調用draw()
。 draw()
本身僅需要上下文(您的filename
對象),因此您可以每次都傳遞該上下文,而不必從每個循環的其他位置檢索它。
/* override Sprite caching to prevent images conflicting */
// (original code commented)
Sprite.getImageFromCache = function(src) {
//return images[src] ? images[src] : null;
return null;
};
Sprite.saveImageToCache = function(src, image) {
//images[src] = image;
};
var PS = {
init: function (id) {
// setup the premise for the canvases,
// this data is needed to animate the sprites.
var sprites = [];
var ios = src.entries[id].file.ios;
var canvas = document.getElementById(ios.filename);
$(canvas).attr('width', ios.width);
$(canvas).attr('height', ios.height);
var context = canvas.getContext('2d');
var imgList = ios.sprite;
for (var i = 0; i < imgList.length; i++) {
sprites[i] = new Sprite(imgList[i], {
frameW: ios.width,
frameH: ios.height,
interval: ios.framerate,
useTimer: false
}); // sprite.js, associates each sprite with given settings.
}
// attach the context to the canvas so we can retrieve it again
$(canvas).data('spritecontext', {
"context": context,
"activeSprite": sprites[0],
"framesDrawn": 0,
"f": 0,
"sprites": sprites,
"sprite": 0,
"framerate": ios.framerate,
"frames": ios.frames
});
},
start: function(id) {
var canvasId = src.entries[id].file.ios.filename;
var canvas = $('#' + canvasId);
var spritecontext = canvas.data('spritecontext');
if(!spritecontext.player) {
PS.draw(id, spritecontext);
}
},
draw: function (id, spritecontext) {
spritecontext.player = setTimeout(function () {
// I'm here to throttle to approriate framerate
requestAnimationFrame(function () {
PS.draw(id, spritecontext);
});
spritecontext.framesDrawn++;
spritecontext.f++;
spritecontext.activeSprite.draw(spritecontext.context, 0, 0);
if (spritecontext.f == spritecontext.frames) {
// you've reached the total frames of animation,
// reset to first spritesheet
spritecontext.sprite = 0;
spritecontext.activeSprite = spritecontext.sprites[spritecontext.sprite];
spritecontext.framesDrawn = 0;
spritecontext.f = 0;
}
if (spritecontext.framesDrawn == 50) {
// each sprite contains 50 images, thus change to new spritesheet
spritecontext.sprite++;
spritecontext.activeSprite = spritecontext.sprites[spritecontext.sprite];
spritecontext.framesDrawn = 0;
}
}, 1000 / 23.976);
},
stop: function (id) {
var canvasId = src.entries[id].file.ios.filename;
var canvas = $('#' + canvasId);
var spritecontext = canvas.data('spritecontext');
// some other better way? - probably not
clearTimeout(spritecontext.player);
// so we know its stopped
spritecontext.player = null;
}
}
var src = {
"entries": {
"1": {
"file": {
"ios": {
"filename": "video1",
"sprite":
["https:\/\/dl.dropboxusercontent.com\/u\/3618143\/sprite1.jpg",
"https:\/\/dl.dropboxusercontent.com\/u\/3618143\/sprite2.jpg",
"https:\/\/dl.dropboxusercontent.com\/u\/3618143\/sprite3.jpg"],
"frames": "115",
"framerate": "23.976",
"width": "426",
"height": "240"
}
}
},
"2": {
"file": {
"ios": {
"filename": "video2",
"sprite":
["https:\/\/dl.dropboxusercontent.com\/u\/3618143\/sprite1.jpg",
"https:\/\/dl.dropboxusercontent.com\/u\/3618143\/sprite2.jpg",
"https:\/\/dl.dropboxusercontent.com\/u\/3618143\/sprite3.jpg"],
"frames": "115",
"framerate": "23.976",
"width": "426",
"height": "240"
}
}
},
}
}
setTimeout(function () {
PS.init(1);
PS.init(2);
}, 500);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.