无法在多个画布上绘制
Posted
技术标签:
【中文标题】无法在多个画布上绘制【英文标题】:unable to draw on multiple canvas 【发布时间】:2021-10-26 02:01:21 【问题描述】:如何加载多个画布并在其上启用绘图。目前,它在我的页面上显示了两个画布,但我只能在一个画布上绘制。
我在数据库中有两条记录。 foreach
下面的循环制作了两个画布,但我只能在一个画布上绘制,而不能在两个画布上绘制。我应该能够在两个画布上画画,这就是我想要的东西。我正在寻找有关我应该如何做的任何帮助或任何提示,以便我可以在动态生成的所有画布上绘图。
<body onload="init()">
<canvas id="can_$draw->id"
style="position:absolute;top:10%;left:10%;border:2px solid;">
</canvas>
</body>
下面是允许用户在画布图像上绘制的js代码
<script type="text/javascript">
var canvas, ctx, flag = false,
prevX = 0,
currX = 0,
prevY = 0,
currY = 0,
dot_flag = false;
var x = "red",
y = 2;
function init()
for(let i=1;i<3;i++)
canvas = document.getElementById('can_'+i);
ctx = canvas.getContext("2d");
w = canvas.width;
h = canvas.height;
//
canvas.addEventListener("mousemove", function (e)
findxy('move', e)
, false);
canvas.addEventListener("mousedown", function (e)
findxy('down', e)
, false);
canvas.addEventListener("mouseup", function (e)
findxy('up', e)
, false);
canvas.addEventListener("mouseout", function (e)
findxy('out', e)
, false);
//end of for
function draw()
ctx.beginPath();
ctx.moveTo(prevX, prevY);
ctx.lineTo(currX, currY);
ctx.strokeStyle = x;
ctx.lineWidth = y;
ctx.stroke();
ctx.closePath();
function findxy(res, e)
if (res == 'down')
prevX = currX;
prevY = currY;
currX = e.clientX - canvas.getBoundingClientRect().left;
currY = e.clientY - canvas.getBoundingClientRect().top;
flag = true;
dot_flag = true;
if (dot_flag)
ctx.beginPath();
ctx.fillStyle = x;
ctx.fillRect(currX, currY, 2, 2);
ctx.closePath();
dot_flag = false;
if (res == 'up' || res == "out")
flag = false;
if (res == 'move')
if (flag)
prevX = currX;
prevY = currY;
currX = e.clientX - canvas.getBoundingClientRect().left;
currY = e.clientY -canvas.getBoundingClientRect().top;
draw();
</script>
【问题讨论】:
你在后端注入的那些画布的 ID 是什么 $draw->id 在循环中给出 id 1 和 2 可能是因为您也只有一个正在绘制的上下文。ctx = canvas.getContext("2d");
我认为这会覆盖一个,因为您试图将一个变量分配给两个画布。也许分配一个 ctx1 和 ctx2 看看是否可以。
你的意思是 ctx1 = canvas.getContext("2d");和 ctx2 = canvas.getContext("2d");在 init() 函数中。如果我这样做,我认为我必须编写函数 double 例如 draw() 函数一个具有 ctx1 和另一个具有 ctx2
我添加了一个您可以尝试的选项的答案
【参考方案1】:
尝试类似的方法。将上下文添加到数组中,看看是否可以同时绘制。不完全确定上下文是你的问题,但我认为是。
let canvas1 = document.getElementById("c1");
let canvas2 = document.getElementById("c2");
let ctx1 = canvas1.getContext("2d");
let ctx2 = canvas2.getContext("2d");
let ctx = [ctx1, ctx2];
function draw()
ctx.forEach((ctx, i) =>
ctx.fillStyle = "lightblue";
ctx.fillRect(10, 10, 100, 100)
);
draw()
<canvas id='c1'></canvas>
<canvas id='c2'></canvas>
添加@Kaiido 所说的性能
let canvas1 = document.getElementById("c1");
let canvas2 = document.getElementById("c2");
let ctx1 = canvas1.getContext("2d");
let ctx2 = canvas2.getContext("2d");
ctx1.fillStyle = "lightblue";
ctx1.fillRect(50, 50, 100, 100)
ctx2.drawImage(canvas1, 0, 0)
<canvas id='c1'></canvas>
<canvas id='c2'></canvas>
【讨论】:
如果他们真的想在两个上下文中绘制相同的东西,最好只执行一次然后drawImage
更新的画布覆盖另一个,而不是复制绘图命令。但我不认为这是他们真正想要的。据我了解,他们想要两个独立的绘图板。
@Kaiido 我明白你在说什么。我添加了一个例子。
但更好地阅读他们的问题,我觉得最后他们只是错过了canvas
在循环中被替换,并且他们的findXY
调用不会得到正确的画布。他们应该重写它以使其更加面向对象,并且每个绘图板都是它自己的实例,拥有自己的变量。如果你有时间教他们怎么做……我不会;-p【参考方案2】:
这是一个利用我们知道哪个画布生成鼠标事件这一事实的解决方案。既然我们知道这一点,我们就可以使用它来获取正确画布的上下文。
我显示 mousemove 和 mousedown 的消息,指示哪个画布触发了事件。
<!doctype html>
<html>
<head>
<script>
"use strict";
var canvas, ctx, flag = false,
prevx = 0,
curx = 0,
prevy = 0,
cury = 0,
dot_flag = false;
var x = "red",
y = 2;
window.addEventListener('load', onLoaded, false);
function onLoaded(evt)
let canvasElems = document.querySelectorAll('canvas');
canvasElems.forEach(
can =>
can.addEventListener('mousemove', function(evt) findxy('move', evt, this);, false);
can.addEventListener('mousedown', function(evt) findxy('down', evt, this);, false);
can.addEventListener('mouseup', function(evt) findxy('up', evt, this);, false);
can.addEventListener('mouseout', function(evt) findxy('out', evt, this);, false);
);
function findxy(reason, evt, elem)
if (reason=='up' || reason=='out')
flag = false;
if (reason == 'down')
document.querySelector('#output').textContent = elem.getAttribute('name') + ' was clicked';
prevx = curx;
prevy = cury;
curx = evt.clientX - elem.getBoundingClientRect().left;
cury = evt.clientY - elem.getBoundingClientRect().top;
flag = true;
dot_flag = true;
//if (dot_flag)
//
let ctx = elem.getContext('2d');
ctx.beginPath();
ctx.fillStyle = x;
ctx.fillRect(curx, cury, 2, 2);
ctx.closePath();
dot_flag = false;
//
else if (reason == 'move')
document.querySelector('#output').textContent = elem.getAttribute('name') + ' was moved over';
if (flag)
prevx = curx;
prevy = cury;
curx = evt.clientX - elem.getBoundingClientRect().left;
cury = evt.clientY - elem.getBoundingClientRect().top;
draw(elem);
function draw(tgtCanvas)
let ctx = tgtCanvas.getContext('2d');
ctx.beginPath();
ctx.moveTo(prevx, prevy);
ctx.lineTo(curx, cury);
ctx.strokeStyle = x;
ctx.lineWidth = y;
ctx.stroke();
ctx.closePath();
</script>
<style>
canvas
margin: 4px;
border: solid 1px #333;
</style>
</head>
<body>
<canvas name='canvas1'></canvas><canvas name='canvas2'></canvas>
</br>
<span id='output'></span>
</body>
</html>
【讨论】:
以上是关于无法在多个画布上绘制的主要内容,如果未能解决你的问题,请参考以下文章