【问题标题】:Change anything thats allready drawn on canvas更改已在画布上绘制的任何内容
【发布时间】:2015-08-26 17:31:59
【问题描述】:

我有 2 个画布。我要做的是在第二个画布上绘制形状(即一条线)。当我想对这条绘制的线应用变换(旋转、缩放等)时,我会修改第一个画布的上下文并在上面画我的第二个画布。完美地工作。现在,当我想在第二个画布上再次绘制形状(即一条线)(带有变换)时,我在第二个画布上画了第一个画布并在上面画了一条线。工作得很好。现在问题发生了。当我再次想对这条线应用转换(旋转、缩放等)时,我修改了第一个画布的上下文并在上面绘制了第二个画布。但是这一次,当我在第一个画布上绘制时,我得到了突然的变化(绘制第二个画布)。这是由于在第二个画布上绘制第一个画布并再次将第二个画布绘制到第一个画布所应用的转换。有没有办法更改(重置或修改)已经在画布上绘制的任何内容?

var cantem = document.getElementById('canvasTemp1');  //second canvas
    var ctxtem = cantem.getContext('2d');

    var canMan = document.getElementById('canvasTempMan');    //first canvas
    canMan.style.visibility = "visible";
    var ctxcanman = canMan.getContext('2d');

    var sWidth = getCanvasWidth();               //returns canvas width
    var sHeight = getCanvasHeight();             //returns canvas height

    canMan.height = sHeight;
    canMan.width = sWidth;

    cantem.style.visibility = "hidden";



    ctxcanman.setTransform(1, 0, 0, 1, 0, 0);
    ctxcanman.clearRect(0, 0, cantem.width, cantem.height);

    ctxcanman.translate(sWidth / 2, sHeight / 2);


    ctxcanman.scale(ZoomFactor, ZoomFactor);
    ctxcanman.rotate(RotateAngle * Math.PI / 180);

    ctxcanman.translate(-sWidth / 2, -sHeight / 2);


    ctxcanman.drawImage(cantem, 0, 0, cantem.width, cantem.height, OffsetX, OffsetY, sWidth, sHeight);
    ctxcanman.save();

现在我在这里将我的第一个画布绘制到第二个-->

 var can = document.getElementById('canvasTempMan');
    can.style.visibility = "hidden";
    var cantem = document.getElementById('canvasTemp1');
    var ctxannotate = cantem.getContext("2d");
    ctxannotate.setTransform(1, 0, 0, 1, 0, 0);
    ctxannotate.clearRect(0, 0, cantem.width, cantem.height);

    ctxannotate.save();
    ctxannotate.drawImage(can, 0, 0, cantem.width, cantem.height, OffsetX, OffsetY, can.width, can.height);

我使用鼠标事件和简单的上下文函数(如 moveTo、lineTo 等)在我的第二个画布上绘制(形状即线条)。

【问题讨论】:

  • 阅读转换矩阵。它们可以保存对您的任何单个形状进行的所有累积变换(平移、旋转、缩放),并允许在以后需要继续变换任何形状时重新应用变换。
  • @markE 很好..但是可以在已经绘制的画布上重置转换吗??
  • 没有。已经在画布上绘制的任何内容都无法转换。 要改变画布上任何东西的位置,only 方法是: (#1) 清除画布,(#2) 计算形状的新位置,(# 3)在新位置重绘所有形状。第 2 步是变换矩阵有用的地方,因为它们让您“记住”所有先前的移动、缩放和形状旋转。 ;-)
  • 我的场景有点不同...1)我在画布上绘制..2)应用转换..3)再次绘制..4)并再次尝试转换之前绘制的所有内容...
  • 当然,您可以预先计算形状的下一个位置,但是要在画布上直观地应用这些变换,您必须清除画布并在新位置重新绘制所有形状。同样,如果不清除和重绘,画布上的任何东西都不能重新定位……画布上的形状永远不能重新定位。 :-)

标签: javascript html canvas


【解决方案1】:

画布中没有元素。在画布上绘制的内容通常不能被隔离(除非您谈论的是单个像素操作)。

您可以将所有内容以对象的形式存储在代码中,而不是将您的工作(形状、旋转和运动)存储在画布上,然后您可以单独处理这些对象,甚至可以进一步操作甚至删除。

如果您“记录”所有动作,您将完全控制画布上显示的内容。

例如,您可以有一个创建线条的函数:

function myLine (xStart, yStart, xEnd, yEnd, deg) {
    this.xS = xStart;
    this.yS = yStart;
    this.xE = xEnd;
    this.xE = yEnd;

    //if needed you can also save the number of degrees that the line has been rotated
    this.deg = deg;
}

只需在开始时创建一个空数组

var myLines = new Array();

并在其中添加您的行:

var newLine = new myLine(100,50,200,70,0);
myLines.push(newLine);

例如,圆圈也可以这样做

function myCircle(x,y,radius) {
    this.x = x;
    this.y = y;
    this.r = radius;
    //no point in trying to rotate a circle so leaving the degrees out
}

通过这种方式,通过存储您的作品,您可以通过循环遍历形状数组来一次绘制全部(或选定的部分)。

您仍然可以使用两个画布,一个显示所有绘制的形状,另一个显示与鼠标移动事件相关的操作,就像您在问题中描述的那样。

在 scale()/rotate()/translate() 处于活动状态时绘图

请看这里回答:Returning un-transformed mouse coordinates after rotating an object on html5 canvas

【讨论】:

  • 我怎样才能恢复已经应用到我的形状(在画布 2 上)并绘制的变换?...当我在第一个画布上绘制 canvas2 时??
  • 在你开始改变你的画布的旋转、缩放或变换之前,把它放在你的代码中:ctx.save(); 然后对画布做任何你想做的事情,但最后你将所有这些设置恢复到通过输入ctx.restore(); 保存您的状态。
  • 假设我以 100% 缩放系数绘制一条线;现在我以 300% 放大这条线并再次绘制另一条线。当我用 2 条线进一步放大此画布时,我会突然改变,因为线2 已经以 300% 的缩放系数绘制。
  • 这取决于你想要什么。即使在 100% 或 300% 缩放期间绘制的线仍然是线,对吗?当您最终缩小到 100% 时,您希望线条看起来相同,对吗?
  • 是的......所以你说的是将线坐标存储在一个数组中(我画了多少条线),然后使用这个线数组在画布上绘制,然后每次都应用转换? ...不是吗??
猜你喜欢
  • 2013-06-15
  • 1970-01-01
  • 2013-01-06
  • 1970-01-01
  • 1970-01-01
  • 2016-12-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多