2011-04-02 36 views
11

我想通過使用translate()scale()轉換上下文,清除畫布,然後重新繪製來縮放和平移HTML5畫布。請注意,我明確四處打電話我轉換save()restore()清除整個已轉換的HTML5畫布,同時保留上下文轉換

如果我執行標準ctx.clearRect(0,0,ctx.canvas.width,ctx.canvas.height)那麼整個可見的畫布不會被清除;縮小或平移可能會導致此初始矩形不能完全覆蓋繪圖區域。

如果我執行的Webkit友好的結算方法...

var w=canvas.width; 
canvas.width = 0; 
canvas.width = w; 

...那麼上下文的累計改造復位。

我怎樣才能最清楚,而不會失去我的改造整個畫布背景?像你可能做的所有轉換信息

+0

吸盤式的方式將存儲您的尺度和翻譯,然後自己計算邊界矩形,但人們會希望有更好的方法。 – 2011-04-02 23:10:26

+0

@JakubHampl這就是我正在做的事情,因爲我已經跟蹤了變換並添加了從屏幕空間轉換到畫布空間的方法,但是這似乎是一個很好的機會來指出這兩個清除的問題方法,看看是否有更清潔的東西。 – Phrogz 2011-04-02 23:24:16

回答

21

飼養的軌道是幾個人到目前爲止已經做什麼(如cake.js和我自己的圖書館,兩個)。我認爲,這對於任何大型畫布庫來說都是不可避免的。

cake.js的ILMARI甚至抱怨的Mozilla: https://bugzilla.mozilla.org/show_bug.cgi?id=408804

你可以改爲調用保存/恢復周圍的清零方法:

// I have lots of transforms right now 
ctx.save(); 
ctx.setTransform(1,0,0,1,0,0); 
// Will always clear the right space 
ctx.clearRect(0,0,ctx.canvas.width,ctx.canvas.height); 
ctx.restore(); 
// Still have my old transforms 

不會滿足你的情況?

+1

我是多麼的愚蠢;我試圖考慮如何獲得單位矩陣,但是正在考慮需要當前的變換來計算倒數,然後乘以該倒數。是的,這應該做得很好。 – Phrogz 2011-04-03 04:04:50

+0

很高興我能幫到你。我也想感謝你對S.O.的畫布主題的所有貢獻。 – 2011-04-04 00:46:09

3

對於那些誰關心跟蹤他們的完整的上下文轉換,這是我在按需,按上下文的基礎這樣的代碼。前面的用法說明了如何根據變換後的座標清除完整的矩形。您可以在我的網站上看到the code in use

window.onload = function(){ 
    var canvas = document.getElementsByTagName('canvas')[0]; 
    var ctx = canvas.getContext('2d'); 
    trackTransforms(ctx); 
    function redraw(){ 
    var p1 = ctx.transformedPoint(0,0); 
    var p2 = ctx.transformedPoint(canvas.width,canvas.height); 
    ctx.clearRect(p1.x,p1.y,p2.x-p1.x,p2.y-p1.y); 
    // ... 
    } 
} 


// Adds ctx.getTransform(), returning an SVGMatrix 
// Adds ctx.transformedPoint(x,y), returning an SVGPoint 
function trackTransforms(ctx){ 
    var svg = document.createElementNS("http://www.w3.org/2000/svg",'svg'); 
    var xform = svg.createSVGMatrix(); 
    ctx.getTransform = function(){ return xform; }; 

    var savedTransforms = []; 
    var save = ctx.save; 
    ctx.save = function(){ 
    savedTransforms.push(xform.translate(0,0)); 
    return save.call(ctx); 
    }; 
    var restore = ctx.restore; 
    ctx.restore = function(){ 
    xform = savedTransforms.pop(); 
    return restore.call(ctx); 
    }; 

    var scale = ctx.scale; 
    ctx.scale = function(sx,sy){ 
    xform = xform.scaleNonUniform(sx,sy); 
    return scale.call(ctx,sx,sy); 
    }; 
    var rotate = ctx.rotate; 
    ctx.rotate = function(radians){ 
    xform = xform.rotate(radians*180/Math.PI); 
    return rotate.call(ctx,radians); 
    }; 
    var translate = ctx.translate; 
    ctx.translate = function(dx,dy){ 
    xform = xform.translate(dx,dy); 
    return translate.call(ctx,dx,dy); 
    }; 
    var transform = ctx.transform; 
    ctx.transform = function(a,b,c,d,e,f){ 
    var m2 = svg.createSVGMatrix(); 
    m2.a=a; m2.b=b; m2.c=c; m2.d=d; m2.e=e; m2.f=f; 
    xform = xform.multiply(m2); 
    return transform.call(ctx,a,b,c,d,e,f); 
    }; 
    var setTransform = ctx.setTransform; 
    ctx.setTransform = function(a,b,c,d,e,f){ 
    xform.a = a; 
    xform.b = b; 
    xform.c = c; 
    xform.d = d; 
    xform.e = e; 
    xform.f = f; 
    return setTransform.call(ctx,a,b,c,d,e,f); 
    }; 
    var pt = svg.createSVGPoint(); 
    ctx.transformedPoint = function(x,y){ 
    pt.x=x; pt.y=y; 
    return pt.matrixTransform(xform.inverse()); 
    } 
} 
+0

這個例子北京時間很大,幫我了很多,但仍然有一個問題,我不能讓我的頭周圍:你如何清除重繪(畫布),如果你的圖像在圖像學中的點旋轉? – Kevkong 2012-12-06 15:27:23

+0

@Kevkong完全像接受的答案所示:保存上下文變換,將變換重置爲單位矩陣,清除0,0,寬度,高度並恢復變換。 – Phrogz 2012-12-07 17:36:47

+0

是的,你說得對,我只是拼錯了一些東西,所以「恢復」不會按預期工作,並且轉換點在恢復後返回了錯誤的地方。感謝迄今。 – Kevkong 2012-12-13 17:12:40