如何避免在更改画布元素时清除它's容器's innerHtml

How to avoid clearing canvas element on changing it's container's innerHtml

本文关键字:清除 innerHtml 容器 元素 何避免 布元素      更新时间:2023-09-26

我正在使用javascript绘制div中的画布元素,该元素包含在包装器中。画布及其div是通过添加到包装器的innerHTML中动态生成的。目标是允许生成无限数量的画布

<div id="wrapper">
     <div id="container"><canvas id="previous"></canvas></div>
     <!-- infinite # of container divs & canvases -->
</div>

然而,当我将一个新的div和画布添加到包装器的innerHTML中时,任何绘制到上一个画布的内容都会丢失。

如果我在页面的其他地方添加一个新的画布,添加到容器外部的div或容器的子级:

<div id="wrapper">
     <div id="container"><canvas id="previous"></canvas></div>
</div>
<div id="wrapper2">
     <!-- newly inserted canvas: -->
     <div id="container"><canvas></canvas></div>
</div>

或:

<div id="wrapper">
     <div id="container"><canvas id="previous"></canvas></div>
     <div id="wrapperChild">
          <!-- newly inserted canvas: -->
          <div id="container"><canvas></canvas></div>
     </div>
</div>

然后保留上一个画布。

根据我所知,更改包装器或其父级的innerHTML会导致清除画布。关于如何避免清理画布,有什么建议吗?我能把画布上画的东西保存在其他地方并修复吗?

无论您的javascript方法(jQuery、其他方法或什么都不使用)如何,您都可以通过不使用innerHTML来实现这一点。基本上,当您附加到innerHTML属性时,你说的是"取innerHTML的值,将其添加到这个新值(可能是画布元素)中,然后将innerHTML设置为所有这些。换句话说,你并没有真正附加"就位"。你基本上是在添加所有内容的新版本,因为画布没有用子元素绘制其内容,所以它们不会被这个方法带入。

您不应该使用innerHTML,而应该使用DOM,将子级作为节点而不是字符串附加到父级。

听起来这是jQuery的一个很好的用例。使用jquery,可以将<canvas>元素附加到任意容器中,从而避免与"innerHtml"交互。

例如:

var myCanvas = $("<canvas>").appendTo("#container");

这样做的目的是向id为"container"(您的div)的元素添加一个新的<canvas>元素。"#"是id的css选择器。谷歌"css选择器",因为这是一个相当广泛的主题。

myCanvas变量现在是一个jQuery数组,其中包含对刚才添加的画布的引用。myCanvas[0]将是您可以与之交互的实际DOM元素。

使用这种方法,您将永远不需要更改div的"innerHtml",因此现有画布将永远不会被触摸/清除。

不使用innerHtml,而是使用appendChild:

document.getElementById('wrapper').appendChild(NewNodeHere);

查看Simon关于绘制形状的教程。http://simonsarris.com/project/canvasdemo/shapes.html

形状的所有属性和位置都存储在对象数组中。当发生类似(单击形状)的事件时,画布的状态会发生变化(在这种情况下,拖动的是一个形状),对于鼠标位置的每次变化,画布都会使用新的坐标和属性重新绘制。

现在,如果你也使用形状、图像和文本对象,你也可以将它们的属性存储在对象数组中。这样,只需多次迭代数组,就可以以相同的方式在多个画布上绘制相同的形状。

因此,当您动态添加新画布时,您可以简单地重新绘制以前的上下文。

这是Simon教程中的相关代码:

您定义了一个矩形形状(构造函数)

function Shape(x, y, w, h, fill) {
  this.x = x || 0;
  this.y = y || 0;
  this.w = w || 1;
  this.h = h || 1;
  this.fill = fill || '#AAAAAA';
}

根据给定上下文绘制此形状Shape.prototype.draw=函数(ctx){ctx.fillStyle=this.fill;ctx.fillRect(this.x,this.y,this.w,this.h);}

向阵列添加新形状

CanvasState.prototype.addShape = function(shape) {
  this.shapes.push(shape);
  this.valid = false;
}

遍历数组并相应地绘制所有形状的

var l = shapes.length;
for (var i = 0; i < l; i++) {
  var shape = shapes[i];
  // We can skip the drawing of elements that have moved off the screen:
  if (shape.x > this.width || shape.y > this.height ||
      shape.x + shape.w < 0 || shape.y + shape.h < 0) continue;
  shapes[i].draw(ctx);
}