簡體   English   中英

單個畫布精靈動畫有效,但如果有兩個畫布則無效

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM