如何在动态上绘制 canvas

how to make drawable on dynamic canvas

我根据数据库中的记录动态显示 canvas。目前我有 数据库中有两条记录,它在 page.Now 中显示了两个 canvas 我应该可以绘制 在两个 cannvas 上,但是我只能在最后一个 canvas 上绘制,而不是在两个 canvas 上绘制。 请查看图片 https://ibb.co/n7rvdk5 了解更多信息。 我得到 id 609,610.It 可以是 1,2 等等。这个 id 传递给 canvas id 以使其唯一。

<div class="snap-field col-sm-12" style="height: 450px;"> 

    loop here
    <canvas data-fieldid="{{$draw->id}}"  
        id="image-canvas-{{$draw->id}}"
        width="400" height="200"  
        class="image-canvas"
        style="position:absolute;">
    </canvas>
  

</div>

这是我的 js 部分,在 document.ready 函数中我加载了 canvas 。 initEditableImageCanvas 采用唯一标识。例如,在这种情况下,它需要 609 并且 610.I 可以在 ID 为 610 的 canvas 上绘制,但不能在 609.Maybe 上绘制 我需要在这里进行一些更改,我不确定我应该做什么

<script>
    var canvas, ctx, flag = false,
    prevX = 0,
    currX = 0,
    prevY = 0,
    currY = 0,
    dot_flag = false;

var x = "red",
    y = 2;

function initEditableImageCanvas(fieldId) {

    canvas = document.getElementById('image-canvas-' + fieldId);
    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);



}

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();

        }
    }

}
$(document).ready(function() {
    $(".image-canvas").each(function(canvas) {
        //get id 
        initEditableImageCanvas($(this).data("fieldid"));
    });
});
</script>

我正在寻求帮助来修复它。我要抽取全部 canvas。 有什么帮助吗?谢谢

为了利用 canvas,您可以将其存储在一个变量中,以便能够应用您的逻辑。

let canvas = document.getElementById('canvasId');
let ctx = canvas.getContext('2d')
/*   
   Logic   
*/

但是,在您的情况下,由于 canvasctx 是全局变量,因此每次在 jQuery 中调用 initEditableImageCanvas() 时都会重新分配它们s each().

因此,即使每当一个事件(即 mousemove)发生时都会调用函数 findxy(),但仅在正确的位置绘制是不够的。你 必须检查它是否指向右侧 canvas.


这就是说,为了防止意外行为,在处理多个可绘制对象 canvas 时,更喜欢使用用 let 语句定义的局部变量而不是全局变量。一种解决方案如下:

  1. 更改 var -> let
  2. 将第三个参数 (c) 添加到 findxy()
  3. draw()添加一个参数(ctx)

// get rid of global canvas and ctx    
var flag = false,
  prevX = 0,
  currX = 0,
  prevY = 0,
  currY = 0,
  dot_flag = false;

var x = "red",
  y = 2;

function initEditableImageCanvas(fieldId) {
  // use let
  let canvas = document.getElementById('editable-image-canvas-' + fieldId);
  ctx = canvas.getContext("2d");
  w = canvas.width;
  h = canvas.height;
  /* 
     Attach this to each findxy 
  */
  canvas.addEventListener("mousemove", function(e) {
    findxy('move', e, this)
  }, false);
  canvas.addEventListener("mousedown", function(e) {
    findxy('down', e, this)
  }, false);
  canvas.addEventListener("mouseup", function(e) {
    findxy('up', e, this)
  }, false);
  canvas.addEventListener("mouseout", function(e) {
    findxy('out', e, this)
  }, false);



}

function draw(ctx) {
  // added parameter ctx
  ctx.beginPath();
  ctx.moveTo(prevX, prevY);
  ctx.lineTo(currX, currY);
  ctx.strokeStyle = x;
  ctx.lineWidth = y;
  ctx.stroke();
  ctx.closePath();
}



function findxy(res, e, c) {
  // added parameter c and local ctx
  let ctx = c.getContext('2d')

  if (res == 'down') {

    prevX = currX;
    prevY = currY;
    currX = e.clientX - c.getBoundingClientRect().left;
    currY = e.clientY - c.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 - c.getBoundingClientRect().left;
      currY = e.clientY - c.getBoundingClientRect().top;
      draw(ctx); // added argument

    }
  }

}
$(document).ready(function() {
  $(".editable-image-canvas").each(function(canvas) {
    // alert($(this).data("fieldid")) //give id 609 and 610
    initEditableImageCanvas($(this).data("fieldid"));
  });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="snap-field col-sm-12" style="height: 450px;"> <div style="display:grid;"> <span>609</span> <canvas data-fieldid="609" id="editable-image-canvas-609" width="200" height="150" class="editable-image-canvas" style="position:relative;top:10%;border:1px dotted; margin-bottom:30px;"> </canvas> <span>610</span> <canvas data-fieldid="610" id="editable-image-canvas-610" width="200" height="150" class="editable-image-canvas" style="position:relative;top:10%;border:1px dotted;"> </canvas> </div><input type="hidden" name="field_{{$draw->id}}" id="editable-image-hidden-{{$draw->id}}"></div>