Очистить весь преобразованный холст HTML5 с сохранением преобразования контекста - PullRequest
11 голосов
/ 03 апреля 2011

Я хочу увеличить и панорамировать HTML5-холст, преобразовав контекст, используя translate() и scale(), очистив холст, а затем перерисовав.Обратите внимание, что я явно не вызываю save() и restore() вокруг своих преобразований.

Если я выполняю стандарт ctx.clearRect(0,0,ctx.canvas.width,ctx.canvas.height), тогда весь видимый холст не будет очищен;уменьшение или панорамирование может привести к тому, что этот начальный прямоугольник не будет полностью покрывать область рисования.

Если я выполняю метод очистки с поддержкой Webkit ...

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

... тогда кумулятивное преобразованиеконтекста сбрасывается.

Как лучше всего очистить весь контекст холста, не теряя своего преобразования?

Ответы [ 2 ]

22 голосов
/ 03 апреля 2011

Отслеживание всей информации о преобразовании, которую вы, вероятно, делаете, - это то, что уже сделали несколько других (например, cake.js и моя собственная библиотека для двоих). Я думаю, что это будет в значительной степени неизбежно для любой большой библиотеки canvas.

Илмари из cake.js даже пожаловался Мозилле: https://bugzilla.mozilla.org/show_bug.cgi?id=408804

Вместо этого вы можете вызвать save / restore для вашего метода очистки:

// 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

Разве это не удовлетворит ваше дело?

3 голосов
/ 03 апреля 2011

Для тех, кто хочет отслеживать свои полные преобразования контекста, вот мой код для этого по требованию, в зависимости от контекста. Это предваряется использованием, которое показывает, как очистить полный прямоугольник на основе преобразованных координат. Вы можете увидеть используемый код на моем сайте.

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());
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...