前端Vue3實現(xiàn)圖片標點兩種方式總結(jié)
前言
公司的業(yè)務(wù)要求可以在圖片的位置上面進行標點,然后在現(xiàn)場對汽車桌椅可以實現(xiàn)按照標點進行質(zhì)量檢測。
技術(shù)棧
圖像標點
- 將畫布覆蓋在圖像上;
- 將圖像畫在畫布上;
目前采用的是畫布覆蓋在圖像上,畫布覆蓋在圖像上這種方式也有兩種:
- 將畫布的大小調(diào)整為圖像渲染的大小;
- 將畫布分解為顆粒,分散在圖像上面;
圖像基本概念
圖像大小有兩個概念:固定尺寸和渲染的大小。
固定尺寸就是圖像真實的分辨率大??;
渲染的大小則是圖像在網(wǎng)頁渲染后的分辨率大??;
因此畫布按照圖像大小繪制的話,可能存在渲染的大小并非和圖像真實的大小相同。
效果圖
方式一:畫布全局覆蓋圖像
- 根據(jù)圖像大小繪制畫布
- 監(jiān)控圖像或畫布點擊
- 繪制圓點和序號
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
點擊事件是用來記錄鼠標在圖片點擊的坐標,從而在其上面做一些操作,這里分別在圖片或畫布上面都做點擊監(jiān)控,是因為第一次畫布加載渲染的大小和后面展示在頁面的大小不一致。
畫布使用相對位置布局 position: absolute;
并且配置以圖片左上角頂點為原點向右往下繪制畫布 top: 0; left: 0;
,是為了保證畫布與圖像完全重疊在一起,從而坐標可以一一對應(yīng)上。
2.配置基本數(shù)據(jù)
// 圖片基本信息 const image = ref(); const imageWidth = ref(0); const imageHeight = ref(0); // 畫布 const canvas = ref(); const ctx = ref(); // 記錄點擊點 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:**個人喜好把獨立函數(shù)定義為異步,異步函數(shù)調(diào)試可能會進不了斷點。
drawImageToCanvas
異步函數(shù)主要是用來獲取頁面渲染的圖片,并將圖片渲染的大小獲取到,將其值賦值給畫布的寬高,從而把畫布與圖片的大小一致,從而進行繪畫。
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'); } }
方式二:畫布分散覆蓋圖像
- 監(jiān)控圖像或畫布點擊
- 根據(jù)點擊坐標創(chuàng)建畫布
- 繪制圓點和序號
1.編寫前端顯示代碼
<div style="position: relative" id="canvas-2"> <img id="img-2" src="/Img/image/1530088404487.jpg" @click="handleClickImg2"/> </div>
這里定義了 handleClickImg2
點擊事件是用來記錄鼠標在圖片點擊的坐標,從而在其上面做一些操作,這里只在圖片上面做了點擊監(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(); // 記錄點擊點 const proQualityList2 = ref([]);
定義一些參數(shù)來接受或后續(xù)使用,詳情請看代碼注釋。
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.創(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'); // 圓點半徑,可以根據(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); }
這里最大的特點就是通過設(shè)置Canvas的樣式來將一小塊畫布放在圖片上面:
// 設(shè)置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']) }
總結(jié)
到此這篇關(guān)于前端Vue3實現(xiàn)圖片標點兩種方式的文章就介紹到這了,更多相關(guān)前端Vue3圖片標點內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue vue-Router默認hash模式修改為history需要做的修改詳解
今天小編就為大家分享一篇vue vue-Router默認hash模式修改為history需要做的修改詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-09-09Vue 讀取HTMLCollection列表的length為0問題
這篇文章主要介紹了Vue 讀取HTMLCollection列表的length為0問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-06-06解決vue單頁面多個組件嵌套監(jiān)聽瀏覽器窗口變化問題
這篇文章主要介紹了解決vue單頁面多個組件嵌套監(jiān)聽瀏覽器窗口變化問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-07-07Vue-cli proxyTable 解決開發(fā)環(huán)境的跨域問題詳解
本篇文章主要介紹了Vue-cli proxyTable 解決開發(fā)環(huán)境的跨域問題詳解,非常具有實用價值,需要的朋友可以參考下2017-05-05Vue+ElementUI?封裝簡易PaginationSelect組件的詳細步驟
這篇文章主要介紹了Vue+ElementUI?封裝簡易PaginationSelect組件,這里簡單介紹封裝的一個Pagination-Select組件幾個步驟,結(jié)合示例代碼給大家介紹的非常詳細,需要的朋友可以參考下2022-08-08vue實現(xiàn)鼠標移過出現(xiàn)下拉二級菜單功能
這篇文章主要介紹了vue實現(xiàn)鼠標移過出現(xiàn)下拉二級菜單功能,本文給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下2019-12-12