日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > vue >内容正文

vue

vue js 图像标注 --- canvas 实现

發布時間:2023/12/20 vue 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 vue js 图像标注 --- canvas 实现 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

圖像標注

        • 需求
        • 打點式實現思路
        • 矩形框實現思路
        • 右鍵彈出刪除和添加備注菜單
        • 刪除選中內容
        • 更新備注

項目中碰到一個需要對圖像標注的功能,查了好幾個插件,但是感覺用起來有點頗為復雜而且和自己需要的功能不完全一致,于是就自己用canvas寫了一個簡單的:

需求

  • 兩種標注方式,一種是打點式標注,一種是矩形框標注
  • 打點式:單擊圖像打點,把每一個點用線連接起來,最后雙擊結束,形成一個閉環,并把所有坐標點記錄下來傳給后端
  • 矩形框:和其他標注工具一樣,鼠標隨意拖動,形成一個矩形框,并把四個角的坐標點記錄下來傳給后端
  • 在繪制的內容上右鍵高亮選中該內容并彈出菜單,可以刪除,可以更新備注
  • 使用打點式標注,鼠標變畫筆;使用矩形框標注,鼠標變十字

打點式實現思路

  • 創建canvas 并繪制和圖片一樣大的背景
  • 使用click事件獲取點擊的坐標,用fillRect方法繪制一個直徑4像素的小矩形,作為點(也可以做圓形)
  • 把每次點擊的坐標存儲起來,點下一個坐標時,使用moveTo,lineTo方法連線
  • 雙擊時把最后一個坐標和第一個連起來

注意: 雙擊事件會觸發兩次單擊事件,需要處理一下,網上找的方法:

click(){clearTimeout(timer)timer = setTimeout(()=>{// xxx},200)}dbclick(){clearTimeout(timer)// xxxx}

打點式標注部分代碼

this.ctx.drawImage(this.image,0,0,this.w,this.h)// 繪制矩形小點 this.ctx.fillStyle="#FF0000"; this.ctx.fillRect(e.offsetX - 2, e.offsetY - 2, 4, 4);//連線 tempPointArr是儲存坐標點的數組,雙擊形成閉環后清空 this.ctx.beginPath() this.ctx.strokeStyle= '#FF0000' this.ctx.moveTo(this.tempPointArr[this.tempPointArr.length - 2].x,this.tempPointArr[this.tempPointArr.length - 2].y); this.ctx.lineTo(this.tempPointArr[this.tempPointArr.length - 1].x,this.tempPointArr[this.tempPointArr.length - 1].y); this.ctx.stroke();

矩形框實現思路

  • 使用mousedown mousemove mouseup 來完成
  • 在mousedown事件獲取開始的坐標
  • mousemove事件使用strokeRect畫矩形,但要注意先清空,再畫新的,否則會導致有很多矩形框
  • mouseup事件清空開始坐標,完成一個矩形框的繪制

鼠標按下時記錄當前canvas 內容,在每一次鼠標拖動時先還原之前干凈的canvas內容,再畫新的矩形,達到先清空再畫新矩形的目的

重點代碼:

mousedown(){this.imgData = this.ctx.getImageData(0,0,this.w,this.h) } mousemove(){this.ctx.putImageData(this.imgData,0,0) }

矩形框標注部分代碼

mousedown(){this.startPoint = {x:e.offsetX,y:e.offsetY}this.imgData = this.ctx.getImageData(0,0,this.w,this.h) }mousemove(){this.ctx.putImageData(this.imgData,0,0)this.ctx.beginPath()this.ctx.fillStyle = "rgba(255,0,0,0.1)";this.ctx.strokeStyle = '#FF0000';this.ctx.strokeRect(this.startPoint.x,this.startPoint.y,e.offsetX - this.startPoint.x,e.offsetY - this.startPoint.y); }mouseup(){this.startPoint = null }

右鍵彈出刪除和添加備注菜單

在有內容的地方才彈出,沒有內容的地方不彈
主要使用坐標點去判斷在不在某一個范圍內,之前把每一個繪制的內容都存儲成數組

思路:右鍵的坐標點必須滿足大于某個x點,小于另一個x點,大于某個y點,小于另一個y點,則表示在這個內容區域內

部分代碼

const index = this.pointData.findIndex((item)=>{let leftX = falselet rightX = falselet topY = falselet bottomY = falseitem.point.forEach(p=>{if(e.offsetX > p.x){leftX = true}if(e.offsetX < p.x){rightX = true}if(e.offsetY < p.y){bottomY = true}if(e.offsetY > p.y){topY = true}})return leftX && rightX && topY && bottomY}) if(index > -1){/**xxxxxx*/this.fillRect(this.pointData[index].point) //給這個區域填充背景色,表示高亮 }

刪除選中內容

思路:使用橡皮擦模擬實現刪除效果,canvas下面要有多一張背景圖,否則的話會直接擦成白色;
使用完后再使用其他功能切記要把globalCompositeOperation屬性從destination-out改回默認值 source-over

部分代碼

this.ctx.globalCompositeOperation = 'destination-out' //重點 /** ...重新繪制一次要刪除的內容 */ this.ctx.globalCompositeOperation = 'source-over'

更新備注

使用fillText方法添加文本
在添加新的文本前先清除掉之前寫的文本,主要使用clearRect方法

部分代碼

let textW = this.ctx.measureText(this.textObj[this.selectedIndex]).width this.ctx.clearRect(this.pointData[this.selectedIndex].point[0].x + 5,this.pointData[this.selectedIndex].point[0].y - 8 - 12 ,textW,13) this.ctx.font="12px Arial" this.ctx.fillStyle ='#FF0000' this.ctx.fillText(this.note,this.pointData[this.selectedIndex].point[0].x + 5,this.pointData[this.selectedIndex].point[0].y - 8)

大致思路到此為止

多次使用geiImageData putImageData 來實現保存某一步的內容,再顯示;
也可以利用這個實現撤銷的功能

如果需要完整的代碼可以去git 上下載一下,也希望有大佬可以幫忙優化一下代碼,感謝~~~
最后附上地址:

https://gitee.com/cuijinrong/project-gather/blob/master/src/components/marker.vue

總結

以上是生活随笔為你收集整理的vue js 图像标注 --- canvas 实现的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。