如何将div标签放在画布上

3
我想知道,如何将通过ajax动态生成的div标签放置在画布上。
我只是用ajax创建了div标签,并将生成的div添加到jsp页面上的另一个div标签中。我希望将主要的div添加到画布上。
提前感谢。
3个回答

5

你不能直接将HTML渲染到画布上。相反,一种方法是使用包含要渲染内容的SVG图像。

要绘制HTML内容,您可以使用一个包含HTML的<foreignObject>元素,然后将该SVG图像绘制到画布上。

var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');

var data = '<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200">' +
  '<foreignObject width="100%" height="100%">' +
  '<div xmlns="http://www.w3.org/1999/xhtml" style="font-size:40px">' +
  '<em>I</em> like ' +
  '<span style="color:white; text-shadow:0 0 2px blue;">' +
  'cheese</span>' +
  '</div>' +
  '</foreignObject>' +
  '</svg>';

var DOMURL = window.URL || window.webkitURL || window;

var img = new Image();
var svg = new Blob([data], {
  type: 'image/svg+xml;charset=utf-8'
});
var url = DOMURL.createObjectURL(svg);

img.onload = function() {
  ctx.drawImage(img, 0, 0);
  DOMURL.revokeObjectURL(url);
}

img.src = url;

您可以在此处找到更多信息。


限制

这种方法有很多限制:

  • IE Edge以下浏览器根本不支持<foreignObject>,所以这根本行不通+它会污染画布, 即使结果是一个空矩形,因为这些浏览器一旦在其上绘制任何svg图像就会如此,出于安全原因。

  • 一些浏览器(至少Safari 9)会因安全原因而在画布上绘制<foreignObject>时对其进行污染。

  • 某些元素渲染得很奇怪(<button>在FF中没有任何样式,<video>在某些UA上只是一个奇怪的东西...)。

  • 没有外部资源会被加载到<img>元素中,图片必须首先转换为dataURL,样式必须直接附加到svg中,或者内联在HTML标签中,字体必须dataURL编码。

因此,如果您不介意使用库,则最好的方法仍然是使用html2canvas

如果您不想使用库,那么您可以尝试做它所做的事情:
使用本机画布绘图方法绘制每个HTML元素及其样式。


@Jatin_g:是的,它可以。 - T.J. Crowder
我不想将 div 转化为图片,因为我使用 jsPlumb 在生成的 div 之间绘制了一条线,并在该线上应用了某些悬停和单击事件,现在我将其转换为图像,那么这些事件如何工作呢? - jatin_ghataliya
如果您有符合我的要求的链接示例,请在此处分享。我根据您的评论得到了一些想法。感谢您为我花费宝贵的时间。再次感谢。 - jatin_ghataliya
@Kaiido 谢谢你提醒我。你能编辑一下回复吗? :) - toskv
1
@toskv 刚刚完成了编辑,请审核一下,你可能不会批准...此外,我会写信给 MDN 的工作人员,因为这篇文章不应该在这里,这更像是一个 hack 而不是解决问题的真正方法。 - Kaiido
显示剩余5条评论

2
< p > 画布实际上不能“包含”div标签(或任何其他HTML标记),它是一个可以绘制的绘图表面。 < /p >

但是,您可以在z顺序中定位

标记,例如:

// Lower
var ctx = document.getElementById("lower-canvas").getContext('2d');
var path = new Path2D();
path.arc(100, 100, 100, 0, Math.PI * 2, true);
ctx.fillStyle = ctx.strokeStyle = "blue";
ctx.fill(path);

// Upper
ctx = document.getElementById("upper-canvas").getContext('2d');
path = new Path2D();
path.arc(75, 75, 50, 0, Math.PI * 2, true);
ctx.fillStyle = ctx.strokeStyle = "green";
ctx.fill(path);
#lower-canvas, #upper-canvas {
  width: 300px;
  height: 300px;
  position: absolute;
  left: 20px;
  top: 20px;
}
#upper-canvas {
  z-index: 2;
}
#the-div {
  position: absolute;
  left: 20px;
  top: 50px;
  z-index: 1;
  background-color: white;
}
<canvas id="lower-canvas" width="300" height="300"></canvas>
<canvas id="upper-canvas" width="300" height="300"></canvas>
<div id="the-div">This is the div</div>

在这个例子中,我们甚至不需要使用z-index,因为div已经被绝对定位,但canvas没有被定位,并且默认情况下,定位元素在比未定位元素更靠近观察者的层上。如果您正在定位画布,您需要添加类似于z-index: 10的东西(使用适当的值),以确保div在定位层的顺序中更靠近观察者。

@Jatin_g:然后就变得很麻烦了,你需要为想要在div上方的位图和想要在div下方的位图分别创建不同的画布。 - T.J. Crowder
但我有一些其他的要求,需要按照我所提到的来做。 - jatin_ghataliya
我能用canvas替换div吗? - jatin_ghataliya
@Jatin_g:不,坦率地说,听起来你应该使用SVG而不是画布。 SVG元素是元素,你可以在它们上面挂钩事件。你也可以看看Raphael.js。 - T.J. Crowder
但是当我缩小页面时,箭头位置会改变到页面的另一侧,并且箭头也会移动。因此,我认为我需要将div放在画布上。 - jatin_ghataliya
显示剩余2条评论

2
< p > Canvas 是一个 HTML 元素,可以使用脚本语言(通常是 JavaScript)来绘制图形。因此,无法在 canvas 元素内添加元素,但您可以使用 CSS 的 position 属性来移动 div 元素在 canvas 内部的位置。

<div class="container">
<canvas id="myCanvas" width="200" height="100"></canvas>
<div id="myDiv"></div>
</div>

CSS:

.container{postion: relative;}
#myCanvas{background: red;}
#myDiv{height: 50px;width: 50px;background: blue;
position: absolute; top:10px;
}

see JSFIDLE


感谢您的回复和花费时间。 - jatin_ghataliya
我的回答对你有用吗? - elreeda
哎呀,不对。我想把 div 标签放进画布里。 - jatin_ghataliya

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接