用插件VMarker在vue中给图片加标记

插件VMarker:Vmarker是基于ui-picture-bd-marker的vue封装,当Vmarker不足并存在现有要求或难以基于Vmarker扩展,此时可以绕过Vmarker进行扩展,直接使用ui-picture-bd-marker扩展即可。

使用方法:

1.安装依赖

npm install vue-picture-bd-marker

2.在vue文件中引入Vmarker,为VMarker设定别名并作为组件引入

注:css样式已经在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">确认创建</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会发送一个onImageLoad 的事件,即this.$emit('vmarker:omImageLoad',rawData, uuid),其中,rawData包含图片的原始宽高和现有宽高

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.获取元数据
getData获取的数据为一个数组

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

获取的数据

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

4.加载标注数据
renderData操作会将数据标注到图上,这意味着多次执行renderData之后,会出现多次标注。 如果需要清空画布,可以调用marker.clearData()进行清空。
renderData(data,wh)参数为标注数据组成的数组,基准宽高【可选】

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

清除数据

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

5.属性说明
readOnly
为true时不可编辑,仅做展示

ratio
图形的宽高比,默认为16/9, 图为当设置为4 / 3的效果
好像无效

uniqueKey
识别控件唯一性,当页面存在多个控件时需要区分。默认未设置。

6.事件
vmarker:onUpdated
@vmarker:onUpdated = onUpdated(index)
当标注框位置或者标框属性发生改动时回调,参数为data【标注数据】, 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)'
当画完一个标注框时回调,参数为data【标注数据】, uniqueKey

 onDrawOne(index) {
      this.total = 0
      this.$refs[ `aiPanel-editor${index}` ][0].getMarker().setTag({
        tagName: '',
        tag: ''
      })
      //当你想限制标记个数时
      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 识别控件唯一性,当页面存在多个控件时需要区分 默认值:无
readOnly 是否只作显示 默认值:false
width 宽(单位:像素、百分比) 默认值:100%
ratio 控件宽高比例 默认值:16/9
imgUrl 图片url 默认值:无
vmarker:onImageLoad 图片加载完成后回调,不包含data:image格式。回调参数,data={rawW,rawH,currentW,currentH}
vmarker:onReady 当控件准备完成后回调,参数为uniqueKey
vmarker:onDrawOne 当画完一个标注框时回调,参数为data【标注数据】, uniqueKey
vmarker:onSelect 当选中图片上的标注框时回调,参数为data【标注数据】, uniqueKey
vmarker:onUpdated 当标注框位置或者标框属性发生改动时回调,参数为data【标注数据】, uniqueKey
vmarker:onDataRendered 当标注框主动渲染数据后时回调,参数为uniqueKey

7.修改标记区域的宽高比和图片一样
方法:

 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监听当currentImg改变时触发方法

 watch: {
    currentImg: {
      handler(newValue, oldValue) {
        for (let i = 0; i < newValue.length; i++) {
          this.$nextTick(() => {
            // this.changeBack(i)
            this.adjustmentRatio(i)
          })
        }
      },
      deep: true
    }
 }
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,402评论 6 499
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,377评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,483评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,165评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,176评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,146评论 1 297
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,032评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,896评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,311评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,536评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,696评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,413评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,008评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,659评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,815评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,698评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,592评论 2 353

推荐阅读更多精彩内容