用插件VMarker在vue中給圖片加標記

插件VMarker:Vmarker是基于ui-picture-bd-marker的vue封裝,當Vmarker不足并存在現(xiàn)有要求或難以基于Vmarker擴展,此時可以繞過Vmarker進行擴展,直接使用ui-picture-bd-marker擴展即可。

使用方法:

1.安裝依賴

npm install vue-picture-bd-marker

2.在vue文件中引入Vmarker,為VMarker設定別名并作為組件引入

注:css樣式已經(jīng)在Vue-picture-BD-Marker中引用過了

<template>
  <div>
    <el-form
        id="el-form"
        ref="testForm"
        label-position="left"
        label-width="130px"
      >
        <el-form-item
          v-for="(item,index) in testForm.sign"
          :key="index"
          :label="`標記${index + 1}`"
          style="margin:20px 0"
        >
         <div :id="index" ref="imageWrapper" class="signBox">
            <div class="sign-main" :class="`main${index}`">
              <div v-show="currentImg.length === 0" class="placeHolder" @click="limitMarkRight(index)" />
              <ui-marker
                  v-if="currentImg.length !== 0"
                  :ref="`aiPanel-editor${index}`"
                  class="ai-observer"
                  :class="`cs${index}`"
                  :img-url="currentImg[index]"
                  :read-only="readOnly[index]"
                  @vmarker:onUpdated="onUpdated(index)"
                  @vmarker:onImageLoad="onImageLoad(index)"
                  @vmarker:onDrawOne="onDrawOne(index)"
                  @vmarker:onReady="onReady(index)"
                  @vmarker:selectOne="selectOne"
                  @click.native="changeBack(index)"
              />
             <div class="sign-footer
                <el-button type="primary" size="mini" @click="handleImgChange(index)">重新編輯</el-button>
              </div>
            </div>
          </div>
      </el-form-item>
      <el-form-item align="center">
        <el-button@click="submitForm">確認創(chuàng)建</el-button>
      </el-form-item>
    </el-form>
   </div>
</template>
import {Aimarker} from 'Vue-Picture-BD-Marker'
export default {
  components: { 'ui-marker': AiMarker },
  data() {
    testForm: {
      sign : ['圖片地址1', '圖片地址2', '圖片地址3']    
    },
    currentImg: [],
    readOnly: []
  }
}

3.操作說明

1.加載圖片
用屬性imgUrl可以加載url或者base64的圖片

<ui-marker ref="aiPanel-editor" class="ai-observer" 
    v-bind:uniqueKey="uuid"
    :ratio="16/9" 
    :imgUrl="url或base64">
</ui-marker>

當圖片加載完成后,vmarker會發(fā)送一個onImageLoad 的事件,即this.$emit('vmarker:omImageLoad',rawData, uuid),其中,rawData包含圖片的原始寬高和現(xiàn)有寬高

2.標注
當在圖片上畫矩形框后,需要對該標注進行備注,以指示該標注代表的含義。此時可以使用vmarker控件的getMarker方法獲取marker實例,再通過marker的實例方法setTag針對選中的矩形框進行標注。 marker可以通過控件的getMarker方法進行獲取。vmarker控件自身也有setTag方法。
setTag接收一個名稱或一個對象

this.$refs['aiPanel-editor'].getMarker().setTag({
    tagName: "小蜜蜂",
    tag: "0x0001"
  });

this.$refs['aiPanel-editor'].setTag({
    tagName: "小蜜蜂",
    tag: "0x0001"
  });

3.獲取元數(shù)據(jù)
getData獲取的數(shù)據(jù)為一個數(shù)組

this.$refs['aiPanel-editor'].getMarker().getData();

獲取的數(shù)據(jù)

[
  {
    tag: "id04",
    tagName: "蜜蜂",
    position: {
      x: "41.026%",
      y: "22.678%",
      x1: "53.790000000000006%",
      y1: "40.496%"
    },
    uuid: "42BA3F7114C8B50D"
  }
]

4.加載標注數(shù)據(jù)
renderData操作會將數(shù)據(jù)標注到圖上,這意味著多次執(zhí)行renderData之后,會出現(xiàn)多次標注。 如果需要清空畫布,可以調(diào)用marker.clearData()進行清空。
renderData(data,wh)參數(shù)為標注數(shù)據(jù)組成的數(shù)組,基準寬高【可選】

this.$refs['aiPanel-editor'].getMarker().renderData([
    {
      tag: "id04",
      tagName: "蜜蜂",
      position: {
        x: "41.026%",
        x1: "53.790000000000006%",
        y: "22.678%",
        y1: "40.496%"
      },
      uuid: "5559A20B25712D9D"
    }
  ]);

清除數(shù)據(jù)

this.$refs['aiPanel-editor'].getMarker().clearData();

5.屬性說明
readOnly
為true時不可編輯,僅做展示

ratio
圖形的寬高比,默認為16/9, 圖為當設置為4 / 3的效果
好像無效

uniqueKey
識別控件唯一性,當頁面存在多個控件時需要區(qū)分。默認未設置。

6.事件
vmarker:onUpdated
@vmarker:onUpdated = onUpdated(index)
當標注框位置或者標框?qū)傩园l(fā)生改動時回調(diào),參數(shù)為data【標注數(shù)據(jù)】, uniqueKey
可以在這個事件里改變標注的css樣式

onUpdated(index) {
      const box = document.getElementById(index)
      const div = box.querySelector('.annotation')
      const annotate = box.querySelector('.annotate.vmr-ai-raw-image-mask')
     div.style.borderRadius = '50%'
      div.style.borderColor = 'rgb(255,0,0)'
      div.style.borderWidth = '2px'
      annotate.addEventListener('click', () => {
        const children = div.querySelectorAll('.resize-dot')
        children.forEach(item => { item.classList.add('hidden') })
      })
      div.addEventListener('click', e => {
        e.stopPropagation()
      })
    },

@vmarker:onDrawOne= 'onDrawOne(index)'
當畫完一個標注框時回調(diào),參數(shù)為data【標注數(shù)據(jù)】, uniqueKey

 onDrawOne(index) {
      this.total = 0
      this.$refs[ `aiPanel-editor${index}` ][0].getMarker().setTag({
        tagName: '',
        tag: ''
      })
      //當你想限制標記個數(shù)時
      const markBox = document.getElementById(index)
      const markers = markBox.querySelectorAll('.annotation')
      for (let i = 0; i < markers.length; i++) {
        if (markers[i].clientWidth !== 0) {
          this.total++
        }
        if (this.total >= 2) {
          this.$message.warning('此圖只可標記一處,若想標記第二處請點擊加號按鈕')
          markers[i].remove()
        }
      }
    },

uniqueKey 識別控件唯一性,當頁面存在多個控件時需要區(qū)分 默認值:無
readOnly 是否只作顯示 默認值:false
width 寬(單位:像素、百分比) 默認值:100%
ratio 控件寬高比例 默認值:16/9
imgUrl 圖片url 默認值:無
vmarker:onImageLoad 圖片加載完成后回調(diào),不包含data:image格式?;卣{(diào)參數(shù),data={rawW,rawH,currentW,currentH}
vmarker:onReady 當控件準備完成后回調(diào),參數(shù)為uniqueKey
vmarker:onDrawOne 當畫完一個標注框時回調(diào),參數(shù)為data【標注數(shù)據(jù)】, uniqueKey
vmarker:onSelect 當選中圖片上的標注框時回調(diào),參數(shù)為data【標注數(shù)據(jù)】, uniqueKey
vmarker:onUpdated 當標注框位置或者標框?qū)傩园l(fā)生改動時回調(diào),參數(shù)為data【標注數(shù)據(jù)】, uniqueKey
vmarker:onDataRendered 當標注框主動渲染數(shù)據(jù)后時回調(diào),參數(shù)為uniqueKey

7.修改標記區(qū)域的寬高比和圖片一樣
方法:

 adjustmentRatio(index) {
      const div = document.querySelector(`.cs${index}`)
      const dom1 = div.querySelector('.vmr-ai-raw-image-mask')
      const dom2 = div.querySelector('.vmr-g-image')
      const dom3 = div.querySelector('.vmr-ai-raw-image')
      const img = new Image()
      img.onload = function() {
        const h = img.naturalHeight
        const w = img.naturalWidth
        this.cal = w / h
        const x = div.clientWidth / this.cal
        div.style.height = x + 'px'
        dom1.style.height = x + 'px'
        dom2.style.height = x + 'px'
        dom3.style.height = x + 'px'
      }
      img.src = dom3.src
    },

watch監(jiān)聽當currentImg改變時觸發(fā)方法

 watch: {
    currentImg: {
      handler(newValue, oldValue) {
        for (let i = 0; i < newValue.length; i++) {
          this.$nextTick(() => {
            // this.changeBack(i)
            this.adjustmentRatio(i)
          })
        }
      },
      deep: true
    }
 }
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容