无法在多个画布上绘制

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>

【讨论】:

以上是关于无法在多个画布上绘制的主要内容,如果未能解决你的问题,请参考以下文章

无法在画布上绘制垂直虚线

为啥我无法在画布上正确绘制 [重复]

无法在javascript中将图像绘制到画布

使用 Chrome 在画布上本地绘制图像

ViewFlipper:在视图上绘制画布

调度触摸事件到画布上绘制的视图