vue如何实现在页⾯上画画_vue组件:canvas实现图⽚涂鸦功
能
⽅案背景
需求
需要对图⽚进⾏标注,导出图⽚。
需要标注N多图⽚最后同时保存。
需要根据多边形区域数据(区域、颜⾊、名称)标注。
对应⽅案
⽤canvas实现涂鸦、圆形、矩形的绘制,最终⽣成图⽚ba64编码⽤于上传
⼤量图⽚批量上传很耗时间,为了提⾼⽤户体验,改为只实现圆形、矩形绘制,最终保存成坐标,下次显⽰时根据坐标再绘制。
多边形区域的显⽰是根据坐标点绘制,名称显⽰的位置为多边形质⼼。
代码
<template>
<div>
<canvas
:id="radom"
:class="{canDraw: 'canvas'}"
:width="width"
:height="height"
:
@moudown="canvasDown($event)"
@mouup="canvasUp($event)"
@moumove="canvasMove($event)"
@touchstart="canvasDown($event)"
@touchend="canvasUp($event)"
@touchmove="canvasMove($event)">
</canvas>
</div>
</template>
<script>
// import proxy from './proxy.js'
const uuid = require('node-uuid')
export default {
props: {
canDraw: { // 图⽚路径type: Boolean,
default: true
},
url: { // 图⽚路径
type: String
},
info: { // 位置点信息type: Array
},
width: { // 绘图区域宽度type: String
},
height: { // 绘图区域⾼度type: String
},
lineColor: { // 画笔颜⾊type: String,
default: 'red'
},
lineWidth: { // 画笔宽度type: Number,
default: 2
},
lineType: { // 画笔类型type: String,
default: 'circle'
}
},
watch: {
info (val) {
if (val) {
this.initDraw()
}
}
},
data () {
return {
// 同⼀页⾯多次渲染时,⽤于区分元素的id
radom: uuid.v4(),
// canvas对象
context: {},
// 是否处于绘制状态
canvasMoveU: fal,
// 绘制矩形和椭圆时⽤来保存起始点信息
beginRec: {
x: '',
y: '',
imageData: ''
},
/
/ 储存坐标信息
drawInfo: [],
// 背景图⽚缓存
img: new Image()
}
},
mounted () {
this.initDraw()
},
methods: {
// 初始化绘制信息
initDraw () {
// 初始化画布
const canvas = ElementById(this.radom) t = Context('2d')
// 初始化背景图⽚
this.img.tAttribute('crossOrigin', 'Anonymous')
this.img.src = this.url
r = () => {
var timeStamp = +new Date()
this.img.src = this.url + '?' + timeStamp
}
load = () => {
this.clean()
}
// Ba64({imgUrl: this.url}).then((res) => {
// if (de * 1 === 0) {
// this.img.src = 'data:image/jpeg;ba64,'+res.data
// load = () => {
// this.clean()
// }
// }
// })
// 初始化画笔
},
// ⿏标按下
canvasDown (e) {
if (this.canDraw) {
this.canvasMoveU = true
// client是基于整个页⾯的坐标,offt是cavas距离pictureDetail顶部以及左边的距离const canvasX = e.clientX - e.target.parentNode.offtLeft
const canvasY = e.clientY - e.target.parentNode.offtTop
// 记录起始点和起始状态
this.beginRec.x = canvasX
this.beginRec.y = canvasY
this.beginRec.imageData = ImageData(0, 0, this.width, this.height) // 存储本次绘制坐标信息
this.drawInfo.push({
x: canvasX / this.width,
y: canvasY / this.height,
type: this.lineType
})
}
},
Area (p0,p1,p2) {
let area = 0.0 ;
area = p0.x * p1.y + p1.x * p2.y + p2.x * p0.y - p1.x * p0.y - p2.x * p1.y - p0.x * p2.y; return area / 2 ;
},
// 计算多边形质⼼
getPolygonAreaCenter (points) {
let sum_x = 0;
let sum_y = 0;
let sum_area = 0;
let p1 = points[1];
for (var i = 2; i < points.length; i++) {
let p2 = points[i];
let area = this.Area(points[0],p1,p2) ;
sum_area += area ;
sum_x += (points[0].x + p1.x + p2.x) * area;
sum_y += (points[0].y + p1.y + p2.y) * area;
p1 = p2 ;
}
return {
x: sum_x / sum_area / 3,
y: sum_y / sum_area / 3
}
},
// 根据坐标信息绘制图形
drawWithInfo () {
this.info.forEach(item => {
if (!pe) {