清除整个转换后的HTML5 Canvas,同时保留上下文转换

时间:2011-04-02 23:04:46

标签: javascript html5 canvas

我希望通过使用translate()scale()转换上下文,清除画布,然后重新绘制来缩放和平移HTML5 Canvas。请注意,我明确在我的转换中调用save()restore()

如果我执行标准ctx.clearRect(0,0,ctx.canvas.width,ctx.canvas.height),那么整个可见画布将不会被清除;缩小或平移可能会导致此初始矩形不完全覆盖绘图区域。

如果我执行Webkit友好的清算方法......

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

...然后重置上下文的累积转换。

如何在不丢失转换的情况下最好地清除整个画布上下文?

2 个答案:

答案 0 :(得分:22)

跟踪你可能正在做的所有转化信息是迄今为止其他几个人所做的事情(比如cake.js和我自己的图书馆,两个人)。我认为这样做对于任何大型画布库来说都是不可避免的。

Ilmari of cake.js甚至向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 :(得分: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());
  }
}