Fabric.js 旧 canvas 的残余仍然存在
Fabric.js remnants of old canvas remain
我想把一个canvas的内容显示为另一个canvas的背景,然后在上面画一堆矩形。我需要动态改变:
- canvas 从中加载我的
finalcanvas
的背景图片
- 绘制哪些矩形
如果我从头开始这个过程是最简单的。我用一个简单的按钮从头开始模仿。然而,在重绘我的 canvas 之后,fabric.js 的先前信息在稍微拖动 canvas 的项目后仍然存在。这意味着旧的 canvas 没有被正确清除。我试过 .clear()
和 .depose()
,但无济于事。
如果描述含糊不清,这里有一张图片:
还有一个可重现的小例子:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Hello</title>
</head>
<body>
<canvas id="finalcanvas"></canvas>
<canvas id="backgroundcanvas" width="200" height="100"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/3.6.3/fabric.min.js" type="text/javascript"></script>
<script>
function load_plane_onto_active_canvas() {
var c = document.getElementById('backgroundcanvas');
var ctx = c.getContext("2d");
var bg = c.toDataURL("image/png");
var canvas = new fabric.Canvas('finalcanvas', {
width: 333,
height: 333
});
canvas.setBackgroundImage(bg, canvas.renderAll.bind(canvas));
canvas.on("mouse:over", function(e) {
console.log(e.target)
});
// add 100 rectangles
for (i = 0; i < 10; i++) {
for (j = 0; j < 10; j++) {
rect = new fabric.Rect({
width: 10,
height: 10,
left: j * 15,
top: i * 15,
fill: 'green',
})
canvas.add(rect);
}
}
}
window.onload = function() {
// fill the background canvas with red
(function() {
var canvas = document.getElementById("backgroundcanvas");
var ctx = canvas.getContext("2d");
ctx.fillStyle = "#FF0000";
ctx.fillRect(0, 0, 150, 75);
}())
load_plane_onto_active_canvas()
}
</script>
<button onclick="load_plane_onto_active_canvas()">click me</button>
</body>
</html>
希望有人能帮帮我!
请注意,您正在 load_plane_onto_active_canvas()
函数中创建 fabric.Canvas
的 new 实例。因此,当您单击按钮时,现有的 canvases 保持不变,并且您实际上是在新创建的 canvas 上调用 clear()
。 DOM 在这一点上变得混乱,有几个嵌套的 canvases 在彼此内部 - 你可以看一下 DOM 检查员看看。
您可以做的是只创建一次 canvas 实例,然后稍后在您的其他函数中使用对它的引用。
const finalCanvas = new fabric.Canvas("finalcanvas", {
width: 333,
height: 333
});
// finalCanvas now exists in the global (window) scope
function load_plane_onto_active_canvas() {
var c = document.getElementById("backgroundcanvas");
var ctx = c.getContext("2d");
var bg = c.toDataURL("image/png");
finalCanvas.clear();
finalCanvas.setBackgroundImage(bg, finalCanvas.renderAll.bind(finalCanvas));
finalCanvas.on("mouse:over", function (e) {
// console.log(e.target);
});
// add 100 rectangles
for (i = 0; i < 10; i++) {
for (j = 0; j < 10; j++) {
rect = new fabric.Rect({
width: 10,
height: 10,
left: j * 15,
top: i * 15,
fill: "green"
});
finalCanvas.add(rect);
}
}
}
window.onload = function () {
// fill the background canvas with red
(function () {
var canvas = document.getElementById("backgroundcanvas");
var ctx = canvas.getContext("2d");
ctx.fillStyle = "#FF0000";
ctx.fillRect(0, 0, 150, 75);
})();
load_plane_onto_active_canvas();
};
document.querySelector("#b1").onclick = () => load_plane_onto_active_canvas();
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/3.6.3/fabric.js"></script>
<canvas id="finalcanvas"></canvas>
<canvas id="backgroundcanvas" width="200" height="100"></canvas>
<button id="b1">start from scratch</button>
我想把一个canvas的内容显示为另一个canvas的背景,然后在上面画一堆矩形。我需要动态改变:
- canvas 从中加载我的
finalcanvas
的背景图片
- 绘制哪些矩形
如果我从头开始这个过程是最简单的。我用一个简单的按钮从头开始模仿。然而,在重绘我的 canvas 之后,fabric.js 的先前信息在稍微拖动 canvas 的项目后仍然存在。这意味着旧的 canvas 没有被正确清除。我试过 .clear()
和 .depose()
,但无济于事。
如果描述含糊不清,这里有一张图片:
还有一个可重现的小例子:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Hello</title>
</head>
<body>
<canvas id="finalcanvas"></canvas>
<canvas id="backgroundcanvas" width="200" height="100"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/3.6.3/fabric.min.js" type="text/javascript"></script>
<script>
function load_plane_onto_active_canvas() {
var c = document.getElementById('backgroundcanvas');
var ctx = c.getContext("2d");
var bg = c.toDataURL("image/png");
var canvas = new fabric.Canvas('finalcanvas', {
width: 333,
height: 333
});
canvas.setBackgroundImage(bg, canvas.renderAll.bind(canvas));
canvas.on("mouse:over", function(e) {
console.log(e.target)
});
// add 100 rectangles
for (i = 0; i < 10; i++) {
for (j = 0; j < 10; j++) {
rect = new fabric.Rect({
width: 10,
height: 10,
left: j * 15,
top: i * 15,
fill: 'green',
})
canvas.add(rect);
}
}
}
window.onload = function() {
// fill the background canvas with red
(function() {
var canvas = document.getElementById("backgroundcanvas");
var ctx = canvas.getContext("2d");
ctx.fillStyle = "#FF0000";
ctx.fillRect(0, 0, 150, 75);
}())
load_plane_onto_active_canvas()
}
</script>
<button onclick="load_plane_onto_active_canvas()">click me</button>
</body>
</html>
希望有人能帮帮我!
请注意,您正在 load_plane_onto_active_canvas()
函数中创建 fabric.Canvas
的 new 实例。因此,当您单击按钮时,现有的 canvases 保持不变,并且您实际上是在新创建的 canvas 上调用 clear()
。 DOM 在这一点上变得混乱,有几个嵌套的 canvases 在彼此内部 - 你可以看一下 DOM 检查员看看。
您可以做的是只创建一次 canvas 实例,然后稍后在您的其他函数中使用对它的引用。
const finalCanvas = new fabric.Canvas("finalcanvas", {
width: 333,
height: 333
});
// finalCanvas now exists in the global (window) scope
function load_plane_onto_active_canvas() {
var c = document.getElementById("backgroundcanvas");
var ctx = c.getContext("2d");
var bg = c.toDataURL("image/png");
finalCanvas.clear();
finalCanvas.setBackgroundImage(bg, finalCanvas.renderAll.bind(finalCanvas));
finalCanvas.on("mouse:over", function (e) {
// console.log(e.target);
});
// add 100 rectangles
for (i = 0; i < 10; i++) {
for (j = 0; j < 10; j++) {
rect = new fabric.Rect({
width: 10,
height: 10,
left: j * 15,
top: i * 15,
fill: "green"
});
finalCanvas.add(rect);
}
}
}
window.onload = function () {
// fill the background canvas with red
(function () {
var canvas = document.getElementById("backgroundcanvas");
var ctx = canvas.getContext("2d");
ctx.fillStyle = "#FF0000";
ctx.fillRect(0, 0, 150, 75);
})();
load_plane_onto_active_canvas();
};
document.querySelector("#b1").onclick = () => load_plane_onto_active_canvas();
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/3.6.3/fabric.js"></script>
<canvas id="finalcanvas"></canvas>
<canvas id="backgroundcanvas" width="200" height="100"></canvas>
<button id="b1">start from scratch</button>