vue+div.canvas图像标注功能实现




main.js
import Vue from 'vue'
import 'vueui-widgets/dist/index.css'
import VueUI from 'vueui-widgets'
import App from './App.vue'
import router from './router'
import store from './store'
Vue.use(VueUI) Vue.config.productionTip = false new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
组件.vue
<template>
<div class="mycanvas-container">
<div class="left">
<p>展示视口</p>
<div class="myshow">
<img :src="mysrc" alt width="100%" />
<!-- <div id="canvas" style="width:100%;height:100%" class="mycanvas"></div> -->
</div>
</div>
<div class="center">
<p>操作视口</p>
<div class="myedit" ref="myedit" @mousedown.prevent="onMousedown" @mousemove="onMousemove" @contextmenu.prevent="">
<!-- <img src="@/assets/jia.svg" alt=""> -->
<img :src="mysrc" />
<span
class="myedit-span"
v-for="(item, index) in mydata"
:key="index"
:style="getSpanStyle(item)"
@contextmenu.prevent="onContextmenu(item, $event)"
></span>
<!-- <div id="canvas" style="width:100%;height:100%" class="mycanvas"></div> -->
</div>
</div>
<div class="right">
<img src alt class="mybutton" />
<input v-show="0" ref="file" type="file" class="mybutton" @change="onChange" />
<button class="mybutton" @click="selectFile">导入图片</button>
<button class="mybutton">新增标注</button>
<button class="mybutton">修改标注</button>
<button class="mybutton">删除</button>
<button class="mybutton">保存</button>
</div>
<div class="myMenu" v-show="mymenu.current" :style="mymenu.style">
<!-- <button @click="onRemoveItem">删除</button> -->
<ui-button type="primary" @click="onRemoveItem">删除</ui-button>
<ui-select></ui-select>
<select name="" id="">
<option value="1">ceshi</option>
</select>
</div>
</div>
</template> <script>
import jiaIcon from "./jia.svg";
export default {
data() {
return {
mysrc: "",
mydata: [],
mymenu: { current: null, style: { left: 0, top: 0 } }
};
},
mounted() {
document.addEventListener('mouseup', this.onMouseup)
},
beforeDestroy() {
document.removeEventListener('mouseup', this.onMouseup)
},
methods: {
getXY(e) {
let rect = this.$refs.myedit.getBoundingClientRect()
return {
x: e.clientX - rect.left,
y: e.clientY - rect.top
}
},
// 上传图片1
onChange(e) {
this.mysrc = window.URL.createObjectURL(e.target.files[0]);
e.target.value = ''
},
// 上传图片2,
selectFile() {
this.$refs.file.click();
},
onMousedown(e) {
this.mymenu.current = null
let { x, y } = this.getXY(e)
this.currentItem = { x, y, w: 0, h: 0, now: Date.now() }
this.startPos = { x, y }
this.mydata.push(this.currentItem)
},
onMousemove(e) {
if (!this.currentItem) return;
let { x, y } = this.getXY(e)
this.currentItem.w = Math.abs(x - this.startPos.x)
this.currentItem.h = Math.abs(y - this.startPos.y)
},
onMouseup(e) {
this.currentItem = this.startPos = null;
this.mydata = this.mydata.filter(_ => _.w > 10 && _.h > 10)
},
onContextmenu(item, e) {
this.mymenu = {
current: item,
style: {
top: e.clientY + 'px',
left: e.clientX + 'px'
}
}
},
onRemoveItem() {
this.mydata.splice(this.mydata.indexOf(this.mymenu.current), 1)
this.mymenu = { ...this.mymenu, current: null }
},
getSpanStyle(item) {
return {
width: `${item.w}px`,
height: `${item.h}px`,
top: `${item.y}px`,
left: `${item.x}px`
};
}
}
};
</script>
<style lang="less" scoped>
// 设置绘图样式1
body {
user-select: none;
} .myMenu {
position: fixed;
top: 400px;
left: 400px;
width: 100px;
padding: 8px 0;
background-color: #fff;
> * {
width: 100%;
}
} #canvas > div {
/* border: 2px solid green; */
position: absolute;
background-color: transparent;
} #canvas > div > span {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-family: simsun;
font-size: 9pt;
} // 设置绘图样式2 .mycanvas-container {
display: flex;
justify-content: center;
align-items: center; .left,
.center,
.right {
width: 300px;
// height: 520px;
margin: 20px; p {
text-align: center;
} .myshow,
.myedit {
width: 300px;
// height: 500px;
border: 1px solid #000;
position: relative;
.myedit-span {
position: absolute;
border: 1px dashed #fff;
background: url("./jia.svg") no-repeat center center;
background-size: contain;
} .mycanvas {
border: 1px solid pink;
position: absolute;
top: 0;
left: 0;
} img {
width: 100%;
}
}
} .right {
width: 150px;
display: flex;
justify-content: center;
align-items: left;
flex-direction: column; .mybutton {
margin-top: 20px;
display: block;
}
}
}
</style>
vue+div.canvas图像标注功能实现的更多相关文章
- 如何实现Canvas图像的拖拽、点击等操作
上一篇Canvas的博文写完后,有位朋友希望能对Canvas绘制出来的图像进行点击.拖拽等操作,因为Canvas绘制出的图像能很好的美化.好像是想做炉石什么的游戏,我也没玩过. Canvas在我的理解 ...
- 【百度地图API】情人节求爱大作战——添加标注功能
原文:[百度地图API]情人节求爱大作战--添加标注功能 任务描述: 2月2日是除夕,2月14立马来!即将到来的情人节,你想送TA一份什么礼物呢? 不如,在你们居住的地方,画个大大的桃心,表达你对TA ...
- OpenCV探索之路(二十五):制作简易的图像标注小工具
搞图像深度学习的童鞋一定碰过图像数据标注的东西,当我们训练网络时需要训练集数据,但在网上又没有找到自己想要的数据集,这时候就考虑自己制作自己的数据集了,这时就需要对图像进行标注.图像标注是件很枯燥又很 ...
- 【开源】canvas图像裁剪、压缩、旋转
前言 前段时间遇到了一个移动端对图像进行裁剪.压缩.旋转的需求. 考虑到已有各轮子的契合度都不高,于是自己重新造了一个轮子. 关于图像裁剪.压缩 在HTML5时代,canvas的功能已经非常强大了,可 ...
- Vue (二) --- Vue对象提供的属性功能
--------------------------------------------不是井里没有水,而是你挖的不够深. 3. Vue对象提供的属性功能 3.1 过滤器 过滤器,就是vue允许开发者 ...
- vue 对象提供的属性功能、通过axio请求数据(2)
1 Vue对象提供的属性功能 1.1 过滤器 过滤器,就是vue允许开发者自定义的文本格式化函数,可以使用在两个地方:输出内容和操作数据中. 1.1.1 使用Vue.filter()进行全局定义(全局 ...
- vue 使用canvas仿芝麻分信用表
如图所示: 画布组件:dashboard.vue <template> <div> <canvas ref="canvas" v-if="c ...
- canvas图像裁剪、压缩、旋转
转载于:http://www.cnblogs.com/dailc/p/7843204.html 前言 前段时间遇到了一个移动端对图像进行裁剪.压缩.旋转的需求.考虑到已有各轮子的契合度都不高,于是自己 ...
- vue教程2-07 微博评论功能
vue教程2-07 微博评论功能 <!doctype html> <html> <head> <meta charset="utf-8"& ...
- PHP《将画布(canvas)图像保存成本地图片的方法》
用PHP将网页上的Canvas图像保存到服务器上的方法 2014年6月27日 歪脖骇客 发表回复 8 在几年前HTML5还没有流行的时候,我们的项目经理曾经向我提出这样一个需求:让项目评审专家们在评审 ...
随机推荐
- 27.路由器Routers
像一些reils这样的web框架提供自动生成urls的功能,但是Django没有 rest framework为django添加了这一功能,以一种简单.快速.一致的方式 routers必须配合view ...
- wpf下的图片放大缩小
WPF下实现图片的放大缩小移动 在windows 7里面有自带的图片查看器,这个软件可以打开一张图片然后以鼠标在图片中的焦点为原点来进行缩放,并且放大后可以随意拖动.下面我们在WPF中实现这个功能 ...
- Linux三剑客awk
Linux三剑客awk awk是一个强大的linux命令,有强大的文本格式化的能力,好比将一些文本数据格式化成专业的excel表的样式 awk早期在Unix上实现,我们用的awk是gawk,是GUN ...
- ES6 学习笔记(四)基本类型Number
1.数值 1.1 .JavaScript数值的特点 不区分整数值和浮点数值. 所有数值均用浮点数值表示. 采用IEEE-754标准定义的64位浮点数格式表示. 整数在实际操作时(如数组索引),则是基于 ...
- 说说switch关键字
Switch语法 switch作为Java内置关键字,却在项目中真正使用的比较少.关于switch,还是有那么一些奥秘的. 要什么switch,我有if-else 确实,项目中使用switch比较少的 ...
- java学习之MybBaits
0x00前言 我前面使用的jdbc和jdbc的工具类集成的但是它们在少部分代码的情况下会会简单,但是以后如果项目较大jdbc的固定代码会很难维护,如果使用框架会简单很多,也标志着java学习正式进入到 ...
- 工作总结:kafka踩过的坑
餐饮系统每天中午和晚上用餐高峰期,系统的并发量不容小觑.公司规定各部门都要轮流值班,防止出现线上问题时能够及时处理. 后厨显示系统属于订单的下游业务. 用户点完菜下单后,订单系统会通过发 Kafka ...
- 面试 个人摸底监测 考察JavaScript基础 (第三天)
01,如何开启JS严格模式?JS严格模式有什么特点? 两种方式 全局开启在js开头加上 'use strict' 局部开启,在作用域开头加上 function fn(){ 'use strict' } ...
- 【Spring系列】- Bean生命周期底层原理
Bean生命周期底层原理 生命不息,写作不止 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 一个有梦有戏的人 @怒放吧德德 分享学习心得,欢迎指正,大家一起学习成长! 前言 上次学到动 ...
- 将现有源码添加进repo管理
将现有源码添加进repo管理 适用于大型项内无源码管理(git/repo)的源码 前言 公司在进行一些项目的开发时,从供应商原厂给的code内没有包含任何源码管理的文件.需要多人协同开发,但由于项 ...