前端Vue3實(shí)現(xiàn)圖片標(biāo)點(diǎn)兩種方式總結(jié)
前言
公司的業(yè)務(wù)要求可以在圖片的位置上面進(jìn)行標(biāo)點(diǎn),然后在現(xiàn)場(chǎng)對(duì)汽車桌椅可以實(shí)現(xiàn)按照標(biāo)點(diǎn)進(jìn)行質(zhì)量檢測(cè)。
技術(shù)棧
圖像標(biāo)點(diǎn)
- 將畫布覆蓋在圖像上;
- 將圖像畫在畫布上;
目前采用的是畫布覆蓋在圖像上,畫布覆蓋在圖像上這種方式也有兩種:
- 將畫布的大小調(diào)整為圖像渲染的大?。?/li>
- 將畫布分解為顆粒,分散在圖像上面;
圖像基本概念
圖像大小有兩個(gè)概念:固定尺寸和渲染的大小。
固定尺寸就是圖像真實(shí)的分辨率大?。?/p>
渲染的大小則是圖像在網(wǎng)頁(yè)渲染后的分辨率大??;
因此畫布按照?qǐng)D像大小繪制的話,可能存在渲染的大小并非和圖像真實(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)擊事件是用來(lái)記錄鼠標(biāo)在圖片點(diǎn)擊的坐標(biāo),從而在其上面做一些操作,這里分別在圖片或畫布上面都做點(diǎn)擊監(jiān)控,是因?yàn)榈谝淮萎嫴技虞d渲染的大小和后面展示在頁(yè)面的大小不一致。
畫布使用相對(duì)位置布局 position: absolute;
并且配置以圖片左上角頂點(diǎn)為原點(diǎn)向右往下繪制畫布 top: 0; left: 0;
,是為了保證畫布與圖像完全重疊在一起,從而坐標(biāo)可以一一對(duì)應(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ù)來(lái)接受或后續(xù)使用,詳情請(qǐng)看代碼注釋。
3.根據(jù)圖像渲染大小繪制畫布
/** * 根據(jù)圖像大小繪制畫布 */ async function drawImageToCanvas() { // 獲取圖片元素 image.value = document.getElementById('img-1'); // 獲取圖片在頁(yè)面渲染的大小 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ù)主要是用來(lái)獲取頁(yè)面渲染的圖片,并將圖片渲染的大小獲取到,將其值賦值給畫布的寬高,從而把畫布與圖片的大小一致,從而進(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)擊事件是用來(lái)記錄鼠標(biāo)在圖片點(diǎn)擊的坐標(biāo),從而在其上面做一些操作,這里只在圖片上面做了點(diǎn)擊監(jiān)控,從而保證可以分散創(chuàng)建畫布。
這里的思路是通過(guò)相對(duì)布局將畫布都掛載到父元素上面,因此這里為父元素定義了唯一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ù)來(lái)接受或后續(xù)使用,詳情請(qǐng)看代碼注釋。
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è)置文本對(duì)齊方式(左、中、右) 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添加到頁(yè)面中 container.appendChild(canvas); }
這里最大的特點(diǎn)就是通過(guò)設(shè)置Canvas的樣式來(lái)將一小塊畫布放在圖片上面:
// 設(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)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue實(shí)現(xiàn)手機(jī)端省市區(qū)區(qū)域選擇
這篇文章主要為大家詳細(xì)介紹了vue實(shí)現(xiàn)手機(jī)端省市區(qū)區(qū)域選擇,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-09-09vue3鼠標(biāo)拖拽滑動(dòng)效果實(shí)現(xiàn)demo
這篇文章主要為大家介紹了vue3鼠標(biāo)拖拽滑動(dòng)效果實(shí)現(xiàn)demo,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-12-12vue vue-Router默認(rèn)hash模式修改為history需要做的修改詳解
今天小編就為大家分享一篇vue vue-Router默認(rèn)hash模式修改為history需要做的修改詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-09-09Vue 讀取HTMLCollection列表的length為0問(wèn)題
這篇文章主要介紹了Vue 讀取HTMLCollection列表的length為0問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-06-06解決vue單頁(yè)面多個(gè)組件嵌套監(jiān)聽瀏覽器窗口變化問(wèn)題
這篇文章主要介紹了解決vue單頁(yè)面多個(gè)組件嵌套監(jiān)聽瀏覽器窗口變化問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-07-07Vue-cli proxyTable 解決開發(fā)環(huán)境的跨域問(wèn)題詳解
本篇文章主要介紹了Vue-cli proxyTable 解決開發(fā)環(huán)境的跨域問(wèn)題詳解,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2017-05-05vue中實(shí)現(xiàn)圖片壓縮 file文件的方法
這篇文章主要介紹了vue中實(shí)現(xiàn)圖片壓縮 file文件的方法,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-05-05Vue+ElementUI?封裝簡(jiǎn)易PaginationSelect組件的詳細(xì)步驟
這篇文章主要介紹了Vue+ElementUI?封裝簡(jiǎn)易PaginationSelect組件,這里簡(jiǎn)單介紹封裝的一個(gè)Pagination-Select組件幾個(gè)步驟,結(jié)合示例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2022-08-08vue實(shí)現(xiàn)鼠標(biāo)移過(guò)出現(xiàn)下拉二級(jí)菜單功能
這篇文章主要介紹了vue實(shí)現(xiàn)鼠標(biāo)移過(guò)出現(xiàn)下拉二級(jí)菜單功能,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-12-12