当前位置:首页 » 《随便一记》 » 正文

【前端】Vue3实现图片标点

9 人参与  2024年12月09日 16:01  分类 : 《随便一记》  评论

点击全文阅读


前言

公司的业务要求可以在图片的位置上面进行标点,然后在现场对汽车桌椅可以实现按照标点进行质量检测。

技术栈

Vue3:https://cn.vuejs.org/index.htmlAnt Design Vue4.x:https://www.antdv.com/docs/vue/introduce-cn

图像标点

将画布覆盖在图像上;将图像画在画布上;

目前采用的是画布覆盖在图像上,画布覆盖在图像上这种方式也有两种:

将画布的大小调整为图像渲染的大小;将画布分解为颗粒,分散在图像上面;

图像基本概念

图像大小有两个概念:固定尺寸和渲染的大小。
固定尺寸就是图像真实的分辨率大小;
渲染的大小则是图像在网页渲染后的分辨率大小;
因此画布按照图像大小绘制的话,可能存在渲染的大小并非和图像真实的大小相同。
在这里插入图片描述

效果图

在这里插入图片描述

方式一:画布全局覆盖图像

根据图像大小绘制画布监控图像或画布点击绘制圆点和序号

1.编写前端显示代码

<div style="position: relative">    <img id="img-1" src="/Img/image/1530088404487.jpg" @click="handleClickImg1"/>    <canvas id="canvas-1" style="position: absolute; top: 0; left: 0;" @click="handleClickImg1" /></div>

这里定义了 handleClickImg1 点击事件是用来记录鼠标在图片点击的坐标,从而在其上面做一些操作,这里分别在图片或画布上面都做点击监控,是因为第一次画布加载渲染的大小和后面展示在页面的大小不一致。

画布使用相对位置布局 position: absolute; 并且配置以图片左上角顶点为原点向右往下绘制画布 top: 0; left: 0;,是为了保证画布与图像完全重叠在一起,从而坐标可以一一对应上。

2.配置基本数据

// 图片基本信息const image = ref();const imageWidth = ref(0);const imageHeight = ref(0);// 画布const canvas = ref();const ctx = ref();// 记录点击点const proQualityList1 = ref([]);

定义一些参数来接受或后续使用,详情请看代码注释。

3.根据图像渲染大小绘制画布

/** * 根据图像大小绘制画布 */async function drawImageToCanvas() {    // 获取图片元素    image.value = document.getElementById('img-1');    // 获取图片在页面渲染的大小    imageWidth.value = image.value.clientWidth;    imageHeight.value = image.value.clientHeight;    // 获取画布元素    canvas.value = document.getElementById('canvas-1');    // 设置画布的大小于图片渲染大小一致    canvas.value.width = imageWidth.value;    canvas.value.height = imageHeight.value;    // 获取二维画布    ctx.value = canvas.value.getContext("2d");}

**Tip:**个人喜好把独立函数定义为异步,异步函数调试可能会进不了断点。

drawImageToCanvas 异步函数主要是用来获取页面渲染的图片,并将图片渲染的大小获取到,将其值赋值给画布的宽高,从而把画布与图片的大小一致,从而进行绘画。

4.在画布绘圆

/** * 在画布绘制圆点 */const drawOriginPoint = (x, y, color) => {    const radius = 8;    ctx.value.beginPath();    ctx.value.arc(x, y, radius, 0, 2 * Math.PI, false);    ctx.value.fillStyle = color;    ctx.value.fill();};

5.在画布绘序号

/** * 在画布绘制序号 */const drawSnPoint = (sn, x, y, color) => {    ctx.value.font = '14px Arial';    ctx.value.fillStyle = color;    ctx.value.textAlign = 'center';    ctx.value.textBaseline = 'middle';    ctx.value.fillText(sn, x, y);};

6.处理图片点击

/** * 图片点击:处理画布全局覆盖 */function handleClickImg(e) {    drawImageToCanvas();    let dataset = e.target.dataset    proQualityList1.value.push({        sn: proQualityList1.value.length + 1,         positionX: e.offsetX || e.layerX,         positionY: e.offsetY || e.layerY,    });    for(let item of proQualityList1.value) {        drawOriginPoint(item.positionX, item.positionY, '#f00');        drawSnPoint(item.sn, item.positionX, item.positionY, '#fff');    }}

方式二:画布分散覆盖图像

监控图像或画布点击根据点击坐标创建画布绘制圆点和序号

1.编写前端显示代码

<div style="position: relative" id="canvas-2">    <img id="img-2" src="/Img/image/1530088404487.jpg" @click="handleClickImg2"/></div>

这里定义了 handleClickImg2 点击事件是用来记录鼠标在图片点击的坐标,从而在其上面做一些操作,这里只在图片上面做了点击监控,从而保证可以分散创建画布。

这里的思路是通过相对布局将画布都挂载到父元素上面,因此这里为父元素定义了唯一id id="canvas-2"

2.配置基本数据

// 图片基本信息const image = ref();const imageWidth = ref(0);const imageHeight = ref(0);// 画布const canvas = ref();const ctx = ref();// 记录点击点const proQualityList2 = ref([]);

定义一些参数来接受或后续使用,详情请看代码注释。

3.在画布绘圆

/** * 在画布绘制圆点 */const drawOriginPoint = (x, y, color) => {    const radius = 8;    ctx.value.beginPath();    ctx.value.arc(x, y, radius, 0, 2 * Math.PI, false);    ctx.value.fillStyle = color;    ctx.value.fill();};

4.在画布绘序号

/** * 在画布绘制序号 */const drawSnPoint = (sn, x, y, color) => {    ctx.value.font = '14px Arial';    ctx.value.fillStyle = color;    ctx.value.textAlign = 'center';    ctx.value.textBaseline = 'middle';    ctx.value.fillText(sn, x, y);};

5.创建画布

/** * 创建画布 */function createCanvas(sn, x, y, color) {    let canvas = document.createElement('canvas');    // 设置Canvas的固定宽度和高度    canvas.width = 24;    canvas.height = 24;    // 设置Canvas的样式    canvas.style.position = 'absolute';    canvas.style.top = `${y}px`;    canvas.style.left = `${x}px`;    let ctx = canvas.getContext('2d');    // 圆点半径,可以根据需要调整    const radius = 8;    ctx.beginPath();    ctx.arc(canvas.width / 2, canvas.height / 2, radius, 0, 2 * Math.PI, false);    // 设置填充颜色    ctx.fillStyle = color[0];    ctx.fill();    // 文字样式设置    ctx.font = '14px Arial';    // 设置填充颜色    ctx.fillStyle = color[1];    // 设置文本对齐方式(左、中、右)    ctx.textAlign = 'center';    // 设置文本基线(上、中、下等)    ctx.textBaseline = 'middle';    // 绘制数字    ctx.fillText(sn, canvas.width / 2, canvas.height / 2);    // 获取要插入Canvas的容器    let container = document.getElementById(`canvas-2`);    // @ts-ignore 将Canvas添加到页面中    container.appendChild(canvas);}

这里最大的特点就是通过设置Canvas的样式来将一小块画布放在图片上面:

// 设置Canvas的样式canvas.style.position = 'absolute';canvas.style.top = `${y}px`;canvas.style.left = `${x}px`;

6.处理图片点击

/** * 图片点击:处理画布分散覆盖 */function handleClickImg2(e) {    let dataset = e.target.dataset    proQualityList2.value.push({        sn: proQualityList.value.length + 1,         positionX: e.offsetX || e.layerX,         positionY: e.offsetY || e.layerY,    });    createCanvas(proQualityList2.value.length, e.offsetX || e.layerX, e.offsetY || e.layerY, ['#f00', '#fff'])}

点击全文阅读


本文链接:http://zhangshiyu.com/post/198697.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1