前端Vue3實(shí)現(xiàn)圖片標(biāo)點(diǎn)兩種方式總結(jié)
前言
公司的業(yè)務(wù)要求可以在圖片的位置上面進(jìn)行標(biāo)點(diǎn),然后在現(xiàn)場對汽車桌椅可以實(shí)現(xiàn)按照標(biāo)點(diǎn)進(jìn)行質(zhì)量檢測。
技術(shù)棧
圖像標(biāo)點(diǎn)
- 將畫布覆蓋在圖像上;
- 將圖像畫在畫布上;
目前采用的是畫布覆蓋在圖像上,畫布覆蓋在圖像上這種方式也有兩種:
- 將畫布的大小調(diào)整為圖像渲染的大小;
- 將畫布分解為顆粒,分散在圖像上面;
圖像基本概念
圖像大小有兩個(gè)概念:固定尺寸和渲染的大小。
固定尺寸就是圖像真實(shí)的分辨率大??;
渲染的大小則是圖像在網(wǎng)頁渲染后的分辨率大?。?/p>
因此畫布按照圖像大小繪制的話,可能存在渲染的大小并非和圖像真實(shí)的大小相同。

效果圖

方式一:畫布全局覆蓋圖像
- 根據(jù)圖像大小繪制畫布
- 監(jiān)控圖像或畫布點(diǎn)擊
- 繪制圓點(diǎn)和序號(hào)
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 點(diǎn)擊事件是用來記錄鼠標(biāo)在圖片點(diǎn)擊的坐標(biāo),從而在其上面做一些操作,這里分別在圖片或畫布上面都做點(diǎn)擊監(jiān)控,是因?yàn)榈谝淮萎嫴技虞d渲染的大小和后面展示在頁面的大小不一致。
畫布使用相對位置布局 position: absolute; 并且配置以圖片左上角頂點(diǎn)為原點(diǎn)向右往下繪制畫布 top: 0; left: 0;,是為了保證畫布與圖像完全重疊在一起,從而坐標(biāo)可以一一對應(yīng)上。
2.配置基本數(shù)據(jù)
// 圖片基本信息 const image = ref(); const imageWidth = ref(0); const imageHeight = ref(0); // 畫布 const canvas = ref(); const ctx = ref(); // 記錄點(diǎn)擊點(diǎn) const proQualityList1 = ref([]);
定義一些參數(shù)來接受或后續(xù)使用,詳情請看代碼注釋。
3.根據(jù)圖像渲染大小繪制畫布
/**
* 根據(jù)圖像大小繪制畫布
*/
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');
// 設(shè)置畫布的大小于圖片渲染大小一致
canvas.value.width = imageWidth.value;
canvas.value.height = imageHeight.value;
// 獲取二維畫布
ctx.value = canvas.value.getContext("2d");
}
**Tip:**個(gè)人喜好把獨(dú)立函數(shù)定義為異步,異步函數(shù)調(diào)試可能會(huì)進(jìn)不了斷點(diǎn)。
drawImageToCanvas 異步函數(shù)主要是用來獲取頁面渲染的圖片,并將圖片渲染的大小獲取到,將其值賦值給畫布的寬高,從而把畫布與圖片的大小一致,從而進(jìn)行繪畫。
4.在畫布繪圓
/**
* 在畫布繪制圓點(diǎn)
*/
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.在畫布繪序號(hào)
/**
* 在畫布繪制序號(hào)
*/
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.處理圖片點(diǎn)擊
/**
* 圖片點(diǎn)擊:處理畫布全局覆蓋
*/
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');
}
}
方式二:畫布分散覆蓋圖像
- 監(jiān)控圖像或畫布點(diǎn)擊
- 根據(jù)點(diǎn)擊坐標(biāo)創(chuàng)建畫布
- 繪制圓點(diǎn)和序號(hào)
1.編寫前端顯示代碼
<div style="position: relative" id="canvas-2">
<img id="img-2" src="/Img/image/1530088404487.jpg" @click="handleClickImg2"/>
</div>
這里定義了 handleClickImg2 點(diǎn)擊事件是用來記錄鼠標(biāo)在圖片點(diǎn)擊的坐標(biāo),從而在其上面做一些操作,這里只在圖片上面做了點(diǎn)擊監(jiān)控,從而保證可以分散創(chuàng)建畫布。
這里的思路是通過相對布局將畫布都掛載到父元素上面,因此這里為父元素定義了唯一id id="canvas-2"。
2.配置基本數(shù)據(jù)
// 圖片基本信息 const image = ref(); const imageWidth = ref(0); const imageHeight = ref(0); // 畫布 const canvas = ref(); const ctx = ref(); // 記錄點(diǎn)擊點(diǎn) const proQualityList2 = ref([]);
定義一些參數(shù)來接受或后續(xù)使用,詳情請看代碼注釋。
3.在畫布繪圓
/**
* 在畫布繪制圓點(diǎn)
*/
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.在畫布繪序號(hào)
/**
* 在畫布繪制序號(hào)
*/
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.創(chuàng)建畫布
/**
* 創(chuàng)建畫布
*/
function createCanvas(sn, x, y, color) {
let canvas = document.createElement('canvas');
// 設(shè)置Canvas的固定寬度和高度
canvas.width = 24;
canvas.height = 24;
// 設(shè)置Canvas的樣式
canvas.style.position = 'absolute';
canvas.style.top = `${y}px`;
canvas.style.left = `${x}px`;
let ctx = canvas.getContext('2d');
// 圓點(diǎn)半徑,可以根據(jù)需要調(diào)整
const radius = 8;
ctx.beginPath();
ctx.arc(canvas.width / 2, canvas.height / 2, radius, 0, 2 * Math.PI, false);
// 設(shè)置填充顏色
ctx.fillStyle = color[0];
ctx.fill();
// 文字樣式設(shè)置
ctx.font = '14px Arial';
// 設(shè)置填充顏色
ctx.fillStyle = color[1];
// 設(shè)置文本對齊方式(左、中、右)
ctx.textAlign = 'center';
// 設(shè)置文本基線(上、中、下等)
ctx.textBaseline = 'middle';
// 繪制數(shù)字
ctx.fillText(sn, canvas.width / 2, canvas.height / 2);
// 獲取要插入Canvas的容器
let container = document.getElementById(`canvas-2`);
// @ts-ignore 將Canvas添加到頁面中
container.appendChild(canvas);
}
這里最大的特點(diǎn)就是通過設(shè)置Canvas的樣式來將一小塊畫布放在圖片上面:
// 設(shè)置Canvas的樣式
canvas.style.position = 'absolute';
canvas.style.top = `${y}px`;
canvas.style.left = `${x}px`;
6.處理圖片點(diǎn)擊
/**
* 圖片點(diǎn)擊:處理畫布分散覆蓋
*/
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'])
}總結(jié)
到此這篇關(guān)于前端Vue3實(shí)現(xiàn)圖片標(biāo)點(diǎn)兩種方式的文章就介紹到這了,更多相關(guān)前端Vue3圖片標(biāo)點(diǎn)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue實(shí)現(xiàn)手機(jī)端省市區(qū)區(qū)域選擇
這篇文章主要為大家詳細(xì)介紹了vue實(shí)現(xiàn)手機(jī)端省市區(qū)區(qū)域選擇,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-09-09
vue3鼠標(biāo)拖拽滑動(dòng)效果實(shí)現(xiàn)demo
這篇文章主要為大家介紹了vue3鼠標(biāo)拖拽滑動(dòng)效果實(shí)現(xiàn)demo,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-12-12
vue vue-Router默認(rèn)hash模式修改為history需要做的修改詳解
今天小編就為大家分享一篇vue vue-Router默認(rèn)hash模式修改為history需要做的修改詳解,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-09-09
Vue 讀取HTMLCollection列表的length為0問題
這篇文章主要介紹了Vue 讀取HTMLCollection列表的length為0問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-06-06
解決vue單頁面多個(gè)組件嵌套監(jiān)聽瀏覽器窗口變化問題
這篇文章主要介紹了解決vue單頁面多個(gè)組件嵌套監(jiān)聽瀏覽器窗口變化問題,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-07-07
Vue-cli proxyTable 解決開發(fā)環(huán)境的跨域問題詳解
本篇文章主要介紹了Vue-cli proxyTable 解決開發(fā)環(huán)境的跨域問題詳解,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2017-05-05
vue中實(shí)現(xiàn)圖片壓縮 file文件的方法
這篇文章主要介紹了vue中實(shí)現(xiàn)圖片壓縮 file文件的方法,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-05-05
Vue+ElementUI?封裝簡易PaginationSelect組件的詳細(xì)步驟
這篇文章主要介紹了Vue+ElementUI?封裝簡易PaginationSelect組件,這里簡單介紹封裝的一個(gè)Pagination-Select組件幾個(gè)步驟,結(jié)合示例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2022-08-08
vue實(shí)現(xiàn)鼠標(biāo)移過出現(xiàn)下拉二級(jí)菜單功能
這篇文章主要介紹了vue實(shí)現(xiàn)鼠標(biāo)移過出現(xiàn)下拉二級(jí)菜單功能,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-12-12

