​​​​​​

  • 鼠标在图片上移动时显示“十字准星”
  • 长按+拖拽+松开鼠标左键,展示一个框
  • 点击选中框,被选中框有不同的颜色(下面示例中,自动选择了新生成的框)

最终效果示例:

说明:

  • 自己造的轮子,不算完美,可能有疏忽的细节
  • 已经处理了页面尺寸自适应,图片尺寸取决于父组件的容器大小,框的数据是相对于图片宽高的比例(0-1之间数字)
  • 因为一开始需要读取图片的宽高,所以需要给图片设置id。也就是说,如果需要在同一页面使用2个以上这个组件,需要自己去把dom id打包,避免多个图片使用同一id。

组件代码:

<template><div@mousedown="handleMouseDown"@mouseup="handleMouseUp"@mousemove="handleMouseMove"@mouseover="handleMouseOver"@mouseleave="handleMouseLeave"class="container"><imgv-if="imgPath.length"id="img-marking":src="imgPath"class="auto-size"draggable="false"@load="setSize"/><divv-show="showCross"class="cross cross-vertical":style="{height: `${crossHeight}px`,top: `${containerTop}px`,left: `${mouseX}px`,}"></div><divv-show="showCross"class="cross cross-horizontal":style="{width: `${crossWidth}px`,top: `${mouseY}px`,left: `${containerLeft}px`,}"></div><template v-if="imgLoaded"><divv-for="(item, i) in rectList":key="i":class="i === selectedRectIndex ? 'rect rect-red' : 'rect rect-blue'":style="{top: `${item.top * containerHeight + containerTop}px`,left: `${item.left * containerWidth + containerLeft}px`,width: `${(item.right - item.left) * containerWidth}px`,height: `${(item.bottom - item.top) * containerHeight}px`,}"@click.stop="rectClick(i)"></div><divv-show="showDrawingRect"class="rect rect-red":style="{top: `${Math.min(drawingPosition.startY, drawingPosition.endY) +containerTop}px`,left: `${Math.min(drawingPosition.startX, drawingPosition.endX) +containerLeft}px`,width: `${Math.abs(drawingPosition.startX - drawingPosition.endX)}px`,height: `${Math.abs(drawingPosition.startY - drawingPosition.endY)}px`,}"></div></template></div>
</template>
<script>
export default {name: "ImageMarker",props: {imgPath: {type: String,required: true,},rectList: {type: Array,required: true,},selectedRectIndex: {type: Number,required: true,},minimumSize: {type: Array,default: () => [50, 50],},},data() {return {imgLoaded: false,showCross: false,crossHeight: 0,crossWidth: 0,containerLeft: 0,containerRight: 0,containerTop: 0,containerBottom: 0,containerWidth: 0,containerHeight: 0,mouseX: 0,mouseY: 0,mouseOffset: 5,lastMouseDown: [0, 0],drawingRect: false,drawingPosition: {},};},computed: {showDrawingRect() {if (!this.drawingRect) {return false;}if (Math.abs(this.drawingPosition.startY - this.drawingPosition.endY) < 8 &&Math.abs(this.drawingPosition.startY - this.drawingPosition.endY) < 8) {return false;}return true;},},mounted() {window.addEventListener("resize", this.setSize);},unmounted() {window.removeEventListener("resize", this.setSize);},methods: {// 根据图片尺寸设置准星长度+尺寸自适应setSize() {this.imgLoaded = true;const container = document.getElementById("img-marking");if (!container) return;const { top, bottom, left, right } = container.getBoundingClientRect();this.crossHeight = bottom - top;this.crossWidth = right - left;this.containerTop = top;this.containerBottom = bottom;this.containerLeft = left;this.containerRight = right;this.containerWidth = right - left;this.containerHeight = bottom - top;},// 鼠标移动handleMouseMove(e) {this.showCross =e.clientX < this.containerRight && e.clientY < this.containerBottom;if (!this.showCross) {return;}this.mouseX = Math.max(e.clientX - this.mouseOffset, this.containerLeft);this.mouseY = Math.max(e.clientY - this.mouseOffset, this.containerTop);if (this.drawingRect) {this.drawingPosition = {...this.drawingPosition,endX: this.mouseX - this.containerLeft,endY: this.mouseY - this.containerTop,};}},// 鼠标移进handleMouseOver() {this.showCross = true;},// 鼠标移出handleMouseLeave() {this.showCross = false;},// 鼠标按下handleMouseDown(e) {this.drawingRect = true;this.lastMouseDown = [e.clientX, e.clientY];this.drawingPosition = {startX: this.mouseX - this.containerLeft - this.mouseOffset,startY: this.mouseY - this.containerTop - this.mouseOffset,endX: this.mouseX - this.containerLeft - this.mouseOffset,endY: this.mouseY - this.containerTop - this.mouseOffset,};console.log(this.rectList);},// 鼠标按起handleMouseUp(e) {this.drawingRect = false;if (Math.abs(e.clientX - this.lastMouseDown[0]) < this.minimumSize[0] ||Math.abs(e.clientY - this.lastMouseDown[1]) < this.minimumSize[1]) {return;}const { startX, startY, endX, endY } = this.drawingPosition;const list = this.rectList;list.push({top: Math.min(startY, endY) / this.containerHeight,bottom: Math.max(startY, endY) / this.containerHeight,left: Math.min(startX, endX) / this.containerWidth,right: Math.max(startX, endX) / this.containerWidth,});this.$emit("update:rectList", list);this.$emit("update:selectedRectIndex", list.length - 1);},// 点击方块rectClick(i) {this.$emit("update:selectedRectIndex", i);},},
};
</script>
<style scoped>
.container {width: 100%;height: 100%;user-select: none;
}.auto-size {max-width: 100%;max-height: 100%;
}.cross {position: absolute;background: #f85757;z-index: 99;
}.cross-vertical {width: 2px;
}.cross-horizontal {height: 2px;
}.rect {position: absolute;z-index: 50;
}.rect-red {border: 1px solid rgb(125, 5, 5);background: rgba(125, 5, 5, 0.3);
}.rect-blue {border: 1px solid rgb(3, 38, 165);background: rgba(3, 38, 165, 0.3);
}
</style>

引用示例:

  • imgPath: 图片路径
  • rectList: 所有框的位置数据
  • selectedRectIndex当前选择的框的索引(rectList里的)
  • minimumSize: 每个框的最小[宽,高]
<template><div style="width: 1200px; height: 900px"><ImageMarker:imgPath="imgPath":rectList.sync="rectList":selectedRectIndex.sync="selectedRectIndex":minimumSize="[50, 50]"/></div>
</template><script>
import ImageMarker from "@/components/ImageMarker.vue";export default {name: "HomeView",components: {ImageMarker,},data() {return {imgPath: "",rectList: [],selectedRectIndex: -1,};},mounted() {this.imgPath = "test.jpg";this.rectList = [{bottom: 0.81446331360189,left: 0.2829747427502339,right: 0.5028063610851263,top: 0.3749187064749361,},{bottom: 0.7,left: 0.55,right: 0.9,top: 0.6,},];this.selectedRectIndex = 1;},
};
</script>

[vue2] 图片标记器相关推荐

  1. view vue 存图片_小小vue2.0图片查看器

    一个 小小vue2.0的图片查看器组件 闲暇下来封装了一个 vue2.0的图片查看器组件,通过这个更能方便清楚地查看列表的一张张图片.已经兼容 pc 跟移动端,通过 npm 来下载安装使用. This ...

  2. win10照片查看器_图片打开方式中找不到Windows图片查看器怎么办

    如何在电脑中使用默认的windows图片查看器来打开图片进行查看的?有时我们可能无法找到Windows图片查看器工具,接下来小编就与大家分享,一种简单的利用windows图片查看器查看图片的具体方法. ...

  3. [开源]基于WPF实现的Gif图片分割器,提取GIf图片中的每一帧

    [开源]基于WPF实现的Gif图片分割器,提取GIf图片中的每一帧 原文:[开源]基于WPF实现的Gif图片分割器,提取GIf图片中的每一帧 不知不觉又半个月没有更新博客了,今天终于抽出点时间,来分享 ...

  4. 图片 标记 软件_如何设计软件功能标记

    图片 标记 软件 A previous company had a problem: our deploys were thousands of lines in size, took nearly ...

  5. Android 加载本地图片(文件管理器中的图片墙)

    Android 加载本地图片(文件管理器中的图片墙) --关于图片墙的一些感悟与疑问,希望大家共同探讨. (By伊叶也) 图片显示及监听 1.图片显示:基本上就5种显示形式(如果同时嵌入5种形式,采用 ...

  6. Web前端技术开发学习笔记(HTML标记语言篇)——第6章 图片标记

    第6章 图片标记 6.1 网页常见图片格式 6.2 插入图片 6.2.1 设置图片大小 6.2.2 设置图片文本 6.2.3 设置图片与周围对象的间距 6.2.4设置图片的对齐方式 6.2.5设置图片 ...

  7. js 写一个前端图片查看器

    1. 前言 网上已经有不少成熟的图片查看器插件,如果是单纯想要点击图片放大预览的话,可以直接使用插件.例如viewerjs 但是,当打开图片后还需要对图片进行一些像删除.下载.标记等业务层面上的操作, ...

  8. 【React组件】写一个模仿蓝湖的图片查看器

    前言 最近公司让写一个可以自由拖拽放大的图片查看器,我寻思这还不简单,一顿操作猛如虎,俩小时后: 事实证明,一旦涉及到 DOM 的变换操作,如果很多细节考虑不全,抓过来就写,那基本就凉了.于是我仔细分 ...

  9. 图片html代码查看器,360度全景商品图片查看器

    360 Degrees Product Viewer360度全景商品图图片查看器是个非常简单的轻松展示图片全景插件. HTML Handle CSS .cd-product-viewer-wrappe ...

最新文章

  1. Oracle 并行原理与示例总结
  2. Boost:mighty bimap强大的双图的测试程序
  3. HDU 4405 Aeroplane chess(期望DP)
  4. linux shell 切割文件,linux shell 将文件按照行数以及顺序拆分成多个文件
  5. mysql stragg_如何在MySQL中將子查詢行的結果顯示為一列?
  6. 【金融工程实验】【matlab】使用candle函数画日均k线图
  7. Bootstrap采样方法的python实现
  8. oracle图形工具创建作业,oracle入门(2)—— 使用图形工具navicat for oracle
  9. 【Reformer】图解Reformer:一种高效的Transformer
  10. html基础之input属性
  11. mysql中的group by分组
  12. semaphore的几种用法
  13. 【C语言】俄罗斯方块的源代码
  14. 【Android】NanoHttpd学习(一)
  15. 《开源软件架构》--nginx架构概述
  16. latex 中下括号 underbrace 如何对齐
  17. 营造平安 信息化使公交事业更加人性化
  18. Windows系统图片不显示缩略图如何解决
  19. GPT-4 终问世!旧王已死,新王当立!面对AI,人类真的准备好了吗?
  20. Python海龟画图

热门文章

  1. CSS布局之“弹性盒子布局”
  2. [网鼎杯 2020 青龙组]AreUSerialz
  3. scilab和matlab的区别,Fortran, Matlab, Octave, Scilab计算速度比较
  4. php 高德地图点击事件,javascript - 高德地图marker动态绑定点击问题
  5. matlab绩点计算程序_用Matlab计算学分绩
  6. 如何写一个拼写检查器—Peter Norvig 中文翻译:徐宥
  7. python--真气网城市空气质量数据抓取
  8. 浅谈大型互联网企业入侵检测及防护策略
  9. java 设计模式
  10. 京东购物车的原理及Java实现