如何使用canvas在图片上进行标注,以下代码不起作用,着实被坑到了(文末附完整代码)

今天发现一个有意思的问题:

如何使用canvas在图片上进行如下的标注,以下代码不起作用,如何修改

 

原始代码如下:

<!DOCTYPE html>
<html lang="en">
 
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
 
<body>
    <img id="myimg" src="./yidongbangong20240124103725.png"></img>
    <canvas id="mycanvas"></canvas>
 
 
    <script>
        const resData = {
            data: {
                cont: [{
                    pos: [10, 20, 33, 40],
                    cont: "数据标注"
                }]
            }
        }
 
        const img = document.getElementById("myimg");
        const canvas = document.getElementById("mycanvas");
        // 调整画布大小
        const ctx = canvas.getContext("2d");
        canvas.width = img.width;
        canvas.height = img.height;
 
        console.log(1);
        // 根据数据循环生成标注框
 
        ctx.strokeStyle = "red";
        // 画布上显示图片
        ctx.drawImage(img, 0, 0, img.width, img.height);
        // 计算缩小比率
        const widthrat = (img.naturalWidth - img.width) / img.width;
        const heightrat = (img.naturalHeight - img.height) / img.height;
        resData.data.cont.forEach(value => {
            // 获取标注框的x、y坐标
            const x = value.pos[0] * widthrat;
            const y = value.pos[1] * heightrat;
            // 获取标注框的宽、高
            const wid = (value.pos[2] - value.pos[0]) * widthrat;
            const hei = (value.pos[3] - value.pos[1]) * heightrat;
            // 根据获取的数据绘制描边矩形
            
            ctx.rect(x, y, wid, hei);
 
            // 绘制描边矩形上的红色填充矩形,并稍微调整样式
            ctx.fillStyle = "red";
            ctx.fillRect(x, y - 20, ctx.measureText(value.cont).width + 20, 20);
 
            // 绘制填充矩形上的白色文字,并调整坐标
            ctx.fillStyle = '#fff';
            ctx.font = "16px Arial";
            ctx.fillText(value.cont, x + 10, y - 4);
        })
        ctx.stroke()
    </script>
</body>
 
</html>

为此,特意去网上补充了一下canvas的知识,下面是canvas的画图语法:

  • drawImage(image,x,y)

 可以知道,把一张图片画到canvas上面,具体例子如下:

<img id="img" src="logo.jpg" alt="The Scream" width="325" height="200"><p>Canvas:</p>
<canvas id="myCanvas" width="250" height="300" style="border:1px solid #eee;">
您的浏览器不支持 HTML5 canvas 标签。</canvas>

var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var img = document.getElementById("img");
ctx.drawImage(img, 10, 10);

 如果你也是用这个例子运行的话,也是不能运行出结果的

经过调试原始代码之后,我发现里面取到的img组件的width和height都是0

为什么都是0呢,会不会是img没有加载呢?

当然不是,因为界面都显示出来了

对于经验丰富的开发人员来说,很快就会想出原因,因为我不是专门的前端。

我实现之后才总结出原因,就是因为img是异步加载的,当我们使用canvas绘制的时候,img如果还没有加载完成,那么取到的width和height肯定都是0,因此我们需要等待图片加载完成后才能获取到宽和高。

类似解决方案代码如下:

var img = document.getElementById("img");

img.onload = function() {
	ctx.drawImage(img, 10, 10);
}

完整代码:

<!DOCTYPE html>
<html lang="en">
 
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
 
<body>
    <img id="myimg" src="./CSDN封面/tomcat.png" width="200" height="200" onload="draw()"></img>
    <canvas id="mycanvas"></canvas>
 
 
    <script>
      function draw() { // 图片加载下载完毕时才进行标注
          const resData = {
              data: {
                  cont: [{
                      pos: [10, 20, 33, 40],
                      cont: "数据标注"
                  }]
              }
          }
   
          const img = document.getElementById("myimg");
          const canvas = document.getElementById("mycanvas");
          // 调整画布大小
          const ctx = canvas.getContext("2d");
          canvas.width = img.width;
          canvas.height = img.height;
   
          console.log(1);
          // 根据数据循环生成标注框
   
          ctx.strokeStyle = "red";
          // 画布上显示图片
          ctx.drawImage(img, 0, 0, img.width, img.height);
          // 计算缩小比率
          const widthrat = (img.naturalWidth - img.width) / img.width;
          const heightrat = (img.naturalHeight - img.height) / img.height;
          resData.data.cont.forEach(value => {
              // 获取标注框的x、y坐标
              const x = value.pos[0] * widthrat;
              const y = value.pos[1] * heightrat;
              // 获取标注框的宽、高
              const wid = (value.pos[2] - value.pos[0]) * widthrat;
              const hei = (value.pos[3] - value.pos[1]) * heightrat;
              // 根据获取的数据绘制描边矩形
              
              ctx.rect(x, y, wid, hei);
   
              // 绘制描边矩形上的红色填充矩形,并稍微调整样式
              ctx.fillStyle = "red";
              ctx.fillRect(x, y - 20, ctx.measureText(value.cont).width + 20, 20);
   
              // 绘制填充矩形上的白色文字,并调整坐标
              ctx.fillStyle = '#fff';
              ctx.font = "16px Arial";
              ctx.fillText(value.cont, x + 10, y - 4);
          })
          ctx.stroke()
        }
    </script>
</body>
 
</html>

问题来源:

https://ask.csdn.net/questions/8102015

  • 8
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
非常抱歉,我之前理解错了您的问题。如果您需要在小程序中将image标签覆盖在canvas标签之上,可以通过以下步骤实现: 1. 在wxml中添加image和canvas标签: ```html <image src="图片地址" style="position: absolute; z-index: 1; left: 0; top: 0; width: 100%; height: 100%;"></image> <canvas canvas-id="myCanvas" style="position: absolute; z-index: 2; left: 0; top: 0; width: 100%; height: 100%;"></canvas> ``` 其中,image标签使用了position: absolute属性使其可以覆盖在canvas标签之上,z-index属性指定了其层级,left、top、width、height属性设置了其大小和位置。 2. 在js文件中获取canvas的上下文(context),并在canvas绘制其它图形或文字: ```javascript const ctx = wx.createCanvasContext('myCanvas'); ctx.setFillStyle('red'); ctx.fillRect(10, 10, 50, 50); ctx.setFontSize(20); ctx.fillText('Hello World', 100, 100); ctx.draw(); ``` 完整示例代码如下: ```html <image src="图片地址" style="position: absolute; z-index: 1; left: 0; top: 0; width: 100%; height: 100%;"></image> <canvas canvas-id="myCanvas" style="position: absolute; z-index: 2; left: 0; top: 0; width: 100%; height: 100%;"></canvas> ``` ```javascript const ctx = wx.createCanvasContext('myCanvas'); ctx.setFillStyle('red'); ctx.fillRect(10, 10, 50, 50); ctx.setFontSize(20); ctx.fillText('Hello World', 100, 100); ctx.draw(); ``` 注意:在小程序中,image标签的层级是高于canvas标签的,因此需要使用z-index属性指定它们的层级关系。此外,为了使image标签和canvas标签覆盖在同一个位置,它们的left、top、width、height属性需要设置相同的值。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

svygh123

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值