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

本文主要是介绍如何使用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

这篇关于如何使用canvas在图片上进行标注,以下代码不起作用,着实被坑到了(文末附完整代码)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/983835

相关文章

使用Python删除Excel中的行列和单元格示例详解

《使用Python删除Excel中的行列和单元格示例详解》在处理Excel数据时,删除不需要的行、列或单元格是一项常见且必要的操作,本文将使用Python脚本实现对Excel表格的高效自动化处理,感兴... 目录开发环境准备使用 python 删除 Excphpel 表格中的行删除特定行删除空白行删除含指定

SpringBoot结合Docker进行容器化处理指南

《SpringBoot结合Docker进行容器化处理指南》在当今快速发展的软件工程领域,SpringBoot和Docker已经成为现代Java开发者的必备工具,本文将深入讲解如何将一个SpringBo... 目录前言一、为什么选择 Spring Bootjavascript + docker1. 快速部署与

深入理解Go语言中二维切片的使用

《深入理解Go语言中二维切片的使用》本文深入讲解了Go语言中二维切片的概念与应用,用于表示矩阵、表格等二维数据结构,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习吧... 目录引言二维切片的基本概念定义创建二维切片二维切片的操作访问元素修改元素遍历二维切片二维切片的动态调整追加行动态

prometheus如何使用pushgateway监控网路丢包

《prometheus如何使用pushgateway监控网路丢包》:本文主要介绍prometheus如何使用pushgateway监控网路丢包问题,具有很好的参考价值,希望对大家有所帮助,如有错误... 目录监控网路丢包脚本数据图表总结监控网路丢包脚本[root@gtcq-gt-monitor-prome

Python通用唯一标识符模块uuid使用案例详解

《Python通用唯一标识符模块uuid使用案例详解》Pythonuuid模块用于生成128位全局唯一标识符,支持UUID1-5版本,适用于分布式系统、数据库主键等场景,需注意隐私、碰撞概率及存储优... 目录简介核心功能1. UUID版本2. UUID属性3. 命名空间使用场景1. 生成唯一标识符2. 数

创建Java keystore文件的完整指南及详细步骤

《创建Javakeystore文件的完整指南及详细步骤》本文详解Java中keystore的创建与配置,涵盖私钥管理、自签名与CA证书生成、SSL/TLS应用,强调安全存储及验证机制,确保通信加密和... 目录1. 秘密键(私钥)的理解与管理私钥的定义与重要性私钥的管理策略私钥的生成与存储2. 证书的创建与

linux解压缩 xxx.jar文件进行内部操作过程

《linux解压缩xxx.jar文件进行内部操作过程》:本文主要介绍linux解压缩xxx.jar文件进行内部操作,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、解压文件二、压缩文件总结一、解压文件1、把 xxx.jar 文件放在服务器上,并进入当前目录#

SpringBoot中如何使用Assert进行断言校验

《SpringBoot中如何使用Assert进行断言校验》Java提供了内置的assert机制,而Spring框架也提供了更强大的Assert工具类来帮助开发者进行参数校验和状态检查,下... 目录前言一、Java 原生assert简介1.1 使用方式1.2 示例代码1.3 优缺点分析二、Spring Fr

Android kotlin中 Channel 和 Flow 的区别和选择使用场景分析

《Androidkotlin中Channel和Flow的区别和选择使用场景分析》Kotlin协程中,Flow是冷数据流,按需触发,适合响应式数据处理;Channel是热数据流,持续发送,支持... 目录一、基本概念界定FlowChannel二、核心特性对比数据生产触发条件生产与消费的关系背压处理机制生命周期

java使用protobuf-maven-plugin的插件编译proto文件详解

《java使用protobuf-maven-plugin的插件编译proto文件详解》:本文主要介绍java使用protobuf-maven-plugin的插件编译proto文件,具有很好的参考价... 目录protobuf文件作为数据传输和存储的协议主要介绍在Java使用maven编译proto文件的插件