vue-picture-bd-marker 图片添加标注
文档地址: https://vmarker.sagocloud.com/about/?spm=a2c6h.24755359.0.0.1b6441e4HwmruJ
实现效果:
清空画布: this.$refs['aiPanel-editor'].clearData()
<template> <div v-loading="loading" class="markBox"> <div class="imgbox" id="imgbox" ref="at"> <ui-marker ref="aiPanel-editor" class="ai-observer" v-bind:uniqueKey="uuid" :ratio="9/ 16" @vmarker:onAnnoSelected="onAnnoSelected" @vmarker:onAnnoAdded="onAnnoAdded" @vmarker:onUpdated="onUpdated" @vmarker:onReady="onReady" @vmarker:onImageLoad="onImageLoad" @vmarker:onDrawOne="onDrawOne(1)" v-bind:readOnly="readOnly" v-bind:imgUrl="currentImage" > </ui-marker> </div> <div class="btnBox"> <el-button class="diaWidth" @click="cancel" style="margin-right:20px">取消</el-button> <el-button class="diaWidth" @click="toImage" type="primary">添加标注</el-button> </div>
//选中标注区域在对应区域下展示select选择要标注的内容 <div v-if="markSelect" class="addMark" :style="{left: tranLeft, top: tranTop}"> <el-select v-model="text" allow-create filterable default-first-option @change="markChange" size="small" style="width:100%" placeholder="请选择"> <el-option v-for="(item,index) in list" :key="index" :label="item.content" :value="item.content"> </el-option> </el-select> </div> </div> </template>
import { AIMarker } from "Vue-Picture-BD-Marker"; import html2canvas from "html2canvas"; export default { components: { "ui-marker": AIMarker, html2canvas }, data(){ uuid: "0da9130", readOnly: false, //是否只读 currentImage: '', blist:[], text:'', markSelect: false, total: 0, tranLeft: '', tranTop: '', }, watch:{
//选中select下拉框中的值时 text(val){ if(this.uuid!=''){ let blist = this.blist blist.forEach(i => { if(this.uuid == i.uuid){ this.$refs['aiPanel-editor'].getMarker().setTag({ tagName: this.text, tag: "0x0001" }); i.tagName = this.text } }); this.blist = blist this.dialogVisible = false this.uuid = ''this.text = '' } }, }, methods: { //生成图片 toImage() { // 没有标注提示 if(this.blist.length == 0){ this.$message({ message: '请选择标注', type: "error", }); return } this.loading = true // 第一个参数是需要生成截图的元素,第二个是自己需要配置的参数,宽高等 html2canvas(this.$refs.at, { backgroundColor: null, useCORS: true, // 如果截图的内容里有图片,可能会有跨域的情况,加上这个参数,解决文件跨域问题 }).then((canvas) => { let quality = 0.2; let url = canvas.toDataURL("image/jpeg",quality); this.htmlUrl = url; let files = this.base64toFile(url) let formData = new FormData(); formData.append("HotelId", this.hotelid); formData.append("file", files); // 把生成的base64位图片上传到服务器,生成在线图片地址 api_UploadImg(formData) .then((res) => { this.loading = false }) .catch((error) => { }); }); }, // base64转文件流
// html2canvas将div转成图片返回的是base64格式的,上传标注图片是需将base64转成文件流 base64toFile (dataurl, filename = 'file') { let arr = dataurl.split(',') let mime = arr[0].match(/:(.*?);/)[1] let suffix = mime.split('/')[1] let bstr = atob(arr[1]) let n = bstr.length let u8arr = new Uint8Array(n) while (n--) { u8arr[n] = bstr.charCodeAt(n) } return new File([u8arr], `${filename}.${suffix}`, { type: mime }) }, onAnnoSelected(e) { this.uuid = e.uuid }, onAnnoAdded(e) { // console.log("添加选框", e); this.dialogVisible = true this.uuid = e.uuid
//选中区域后展示select,在对应的区域下方 this.markSelect = true this.tranLeft = Number(e.position.x.replace('%',''))/100 * document.querySelector('.imgbox').offsetWidth + 'px' this.tranTop = Number(e.position.y1.replace('%',''))/100 * document.querySelector('.imgbox').offsetHeight + 20 + 'px'
//限制标注个数超过5个时隐藏select if(this.total > 5){ this.markSelect = false } }, onUpdated(e) { // console.log("选框位置或者标框属性发生改动", e); this.blist = e this.uuid = '' this.text = '' // 限制标注个数 this.total = 0 const markBox = document.getElementById('imgbox') const markers = markBox.querySelectorAll('.annotation') for (let i = 0; i < markers.length; i++) { if (markers[i].clientWidth !== 0) { this.total++ } if (this.total > 5) { this.$message.warning('最多只可标记五处!') markers[i].remove() } }
//如果有重复的标注时新添加的标注覆盖已有的 let arr1 = [] let peon = e.reduce((cur,next) => { let index = cur.findIndex(item=> item.tagName == next.tagName) if(index != -1){ arr1.push(cur[index]) cur.splice(index, 1) } cur.push(next) return cur; },[]) this.blist = peon e = peon // 重复项新的替换旧的 for(var i = 0; i < markers.length; i++){ let arr = e.findIndex(item=>item.uuid == markers[i].getAttribute('data-uuid')) // console.log(arr) if(arr == -1){ markers[i].remove() } } },