需求:根据接口返回的坐标数据,根据坐标数据在影像上绘图,初始页面,不满足条件的内容,都要被绘制红框,点击表格对应的数据后,绘制蓝框
//完整cavans
<template>
<div class="can">
<canvas
id="canvas3"
style="
border: 1px solid #dcdfe6;
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.12),
0 0 6px 0 rgba(0, 0, 0, 0.04);
width: 500px;
height: 500px;
"
>
<p>您的系统不支持此程序,请更换浏览器!</p>
</canvas>
</div>
</template>
<script>
import { fabric as Fabric } from 'fabric'
import $ from 'jquery'
export default {
props: {
baseUrl: { //父组件传过来的影像url
type: String
},
redBorder: { //父组件传过来的数组
type: Array
},
positionType:{
type:String,
default:'initPosition'
}
},
data () {
return {
card: {},
panning: false,
// 待旋转的图片
selectedObj: {},
index:null,
localPosition: []
}
},
created () {
window.addEventListener('resize', this.resizeWindowEvent)
},
mounted() {
// this.initCanvas()
},
destoryed () {
window.removeEventListener('resize', this.resizeWindowEvent)
},
methods: {
resizeWindowEvent(e) {
if (!!this.card) {
this.card.setWidth($('.image').innerWidth()) //外层容器
this.card.setHeight($('.can').height() - 15)
}
},
// drawArr args是传过来的坐标数据
//坐标数组 [[251, 309, 310, 252, 330, 328, 360, 362],[812, 952, 953, 814, 333, 324, 349, 358]] 坐标是根据影像坐顶点为原点
drawArrDefault(args) {
let tempArr = []
for(let i in args) {
var react = react + i
react = new Fabric.Rect({
top: args[i][4]* 0.5,
left: args[i][0] * 0.5,
width: args[i][1] - args[i][0],
height: args[i][7] - args[i][4],
fill: 'transparent',
scaleX: 0.5,
scaleY: 0.5,
stroke: 'red',
strokeWidth: 2,
angle: 0,
// perPixelTargetFind: false,
})
tempArr.push(react)
}
for(let item of tempArr) {
this.card.add(item)
}
},
//初始化
initCanvas (data) {
this.card = new Fabric.Canvas('canvas3', {
preserveObjectStacking: true,
centeredScaling: true // 全局所有元素都生效 鼠标中心点实现缩放
})
const canvas = this.card
canvas.setWidth($('.image').innerWidth())
canvas.setHeight($('.can').height() - 15)
Fabric.Image.fromURL(this.baseUrl, (img) => {
img.set({
hasControls: false, // 是否开启图层的控件
// borderColor: 'orange', // 图层控件边框的颜色
scaleX: 0.5,
scaleY: 0.5,
//防止鼠标拖动影像,绘图发生位移
lockMovementX: true, // 禁止水平移动
lockMovementY: true, // 禁止垂直移动
hasRotatingPoint: false, // 无旋转点
})
// 添加对象后, 如下图
canvas.add(img)
// 在画布图片后,插入新的所有默认标记
this.drawArrDefault(data)
canvas.renderAll()
})
$('#canvas3').parent().siblings().css('display', 'none')
const relationship = { x: 0, y: 0, zoom: 1 }
// 鼠标按下事件
canvas.on('mouse:down', function (e) {
this.panning = true
canvas.selection = false
})
// 鼠标抬起事件
canvas.on('mouse:up', function (e) {
this.panning = false
canvas.selection = true
})
// 移动画布事件
canvas.on('mouse:move', function (e) {
if (this.panning && e && e.e) {
const delta = new Fabric.Point(e.e.movementX, e.e.movementY)
canvas.relativePan(delta)
// 累计每一次移动时候的偏移量
relationship.x += e.e.movementX / relationship.zoom
relationship.y += e.e.movementY / relationship.zoom
}
})
// 鼠标滚动画布放大缩小
canvas.on('mouse:wheel', opt => {
const delta = opt.e.deltaY // 滚轮,向上滚一下是 -100,向下滚一下是 100
let zoom = canvas.getZoom() // 获取画布当前缩放值
zoom *= 0.999 ** delta
if (zoom > 20) zoom = 20
if (zoom < 0.01) zoom = 0.01
// 以左上角为原点
// this.canvas.setZoom(zoom)
// 以鼠标所在位置为原点缩放
canvas.zoomToPoint(
{ // 关键点
x: opt.e.offsetX,
y: opt.e.offsetY
},
zoom
)
opt.e.preventDefault()
opt.e.stopPropagation()
})
},
drawRedBorder (newValue) {
this.card._objects.splice(1)
let arr = []
if (newValue !== null) {
this.drawArrDefault(this.localPosition)
const rect = new Fabric.Rect({
top: newValue[4]* 0.5,
left: newValue[0] * 0.5,
width: newValue[1] - newValue[0],
height: newValue[7] - newValue[4],
fill: 'transparent', // 背景
scaleX: 0.5,
scaleY: 0.5,
stroke: 'blue',
strokeWidth: 2,
angle: 0,
perPixelTargetFind: false,
//防止鼠标拖动影像,绘图发生位移
lockMovementX: true, // 禁止水平移动
lockMovementY: true, // 禁止垂直移动
hasRotatingPoint: false, // 无旋转点
hasControls:false,
selectable: false // 不可选中
})
this.card.add(rect) // 选中
}
this.card.renderAll()
},
// currAngle影像旋转
currAngle () {
this.selectedObj = this.card._objects[0]
// 顺时针90°旋转
const currAngle = this.selectedObj.angle // 当前图层的角度
const angle = currAngle === 360 ? 90 : currAngle + 90
this.selectedObj.rotate(angle)
// 所有图层的操作之后,都需要调用这个方法
this.card.renderAll()
}
},
watch: {
baseUrl (newValue, oldValue) {
// console.log(newValue, oldValue)
if(this.positionType == 'clickTable'){
if (newValue !== oldValue) {
this.initCanvas()
}
}
},
redBorder: {
handler (newValue, oldValue) {
this.localPosition = sessionStorage.getItem('position') ? JSON.parse(sessionStorage.getItem('position')) : newValue
if(this.positionType == 'initPosition') { // 获取所有初始位置
this.initCanvas(this.localPosition)
} else {
if(this.positionType == 'clickTable') { // 点击费用清单中 小项表格
this.drawRedBorder(newValue)
}
}
},
deep: true
},
}
}
</script>
<style>
.can {
width: 100vw;
height: -moz-calc(90vh - 30px);
height: -webkit-calc(90vh - 30px);
height: calc(90vh - 30px);
}
</style>