Javascript 清除整个已转换的HTML5画布,同时保留上下文转换
我想通过使用Javascript 清除整个已转换的HTML5画布,同时保留上下文转换,javascript,html,canvas,Javascript,Html,Canvas,我想通过使用translate()和scale()转换上下文,清除画布,然后重新绘制,来缩放和平移HTML5画布。请注意,在转换过程中,我没有显式地调用save()和restore() 如果我执行标准的ctx.clearRect(0,0,ctx.canvas.width,ctx.canvas.height)则不会清除整个可见画布;缩小或平移可能会导致此初始矩形无法完全覆盖绘图区域 如果我执行Webkit友好的清除方法 var w=canvas.width; canvas.width = 0; c
translate()
和scale()
转换上下文,清除画布,然后重新绘制,来缩放和平移HTML5画布。请注意,在转换过程中,我没有显式地调用save()
和restore()
如果我执行标准的ctx.clearRect(0,0,ctx.canvas.width,ctx.canvas.height)
则不会清除整个可见画布;缩小或平移可能会导致此初始矩形无法完全覆盖绘图区域
如果我执行Webkit友好的清除方法
var w=canvas.width;
canvas.width = 0;
canvas.width = w;
…然后重置上下文的累积转换
如何才能在不丢失转换的情况下最好地清除整个画布上下文?像您这样跟踪所有转换信息大概是其他几个人到目前为止所做的事情(比如cake.js和我自己的库)。我认为这样做对于任何大型画布库来说都是不可避免的 cake.js的Ilmari甚至向mozilla抱怨: 您可以围绕清除方法调用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
这难道不能满足您的要求吗?对于那些希望跟踪其完整上下文转换的人,这里是我的代码,用于按需、按上下文进行跟踪。本文的开头介绍了如何根据变换后的坐标清除整个矩形。你可以在我的网站上看到
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());
}
}
最简单的方法是存储缩放和平移,然后自己计算边界矩形,但人们希望有更好的方法。@JakubHampl这就是我正在做的,因为我已经在跟踪变换,并添加了从屏幕空间到画布空间的变换方法,但这似乎是一个很好的机会来指出这两种清理方法的问题,看看是否有更干净的东西;我试着想如何得到单位矩阵,但我想需要电流变换来计算逆矩阵,然后乘以它。是的,这应该很好。很高兴我能帮上忙。我还想感谢您对S.O.画布主题的所有贡献。这个示例非常好,对我帮助很大,但仍然有一个问题我无法解决:如何在redraw()中清除画布,如果你的图像在图像的几个点上旋转?@Kevkong与公认的答案完全相同:保存上下文转换,将转换重置为身份矩阵,清除0,0,宽度,高度,然后恢复转换。是的,你是对的,我只是拼错了“还原”一词无法按预期工作,transformedPoint在还原后返回了错误的点。谢谢你。