日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

vue實(shí)現(xiàn)一個(gè)矩形標(biāo)記區(qū)域(rectangle marker)的方法

瀏覽:33日期:2022-11-10 16:32:06

代碼地址:vue-rectangle-marker

一、前言

一些cms系統(tǒng)經(jīng)常會(huì)用到區(qū)域標(biāo)記功能,所以寫了個(gè)用vue實(shí)現(xiàn)的矩形標(biāo)記區(qū)域,包含拖拽、放大縮小、重置功能。

二、實(shí)現(xiàn)結(jié)果

1.初始

vue實(shí)現(xiàn)一個(gè)矩形標(biāo)記區(qū)域(rectangle marker)的方法

2.標(biāo)記

vue實(shí)現(xiàn)一個(gè)矩形標(biāo)記區(qū)域(rectangle marker)的方法

三、代碼實(shí)現(xiàn)

<template><div class='rectangle-marker'><div class='mark-wrap'><img ref='backImg' :src='http://www.b3g6.com/bcjs/imgUrl' alt='響應(yīng)式圖像' @load='onload'><div : @mousemove='mouseMove'@mousedown='mouseDown' @mouseup='mouseUp'><div ref='box' v-if='boxVisible' : class='box':style='{ width: boxW + ’px’, height: boxH + ’px’, left: boxL + ’px’, top: boxT + ’px’ }'><div @mousedown='onUpleftbtn'></div><div @mousedown='onUpRightbtn'></div><div @mousedown='onDownleftbtn'></div><div @mousedown='onDownRightbtn'></div></div></div><transition name='fade'><div v-if='showBtns && !markFlag' @mouseleave='mouseLeave'><button @click='mark'>mark</button>&nbsp;&nbsp;<button @click='reset'>reset</button></div></transition></div></div></template><script>export default {name: ’rectangleMarker’,data() {return {imgW: 0,imgH: 0,showBtns: true,markFlag: false,// 鼠標(biāo)事件屬性dragging: false,startX: undefined,startY: undefined,diffX: undefined,diffY: undefined,obj: null, //當(dāng)前操作對(duì)象box: null, //要處理的對(duì)象backImgRect: null,boxId: ’’,boxW: 0,boxH: 0,boxL: 0,boxT: 0,boxVisible: false}},props: {imgUrl: {type: String,required: true,default: ’’},disabled: {type: Boolean,default: false},value: {type: Array,default: function () {return []}}},methods: {onload() {let rect = this.$refs.backImg.getBoundingClientRect()this.backImgRect = {height: rect.height,width: rect.width}// console.log('initConfig -> this.backImgRect', this.backImgRect)if (this.value === ’’ || this.value === undefined || this.value === null || (Array.isArray(this.value) && this.value.length === 0)) {return}this.initData(this.value)},mouseLeave() {this.showBtns = false},mark() {this.markFlag = true},reset() {this.boxVisible = falsethis.boxId = ’’this.boxH = 0this.boxW = 0this.boxL = 0this.boxT = 0},initData(data) {if (data === ’’ || data === undefined || data === null || (Array.isArray(data) && data.length === 0)) {return}this.boxId = ’changeBox’this.boxL = data[0][0] * this.backImgRect.widththis.boxT = data[0][1] * this.backImgRect.heightthis.boxH = (data[3][1] - data[0][1]) * this.backImgRect.heightthis.boxW = (data[1][0] - data[0][0]) * this.backImgRect.widththis.boxVisible = true},mouseDown(e) {if (!this.markFlag && !this.boxVisible) {return}this.startX = e.offsetX;this.startY = e.offsetY;// 如果鼠標(biāo)在 box 上被按下if (e.target.className.match(/box/)) {// 允許拖動(dòng)this.dragging = true;// 設(shè)置當(dāng)前 box 的 id 為 movingBoxif (this.boxId !== ’movingBox’) {this.boxId = ’movingBox’}// 計(jì)算坐標(biāo)差值this.diffX = this.startXthis.diffY = this.startY} else {if (this.boxId === ’changeBox’) {return}this.boxId = ’activeBox’this.boxT = this.startYthis.boxL = this.startXthis.boxVisible = true}},mouseMove(e) {if (!this.markFlag && !this.boxVisible) {if (!this.backImgRect) {return}let toRight = this.backImgRect.width - e.offsetXlet toTop = e.offsetYif (toRight <= 100 && toTop <= 40) {this.showBtns = true}return}let toRight = this.backImgRect.width - e.offsetXlet toTop = e.offsetYif (toRight <= 100 && toTop <= 40) {this.showBtns = truereturn}// 更新 box 尺寸if (this.boxId === ’activeBox’) {this.boxW = e.offsetX - this.startXthis.boxH = e.offsetY - this.startY}// 移動(dòng),更新 box 坐標(biāo)if (this.boxId === ’movingBox’ && this.dragging) {let realTop = (e.offsetY + e.target.offsetTop - this.diffY) > 0 ? (e.offsetY + e.target.offsetTop -this.diffY) : 0let realLeft = (e.offsetX + e.target.offsetLeft - this.diffX) > 0 ? (e.offsetX + e.target.offsetLeft -this.diffX) : 0let maxTop = this.backImgRect.height - this.$refs.box.offsetHeightlet maxLeft = this.backImgRect.width - this.$refs.box.offsetWidthrealTop = realTop >= maxTop ? maxTop : realToprealLeft = realLeft >= maxLeft ? maxLeft : realLeftthis.boxT = realTop;this.boxL = realLeft;}if (this.obj) {e = e || window.event;var location = {x: e.x || e.offsetX,y: e.y || e.offsetY}switch (this.obj.operateType) {case 'nw':this.move(’n’, location, this.$refs.box);this.move(’w’, location, this.$refs.box);break;case 'ne':this.move(’n’, location, this.$refs.box);this.move(’e’, location, this.$refs.box);break;case 'sw':this.move(’s’, location, this.$refs.box);this.move(’w’, location, this.$refs.box);break;case 'se':this.move(’s’, location, this.$refs.box);this.move(’e’, location, this.$refs.box);break;case 'move':this.move(’move’, location, this.box);break;}}},mouseUp() {if (!this.markFlag && !this.boxVisible) {return}// 禁止拖動(dòng)this.dragging = false;if (this.boxId === ’activeBox’) {if (this.$refs.box) {this.boxId = ’changeBox’if (this.$refs.box.offsetWidth < 3 || this.$refs.box.offsetHeight < 3) {this.boxVisible = falsethis.boxId = ’’}}} else {if (this.$refs.box && this.boxId === ’movingBox’) {this.boxId = ’changeBox’if (this.$refs.box.offsetWidth < 3 || this.$refs.box.offsetHeight < 3) {this.boxVisible = falsethis.boxId = ’’}}}if (this.boxVisible) {this.getHotData()document.body.style.cursor = 'auto';this.obj = null;this.markFlag = false} else {this.markFlag = true}},getHotData() {let target = this.$refs.boxif (target) {let {offsetTop,offsetLeft} = targetlet {width: WIDTH,height: HEIGHT} = this.backImgRectlet {width,height} = target.getBoundingClientRect()// 矩形區(qū)域 角點(diǎn)位置(百分比)let data = [[this.toFixed6(offsetLeft, WIDTH), this.toFixed6(offsetTop, HEIGHT)],[this.toFixed6(offsetLeft + width, WIDTH), this.toFixed6(offsetTop, HEIGHT)],[this.toFixed6(offsetLeft + width, WIDTH), this.toFixed6(offsetTop + height, HEIGHT)],[this.toFixed6(offsetLeft, WIDTH), this.toFixed6(offsetTop + height, HEIGHT)]]// 矩形中點(diǎn)let centerPoint = [this.toFixed6(offsetLeft + 0.5 * width, WIDTH),this.toFixed6(offsetTop + 0.5 * height, HEIGHT)]let hotData = {data,centerPoint}console.log('getHotData -> hotData', hotData)console.log(JSON.stringify(hotData));}},toFixed6(v1, v2) {return (v1 / v2).toFixed(6)},move(type, location, tarobj) {switch (type) {case ’n’: {let add_length = this.clickY - location.y;this.clickY = location.y;let length = parseInt(tarobj.style.height) + add_length;tarobj.style.height = length + 'px';let realTop = this.clickY > 0 ? this.clickY : 0let maxTop = this.backImgRect.height - parseInt(tarobj.style.height)realTop = realTop >= maxTop ? maxTop : realToptarobj.style.top = realTop + 'px';break;}case ’s’: {let add_length = this.clickY - location.y;this.clickY = location.y;let length = parseInt(tarobj.style.height) - add_length;let maxHeight = this.backImgRect.height - parseInt(tarobj.style.top)let realHeight = length > maxHeight ? maxHeight : lengthtarobj.style.height = realHeight + 'px';break;}case ’w’: {var add_length = this.clickX - location.x;this.clickX = location.x;let length = parseInt(tarobj.style.width) + add_length;tarobj.style.width = length + 'px';let realLeft = this.clickX > 0 ? this.clickX : 0let maxLeft = this.backImgRect.width - parseInt(tarobj.style.width)realLeft = realLeft >= maxLeft ? maxLeft : realLefttarobj.style.left = realLeft + 'px';break;}case ’e’: {let add_length = this.clickX - location.x;this.clickX = location.x;let length = parseInt(tarobj.style.width) - add_length;let maxWidth = this.backImgRect.width - parseInt(tarobj.style.left)let realWidth = length > maxWidth ? maxWidth : lengthtarobj.style.width = realWidth + 'px';break;}}},onUpleftbtn(e) {e.stopPropagation();this.onDragDown(e, 'nw');},onUpRightbtn(e) {e.stopPropagation();this.onDragDown(e, 'ne');},onDownleftbtn(e) {e.stopPropagation();this.onDragDown(e, 'sw');},onDownRightbtn(e) {e.stopPropagation();this.onDragDown(e, 'se');},onDragDown(e, type) {e = e || window.event;this.clickX = e.x || e.offsetX;this.clickY = e.y || e.offsetY;this.obj = window;this.obj.operateType = type;this.box = this.$refs.box;return false;}},}</script><style lang='less' scoped>.rectangle-marker {width: 100%;height: 100%;display: flex;flex-direction: column;align-items: center;.mark-wrap {position: relative;.img-responsive {display: inline-block;max-width: 100%;max-height: 100%;}.draw-rect {position: absolute;top: 0;left: 0;bottom: 0;right: 0;width: 100%;height: 100%;z-index: 99;user-select: none;&.no-event {pointer-events: none;}}}.act-box {margin-top: 10px;display: flex;}.act-btns {position: absolute;right: 0;top: 0;z-index: 199;padding: 0 10px;height: 40px;width: 100px;display: flex;align-items: center;justify-content: center;}.fade-enter-active {animation: hide-and-show .5s;}.fade-leave-active {animation: hide-and-show .5s reverse;}@keyframes hide-and-show {0% {opacity: 0;}100% {opacity: 1;}}}</style><style lang='less'>.rectangle-marker {.box {position: absolute;width: 0px;height: 0px;opacity: 0.5;z-index: 149;cursor: move;border: 1px solid #f00;.upleftbtn,.uprightbtn,.downleftbtn,.downrightbtn {width: 10px;height: 10px;border: 1px solid steelblue;position: absolute;z-index: 5;background: whitesmoke;border-radius: 10px;}.upleftbtn {top: -5px;left: -5px;cursor: nw-resize;}.uprightbtn {top: -5px;right: -5px;cursor: ne-resize;}.downleftbtn {left: -5px;bottom: -5px;cursor: sw-resize;}.downrightbtn {right: -5px;bottom: -5px;cursor: se-resize;}}}</style> 背景圖傳入,圖片自適應(yīng)處理。 定義drag標(biāo)記為,添加開(kāi)始標(biāo)記、重置按鈕。 創(chuàng)建box區(qū)域,不同狀態(tài)(change、moving、active),對(duì)應(yīng)不同id。 box可移動(dòng)距離,計(jì)算邊界。 四角放大縮小的功能。 生成結(jié)果,精確到6位小數(shù),這樣可以使得復(fù)原標(biāo)記區(qū)域的時(shí)候誤差最小。

四、覺(jué)得有幫助的,麻煩給個(gè)贊哦,謝謝!

以上就是vue實(shí)現(xiàn)一個(gè)矩形標(biāo)記區(qū)域(rectangle marker)的方法的詳細(xì)內(nèi)容,更多關(guān)于vue實(shí)現(xiàn)矩形標(biāo)記區(qū)域的資料請(qǐng)關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

標(biāo)簽: Vue
相關(guān)文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
欧美亚洲日本精品| 国产日韩中文在线中文字幕| 国产精品一区二区三区av| 日本在线观看不卡视频| 日韩一区免费| 日韩福利在线观看| 欧美在线首页| 久久av超碰| 欧美激情另类| 色婷婷精品视频| 婷婷中文字幕一区| 久色成人在线| 四虎在线精品| 日本aⅴ亚洲精品中文乱码| 国产视频欧美| 蜜桃av一区| 久久国产精品色av免费看| 国产精品久久国产愉拍| 精品国产美女a久久9999| 亚洲黄色免费看| 99精品综合| 亚洲神马久久| 欧美中文一区| 98精品久久久久久久| 欧美日韩中文一区二区| 亚洲综合欧美| 欧美亚洲三级| 91日韩在线| 激情偷拍久久| 日韩中文欧美在线| 欧美另类中文字幕| 国产成人a视频高清在线观看| 人人香蕉久久| 一区二区三区国产在线| 国产精品一区二区精品| 91av亚洲| 美女国产一区| 麻豆久久久久久| 欧美~级网站不卡| 日本不卡视频在线| 日本一区二区高清不卡| 免费精品国产的网站免费观看| 日韩在线观看一区二区| 久久av影视| 91麻豆国产自产在线观看亚洲| 久久一区二区三区喷水| 视频精品一区二区| 国产精品白浆| 午夜av一区| 国产精品久久久久9999高清| 日本欧美不卡| 日韩不卡在线观看日韩不卡视频| 成人欧美一区二区三区的电影| 亚洲专区一区| 国产成人免费| 亚洲人成高清| 日本一区二区免费高清| 久久www成人_看片免费不卡| 精品一区二区三区在线观看视频| 999国产精品999久久久久久| 天堂va在线高清一区| 国产美女高潮在线| 婷婷视频一区二区三区| 欧洲精品一区二区三区| 亚洲精品观看| 日韩福利一区| 欧美日韩亚洲三区| 午夜欧美在线| 精品久久视频| 蜜臀av国产精品久久久久| 精品99在线| 日韩av电影一区| 蜜桃成人av| 国产精品99一区二区三| 一区二区国产精品| 亚洲成人av观看| 国产精品久av福利在线观看| 亚洲黄色影院| 日本蜜桃在线观看视频| 国产亚洲一卡2卡3卡4卡新区| 国产精品99免费看| 久久精品国产久精国产| 日本不卡的三区四区五区| 99久久九九| 成人一区不卡| 国产免费av一区二区三区| 欧美一区=区| 91精品国产乱码久久久久久久 | 欧美三级第一页| 偷拍欧美精品| 日韩综合在线| 国产欧美精品| 免费视频一区二区| 亚洲欧美伊人| 日韩不卡在线| 日本一二区不卡| 国产精品www.| 日韩av网站在线观看| 久久性天堂网| 欧美特黄一区| 亚洲午夜天堂| 久久精品天堂| 国产黄色精品| 国产日韩免费| 欧美自拍一区| 欧美日韩中文| 日韩成人精品一区二区三区 | 欧美不卡高清| 99精品电影| 桃色av一区二区| 国产日产精品_国产精品毛片 | 日韩不卡一区二区三区| 国产精品三上| 久久精品免费一区二区三区| 久久av免费看| 国产欧美日韩视频在线 | 婷婷成人av| 涩涩涩久久久成人精品| 在线看片日韩| 欧美中文字幕| 亚洲一区国产| 亚洲成人一区| 偷拍欧美精品| 午夜亚洲福利在线老司机| 婷婷综合在线| 日韩午夜电影| 不卡视频在线| 在线精品小视频| 好看的亚洲午夜视频在线| 黑丝一区二区三区| 欧美一区=区| 中文字幕免费一区二区| 日日夜夜免费精品视频| 91精品麻豆| 久久永久免费| 久久久久免费| 日韩三区在线| 日本美女一区| 免费欧美一区| 亚洲香蕉久久| 国产午夜久久av| 国产精品伦理久久久久久| 亚洲小说春色综合另类电影| 日韩区欧美区| 久久99久久久精品欧美| 国产理论在线| 好看的av在线不卡观看| 亚洲狼人精品一区二区三区| 久久精品 人人爱| 精品精品99| 激情婷婷亚洲| 视频一区日韩精品| 欧美国产亚洲精品| 精品丝袜在线| 亚洲欧美视频一区二区三区| 日本亚州欧洲精品不卡| 美女久久久精品| 成人精品动漫一区二区三区| 91精品亚洲| 综合一区av| 精品日韩一区| 亚洲精品2区| 日本午夜精品视频在线观看| 国产精品羞羞答答在线观看| 国内自拍视频一区二区三区| 91精品一区国产高清在线gif| 在线看片日韩| 久久精品九色| 国产精品免费看| 国产激情一区| 午夜欧美精品| 国产精品久久久久久av公交车 | 久久国产视频网| 国产不卡人人| 视频一区二区三区在线| 欧美精品第一区| 欧美亚洲在线日韩| 日韩美女精品| 成人亚洲欧美| 亚洲精品大片| 蜜桃精品在线| 日韩国产一区二| 久久久精品久久久久久96 | 精品国产一区二区三区av片| 久久国产亚洲| 国产一精品一av一免费爽爽| 四虎成人av| 亚洲久久视频| 92国产精品| 91成人福利| 激情婷婷久久| 老司机免费视频一区二区三区| 午夜电影亚洲| 久久精品三级| 亚洲午夜国产成人| 日韩三区免费| 久久精品999| av亚洲免费| 久久免费精品| 亚洲精品日韩久久|