需要绘制一条可控制的贝塞尔曲线,发现fabic官网中一个demo有点类似。感兴趣的可以移步官网查看demo。
官网的demo是对于html 而言的,放在vue中需要变换一下,具体代码如下:
- <div class="dashboard-container" @contextmenu.prevent>
- <canvas id="editorCanvas" ref="canvas" style="margin-top: 10px;" />
- div>
-
- <script>
- import { mapGetters } from 'vuex'
- // import fabric from 'fabric'
- let canvas = ''
- export default {
- name: 'Dashboard',
- computed: {
- ...mapGetters([
- 'name'
- ])
- },
- data () {
- return {
- width: window.innerWidth,
- height: window.innerHeight,
- activeEl: {}// 获取当前点击元素
- }
- },
- mounted () {
- const self = this
- // canvas = new fabric.StaticCanvas('editorCanvas', {//静态画布,不可以修改
- canvas = new fabric.Canvas('editorCanvas', {
- width: self.width,
- height: self.height,
-
- backgroundColor: '#ffffff'
- })
- var line = new fabric.Path('M 65 0 Q 100, 100, 200, 0', { fill: '', stroke: 'black', objectCaching: false })
-
- line.path[0][1] = 100
- line.path[0][2] = 100
-
- line.path[1][1] = 200
- line.path[1][2] = 200
-
- line.path[1][3] = 300
- line.path[1][4] = 100
-
- line.selectable = false
- canvas.add(line)
-
- var p1 = self.makeCurvePoint(200, 200, null, line, null)
- p1.name = 'p1'
- canvas.add(p1)
-
- var p0 = self.makeCurveCircle(100, 100, line, p1, null)
- p0.name = 'p0'
- canvas.add(p0)
-
- var p2 = self.makeCurveCircle(300, 100, null, p1, line)
- p2.name = 'p2'
- canvas.add(p2)
- canvas.on('object:selected', function (opt) {
- self.onObjectSelected(opt)
- })
- canvas.on('object:moving', function (opt) {
- self.onObjectMoving(opt)
- })
- canvas.on('selection:cleared', function (opt) {
- self.onSelectionCleared(opt)
- // canvas.on({
- // 'object:selected': this.onObjectSelected(e),
- // 'object:moving': this.onObjectMoving(e),
- // 'selection:cleared': this.onSelectionCleared(e)
- })
- },
- methods: {
- makeCurveCircle (left, top, line1, line2, line3) {
- var c = new fabric.Circle({
- left: left,
- top: top,
- strokeWidth: 5,
- radius: 12,
- fill: '#fff',
- stroke: '#666',
- originX: 'center',
- originY: 'center'
- })
-
- c.hasBorders = c.hasControls = false
-
- c.line1 = line1
- c.line2 = line2
- c.line3 = line3
-
- return c
- },
-
- makeCurvePoint (left, top, line1, line2, line3) {
- var c = new fabric.Circle({
- left: left,
- top: top,
- strokeWidth: 8,
- originX: 'center',
- originY: 'center',
- radius: 14,
- fill: '#fff',
- stroke: '#666'
- })
-
- c.hasBorders = c.hasControls = false
-
- c.line1 = line1
- c.line2 = line2
- c.line3 = line3
-
- return c
- },
- onObjectSelected (e) {
- // console.log(e.target)
- var activeObject = e.target
- if (activeObject.name == 'p0' || activeObject.name == 'p2') {
- activeObject.line2.animate('opacity', '1', {
- duration: 200,
- onChange: canvas.renderAll.bind(canvas)
- })
- activeObject.line2.selectable = true
- }
- },
- onSelectionCleared (e) {
- var activeObject = e.target
- if (activeObject.name == 'p0' || activeObject.name == 'p2') {
- activeObject.line2.animate('opacity', '0', {
- duration: 200,
- onChange: canvas.renderAll.bind(canvas)
- })
- activeObject.line2.selectable = false
- } else if (activeObject.name == 'p1') {
- activeObject.animate('opacity', '0', {
- duration: 200,
- onChange: canvas.renderAll.bind(canvas)
- })
- activeObject.selectable = false
- }
- },
- onObjectMoving (e) {
- if (e.target.name == 'p0' || e.target.name == 'p2') {
- var p = e.target
-
- if (p.line1) {
- p.line1.path[0][1] = p.left
- p.line1.path[0][2] = p.top
- } else if (p.line3) {
- p.line3.path[1][3] = p.left
- p.line3.path[1][4] = p.top
- }
- } else if (e.target.name == 'p1') {
- var p = e.target
-
- if (p.line2) {
- p.line2.path[1][1] = p.left
- p.line2.path[1][2] = p.top
- }
- } else if (e.target.name == 'p0' || e.target.name == 'p2') {
- var p = e.target
-
- p.line1 && p.line1.set({ 'x2': p.left, 'y2': p.top })
- p.line2 && p.line2.set({ 'x1': p.left, 'y1': p.top })
- p.line3 && p.line3.set({ 'x1': p.left, 'y1': p.top })
- p.line4 && p.line4.set({ 'x1': p.left, 'y1': p.top })
- }
- }
-
- }
- }
- script>
-
- <style lang="scss" scoped>
- style>
效果如图:
核心:定义 line时,设置path数组值。变换时修改path数组中的值。直接=
但是我需要绘制三阶贝塞尔曲线,即要两个控制点。这时候就需要变形一下。
- const line = new fabric.Path(`M ${item1.left} ${item1.top} C ${item1.left} ${item2.top}, ${item2.left} ${item1.top}, ${item2.left}, ${item2.top}`, {
- ......
-
- /* 起点 */
- line.path[0][1] = item1.left
- line.path[0][2] = item1.top
- /* 控制点1 */
- line.path[1][1] = item1.left
- line.path[1][2] = item2.top
- /* 控制点2 */
- line.path[1][3] = item2.left
- line.path[1][4] = item1.top
- /* 结束点 */
- line.path[1][5] = item2.left
- line.path[1][6] = item2.top
-
修改直接进行重新赋值。