2014-09-02 108 views
0

我的問題:什麼導致HTML5 Canvas clearRect方法在下面描述的情況下無法按預期工作,並且有什麼我可以解決它(不添加另一個第三方庫到我的項目)?RectClear不適用於HTML5畫布縮放動畫

簡而言之:我爲HTML5畫布上的各種縮放操作設置動畫。我正在使用JQuery來處理這些動畫,以便利用隨時可用的緩動功能。在某些情況下,clearRect方法不會完全清除畫布。

更多詳細信息我已經設置了一個緩衝區畫布,其中包含要繪製到主顯示畫布上的圖像數據。每次我需要更新顯示畫布的縮放比例或旋轉角度時,我都清除主畫布,對顯示畫布進行更改,然後將緩衝區畫布拖到顯示畫布上。

當使用非常特定的動畫序列(例如easeOutElastic),並且縮放處於緩動功能的最後部分期間的某個點(在這種情況下,縮放反轉方向時),畫布似乎不是正在清理。

我已經試過 我曾嘗試以下方法,失敗: :

  • 四捨五入由JQuery的動畫製作的價值觀與他們(toFixed(1),即)縮放前
  • 跟蹤由JQuery動畫生成的值並跳過未顯着改變值的縮放操作
  • 向每個動畫步驟中注入一個額外的setTimeout(fn,0)以查看瀏覽器是否過載。

這裏的一個小提琴展示問題(我試圖上IE 11,鉻37和FF 32):

http://jsfiddle.net/pae9n00n/21/

(第三測試演示該問題)

//Easy refs 
var canvasBuff = $("#canvasBuff")[0]; 
var ctxBuff = canvasBuff.getContext("2d"); 
var canvasMain = $("#canvasMain")[0]; 
var ctxMain = canvasMain.getContext("2d"); 
var offsetX = 64; 
var offsetY = 64; 

//Setup 
setupBufferCanvas(); 
setupMainCanvas(); 
refreshMainCanvas(); 

$("#butTest1").click(function(){ doTest1(); }); 
$("#butTest2").click(function(){ doTest2(); }); 
$("#butTest3").click(function(){ doTest3(); }); 

$("#butReset").click(function(){ 

    var l = -1 * offsetX; 
    var t = -1 * offsetY; 
    ctxMain.clearRect(l, t, canvasMain.width, canvasMain.height); 

    ctxMain.restore(); 
    refreshMainCanvas(); 
    ctxMain.save(); 
}); 

//======================= 
// doTest1 
//======================= 
function doTest1(){ 
    //No Problems 
    animateScale(2, 2, 1000, "linear", null); 
};  

//======================= 
// doTest2 
//======================= 
function doTest2(){ 
//No Problems 
animateScale(2, 2, 800, "linear", function(){ 
    animateScale(.5, .5, 200, "linear", null); 
}); 
};  

//======================= 
// doTest3 
//======================= 
function doTest3(){ 
    //Problem 
    animateScale(2, 2, 1000, "easeOutElastic", null); 
};  

//======================= 
// setupBufferCanvas 
//======================= 
function setupBufferCanvas(){ 
    //Prep the buffer canvas 
    canvasBuff.width=128; 
    canvasBuff.height=128; 

    ctxBuff.fillStyle = "rgba(74,142,196,1)"; 
    ctxBuff.fillRect(32, 32, 64, 64); 

    ctxBuff.lineWidth = 4; 
    ctxBuff.strokeStyle = "rgba(0,0,0,1)"; 
    ctxBuff.strokeRect(32, 32, 64, 64); 
}; 

//======================= 
// setupMainCanvas 
//======================= 
function setupMainCanvas(){ 
    canvasMain.width=128; 
    canvasMain.height=128; 
    ctxMain.translate(offsetX, offsetY); 
    ctxMain.rotate(Math.PI/4); 
    scaleMainCanvas(.5,.5); //scale to half 
    ctxMain.save(); 
}; 

//======================= 
// clearMainCanvas 
//======================= 
function clearMainCanvas(){ 
    var l = -1 * offsetX; 
    var t = -1 * offsetY; 
    ctxMain.clearRect(l, t, canvasMain.width, canvasMain.height); 
}; 

//======================= 
// refreshMainCanvas 
//======================= 
function refreshMainCanvas(){ 
    var l = -1 * offsetX; 
    var t = -1 * offsetY; 
    ctxMain.clearRect(l, t, canvasMain.width, canvasMain.height); 
    ctxMain.drawImage(canvasBuff, l, t); 
}; 

//======================= 
// scaleMainCanvas 
//======================= 
function scaleMainCanvas(x, y){ 
    var l = -1 * offsetX; 
    var t = -1 * offsetY; 
    ctxMain.clearRect(l, t, canvasMain.width, canvasMain.height); 
    ctxMain.scale(x, y) 
    ctxMain.drawImage(canvasBuff, l, t); 
}; 

//======================= 
// animateScale 
//======================= 
function animateScale(x, y, duration, easing, callback){ 
    var ani$ = $({x:1, y:1}); 
    ani$.animate({x:x, y:y},{ 
     duration:duration, 
     easing:easing, 
     step: function(){ 
      ctxMain.save(); 
      scaleMainCanvas(ani$[0].x, ani$[0].y); 
      ctxMain.restore(); 
     }, 
     complete: function(){ 
      scaleMainCanvas(x, y); 
      if (callback){ callback(); } 
     } 
    }); 
}; 

回答

0

解決:錯誤,勿庸置疑,是我自己的錯。爲了避免累積比例操作,我在每次渲染之前和之後保存()和還原()畫布比例。這裏的問題是,我最終清除了之前大小的畫布,這始終是起始比例(在此情況下小於當前繪圖比例)。

這個問題在增加規模操作期間被混淆,因爲我們總結了一切。

我破解了小提琴的解決方案。它可能不是理想的長期解決方案。但確認錯誤,原因:

http://jsfiddle.net/pae9n00n/24/

修復在此方法適用於:

//======================= 
// scaleMainCanvas 
//======================= 
function scaleMainCanvas(x, y, useFix){ 
    var l = -1 * offsetX; 
    var t = -1 * offsetY; 

    ctxMain.clearRect(l, t, canvasMain.width, canvasMain.height); 

    ctxMain.scale(x, y); 

    if (useFix){ 
     //Not a great solution, but it illustartes my error 
     ctxMain.clearRect(l, t, canvasMain.width, canvasMain.height); 
    } 

    ctxMain.drawImage(canvasBuff, l, t); 
}; 
+0

我還想補充一點,我開始意識到,使用save()並以這種方式恢復()是一個壞主意。它與其他同時發生的操作可能會產生潛在的衝突,這些操作可能會針對上下文而對這種批量更改敏感。我計劃開始手動跟蹤比例變化,並根據需要明確地反轉它們。我認爲這是一種更可持續的方法。 – maulkye 2014-09-03 20:15:41