成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久

您的位置:首頁技術文章
文章詳情頁

vue實現一個矩形標記區域(rectangle marker)的方法

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

代碼地址:vue-rectangle-marker

一、前言

一些cms系統經常會用到區域標記功能,所以寫了個用vue實現的矩形標記區域,包含拖拽、放大縮小、重置功能。

二、實現結果

1.初始

vue實現一個矩形標記區域(rectangle marker)的方法

2.標記

vue實現一個矩形標記區域(rectangle marker)的方法

三、代碼實現

<template><div class='rectangle-marker'><div class='mark-wrap'><img ref='backImg' :src='http://www.piao2010.com/bcjs/imgUrl' alt='響應式圖像' @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,// 鼠標事件屬性dragging: false,startX: undefined,startY: undefined,diffX: undefined,diffY: undefined,obj: null, //當前操作對象box: null, //要處理的對象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;// 如果鼠標在 box 上被按下if (e.target.className.match(/box/)) {// 允許拖動this.dragging = true;// 設置當前 box 的 id 為 movingBoxif (this.boxId !== ’movingBox’) {this.boxId = ’movingBox’}// 計算坐標差值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}// 移動,更新 box 坐標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}// 禁止拖動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()// 矩形區域 角點位置(百分比)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)]]// 矩形中點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> 背景圖傳入,圖片自適應處理。 定義drag標記為,添加開始標記、重置按鈕。 創建box區域,不同狀態(change、moving、active),對應不同id。 box可移動距離,計算邊界。 四角放大縮小的功能。 生成結果,精確到6位小數,這樣可以使得復原標記區域的時候誤差最小。

四、覺得有幫助的,麻煩給個贊哦,謝謝!

以上就是vue實現一個矩形標記區域(rectangle marker)的方法的詳細內容,更多關于vue實現矩形標記區域的資料請關注好吧啦網其它相關文章!

標簽: Vue
相關文章:
成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久
欧美日韩在线不卡一区| 久久精品国产第一区二区三区最新章节 | 亚洲一区在线看| 欧美人成网站| 精品粉嫩aⅴ一区二区三区四区| 美女免费视频一区二区| 久久不射中文字幕| 亚洲国产成人tv| 一本色道婷婷久久欧美| 中国av一区二区三区| 99国产一区二区三精品乱码| 日韩一区二区在线观看| 亚洲国产精选| 国产精品丝袜在线| 欧美国产高潮xxxx1819| 久久看人人爽人人| 波多野洁衣一区| 欧美大片国产精品| 国产成a人无v码亚洲福利| 欧美精品一卡两卡| 国产一级精品在线| 欧美人妇做爰xxxⅹ性高电影| 麻豆91精品视频| 欧美日韩国产一级二级| 免费黄网站欧美| 久久在线视频| 久久狠狠亚洲综合| 欧美在线短视频| 蜜臀91精品一区二区三区| 在线观看网站黄不卡| 久久黄色级2电影| 欧美浪妇xxxx高跟鞋交| 国产精品一级二级三级| 日韩三级在线免费观看| 白白色亚洲国产精品| 国产亚洲精品精华液| 午夜久久资源| 亚洲欧洲成人精品av97| 亚洲国产一区二区三区高清| 一区二区三区在线播放| 国产农村妇女精品一二区| 亚洲第一在线综合网站| 久久亚洲精选| 国产一区二区女| 欧美电视剧在线看免费| 欧美激情性爽国产精品17p| 亚洲人成在线播放网站岛国| 亚洲免费久久| 亚瑟在线精品视频| 欧美羞羞免费网站| 国产成人精品免费| 国产视频亚洲色图| 精品成人在线| 午夜成人免费视频| 欧美三级韩国三级日本一级| 国产精品一区二区免费不卡 | 国产欧美日韩伦理| 人人爽香蕉精品| 日韩三级免费观看| 国产精品成人观看视频免费| 亚洲图片有声小说| 欧美午夜理伦三级在线观看| 成人av免费在线| 成人免费在线视频观看| 老司机一区二区三区| 国产一区二区91| 国产欧美一区二区精品婷婷| 亚洲无毛电影| 三级久久三级久久| 欧美一级欧美三级在线观看| 欧美日韩一区二| 日韩精品福利网| 日韩欧美美女一区二区三区| 黄色工厂这里只有精品| 日本在线不卡视频一二三区| 日韩欧美的一区| 极品日韩久久| 男男gaygay亚洲| 久久久亚洲精品一区二区三区 | 国产精品一区二区免费不卡 | 亚洲裸体俱乐部裸体舞表演av| 蜜臀av性久久久久蜜臀aⅴ| 久久综合狠狠综合久久综合88 | 欧美一级午夜免费电影| 伊人精品视频| 国产综合久久久久久鬼色 | 久久精品99久久久| 久久蜜桃一区二区| 中文在线不卡| 国产成人av电影在线观看| 亚洲色图另类专区| 欧美精品第1页| 国产一区高清在线| 亚洲欧美视频在线观看| 欧美精品日日鲁夜夜添| 精品1区2区3区4区| 国产精品一线二线三线| 亚洲欧美欧美一区二区三区| 欧美丰满美乳xxx高潮www| 亚洲国产精品一区| 国产伦精一区二区三区| 亚洲欧美区自拍先锋| 日韩一区二区三| 国产日韩亚洲| 丁香激情综合国产| 亚洲成人中文在线| 久久久久久久久久美女| 一本色道久久加勒比精品| 欧美1区2区| 韩国精品主播一区二区在线观看| 亚洲精品日日夜夜| 欧美精品一区二区精品网| 久久久国产亚洲精品| 亚洲精品1区2区| 国产成人精品一区二区三区四区| 一区二区三区精品在线| 精品国产91九色蝌蚪| 久久精品女人| 欧美日韩一区二区三区在线视频| 久久97超碰国产精品超碰| 亚洲欧美色一区| 久久免费国产精品| 7777精品伊人久久久大香线蕉的| 国产精品毛片va一区二区三区| 不卡一区在线观看| 美女一区二区视频| 亚洲黄网站在线观看| 久久精品夜色噜噜亚洲aⅴ| 欧美日韩国产首页| 亚洲女同在线| 国语自产精品视频在线看8查询8| 国产福利一区二区三区视频| 亚洲国产精品久久久久婷婷884| 中文字幕乱码日本亚洲一区二区| 欧美区视频在线观看| 亚洲尤物影院| 黄色一区三区| 99国产欧美久久久精品| 国产一区二区三区观看| 日本不卡视频在线| 亚洲精品欧美二区三区中文字幕| 久久久久国产精品人| 欧美麻豆精品久久久久久| 久久裸体视频| 亚洲人成免费| 欧美日韩一区二区三区免费| 成人一级片在线观看| 精品一区二区精品| 日本在线不卡视频| 亚洲国产精品影院| 亚洲精品午夜久久久| 中文av字幕一区| 国产偷国产偷亚洲高清人白洁| 日韩一卡二卡三卡国产欧美| 欧美性猛片xxxx免费看久爱| 久久午夜精品| 欧美一级视频| 欧美亚洲三区| 亚久久调教视频| 欧美一级一区| 免费在线成人| 国产精品区一区| 在线午夜精品| 好吊日精品视频| 色综合天天综合| 亚洲天天做日日做天天谢日日欢| 26uuuu精品一区二区| 欧美一级日韩一级| 欧美一区二区三区在线看| 欧美美女一区二区三区| 欧美人狂配大交3d怪物一区| 欧美日韩一本到| 精品视频999| 欧美三级中文字| 欧美日韩免费一区二区三区 | 亚洲区小说区图片区qvod| 最新国产成人在线观看| 国产精品沙发午睡系列990531| 亚洲国产激情av| 国产精品美女视频| 国产精品第13页| 亚洲私人黄色宅男| 有码一区二区三区| 亚洲第一主播视频| 天天操天天色综合| 日韩成人免费看| 久久精品国产久精国产爱| 久久99国产精品免费| 国产精品主播直播| 国产河南妇女毛片精品久久久 | 国产精品资源在线观看| 国产成人av电影在线| 风间由美中文字幕在线看视频国产欧美| 国产成人丝袜美腿| 成人精品免费看| 91亚洲精品久久久蜜桃网站 | 激情欧美一区二区三区| 一区二区冒白浆视频| 欧美一级视频| 在线观看亚洲成人|