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