Skip to content

Instantly share code, notes, and snippets.

@fwindpeak
Created March 5, 2021 08:40
Show Gist options
  • Save fwindpeak/1ecafd1db6006d0d9ec09f274fcb369d to your computer and use it in GitHub Desktop.
Save fwindpeak/1ecafd1db6006d0d9ec09f274fcb369d to your computer and use it in GitHub Desktop.
vue pointline component with fabric.js
<template>
<canvas id="canvas"></canvas>
</template>
<script>
import { fabric } from 'fabric'
export default {
props: {
value: {
type: Array,
required: true,
default: () => [],
},
},
watch: {
// value(val) {
// this.init(val)
// },
},
data() {
return {
fabricObj: {},
circleList: [],
moving: false,
lineLeft: null,
}
},
computed: {
canvasWidth() {
return window.innerWidth - 20
},
},
mounted() {
//起始点居中
fabric.Object.prototype.originX = fabric.Object.prototype.originY = 'center'
//阻止group缩放
fabric.Group.prototype.lockScalingX = true
fabric.Group.prototype.lockScalingY = true
this.fabricObj = new fabric.Canvas('canvas', {
isDrawingMode: false,
selectable: true,
selection: true,
devicePixelRatio: true,
})
this.fabricObj.setWidth(this.canvasWidth)
this.fabricObj.setHeight(500)
//绑定事件
this.fabricObjAddEvent()
this.init(this.value)
},
methods: {
//绑定fabric事件
fabricObjAddEvent() {
this.fabricObj.on({
//鼠标双击事件
'mouse:dblclick': o => {
this.addNode({
x: o.pointer.x,
y: o.pointer.y,
})
},
//对象移动事件
'object:moving': e => {
const p = e.target
if (p._objects) {
//多选
for (let obj of p._objects) {
this.onNodeMoving(obj, p)
}
} else {
//单选
this.onNodeMoving(p)
}
},
})
},
makeCircle(left, top, lineLeft, lineRight) {
let c = new fabric.Circle({
left: left,
top: top,
strokeWidth: 2,
radius: 12,
fill: 'red',
stroke: 'gray',
})
c.hasControls = c.hasBorders = false
c.lineLeft = lineLeft
c.lineRigt = lineRight
return c
},
makeLine(pa, pb) {
if (pa && pb) {
const c = new fabric.Line([pa.x, pa.y, pb.x, pb.y], {
fill: 'red',
stroke: 'red',
strokeWidth: 5,
selectable: false,
evented: false,
})
c.hasControls = c.hasBorders = false
return c
} else {
return null
}
},
/**
* 添加节点
*/
addNode(point) {
let lineLeft = null
let lineRight = null
if (this.circleList.length > 0) {
const lastCircle = this.circleList.slice(-1)[0]
const pointLast = { x: lastCircle.left, y: lastCircle.top }
lineLeft = this.makeLine(pointLast, point)
lastCircle.lineRight = lineLeft
this.fabricObj.add(lineLeft)
}
const circle = this.makeCircle(point.x, point.y, lineLeft, lineRight)
this.circleList.push(circle)
this.fabricObj.add(circle)
this.fabricObj.renderAll()
this.update()
},
/**
* 节点移动
*/
onNodeMoving(p, group) {
let offsetX = p.left
let offsetY = p.top
if (group) {
offsetX += group.left
offsetY += group.top
}
p.lineLeft && p.lineLeft.set({ x2: offsetX, y2: offsetY })
p.lineRight && p.lineRight.set({ x1: offsetX, y1: offsetY })
this.fabricObj.renderAll()
this.update()
},
/**
* 组件参数数据初始化
*/
init(pointList) {
this.circleList = []
this.fabricObj.clear()
console.log('point init', pointList)
for (let p of pointList) {
const point = { x: p[0], y: p[1] }
this.addNode(point)
}
},
/**
* 组件数据更新
*/
update() {
this.$emit(
'input',
this.circleList.map(p => [p.top, p.left])
)
},
},
}
</script>
<style scoped>
#canvas {
margin: 5px;
border: 1px solid;
}
</style>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment