需求:

使用canvas绘制多边形,且多边形的位置,大小和形状可拖动修改


使用Fabric.js

Fabric.js是一个可以简化canvas程序编写的库。 Fabric.js为canvas提供所缺少的对象模型
fabric.js官网

cnpm i fabric -D // 或者 npm i fabric -D

页面引入

import { fabric } from 'fabric'

html代码:

<div class="container">
    <div style="border: 1px solid #ccc; margin-right: 10px">
      <canvas ref="myCanvas" id="myCanvas" width="800" height="400">
      </canvas>
    </div>
    <el-button type="primary" @click="Edit">切换</el-button>
  </div>
.container {
  display: flex;
  padding: 8px;
  .toolBox {
  }
}

实现效果:

两个拖动模式
对多边形大小位置的拖动
对多边形形状,点的修改


typescript代码:

这里比较麻烦,参考了
我改写成了vue3.0的,且中的this稍微卡顿了半小时

<script lang="ts">
import { defineComponent, reactive, onMounted, toRefs, ref, watch } from 'vue'
import { fabric } from 'fabric'
import _ from 'lodash'

export default defineComponent({
  name: 'AreaPlan',
  components: {},
  setup() {
    let canvas: any
    const initCanvas = () => {
      // 直接获取Dom
      canvas = new fabric.Canvas('myCanvas')
      // 创建一个矩形数组,上面
      let points = [
        {
          x: 3,
          y: 4,
        },
        {
          x: 16,
          y: 3,
        },
        {
          x: 30,
          y: 5,
        },
        {
          x: 25.0,
          y: 55,
        },
        {
          x: 19,
          y: 44,
        },
        {
          x: 15,
          y: 30,
        },
        {
          x: 15,
          y: 55,
        },
        {
          x: 9,
          y: 55,
        },
        {
          x: 6,
          y: 53,
        },
        {
          x: -2,
          y: 55,
        },
        {
          x: -4,
          y: 40,
        },
        {
          x: 0,
          y: 20,
        },
      ]
      let polygon = new fabric.Polygon(points, {
        left: 100,
        top: 50,
        fill: '#D81B60',
        strokeWidth: 1,
        stroke: 'green',
        scaleX: 4,
        scaleY: 4,
        objectCaching: false,
        transparentCorners: false,
        cornerColor: 'blue',
      })

      canvas.viewportTransform = [0.7, 0, 0, 0.7, -50, 50]
      canvas.add(polygon)
    }
    const polygonPositionHandler = (
      dim,
      finalMatrix,
      fabricObject,
      constrol
    ) => {
      const index = constrol.pointIndex
      var x = fabricObject.points[index].x - fabricObject.pathOffset.x,
        y = fabricObject.points[index].y - fabricObject.pathOffset.y
      return fabric.util.transformPoint(
        { x: x, y: y },
        fabric.util.multiplyTransformMatrices(
          fabricObject.canvas.viewportTransform,
          fabricObject.calcTransformMatrix()
        )
      )
    }

    const actionHandler = (eventData, transform, x, y) => {
      var polygon = transform.target,
        currentControl = polygon.controls[polygon.__corner],
        mouseLocalPosition = polygon.toLocalPoint(
          new fabric.Point(x, y),
          'center',
          'center'
        ),
        polygonBaseSize = polygon._getNonTransformedDimensions(),
        size = polygon._getTransformedDimensions(0, 0),
        finalPointPosition = {
          x:
            (mouseLocalPosition.x * polygonBaseSize.x) / size.x +
            polygon.pathOffset.x,
          y:
            (mouseLocalPosition.y * polygonBaseSize.y) / size.y +
            polygon.pathOffset.y,
        }
      polygon.points[currentControl.pointIndex] = finalPointPosition
      return true
    }
    const anchorWrapper = (anchorIndex, fn) => {
      return function (eventData, transform, x, y) {
        var fabricObject = transform.target,
          absolutePoint = fabric.util.transformPoint(
            {
              x: fabricObject.points[anchorIndex].x - fabricObject.pathOffset.x,
              y: fabricObject.points[anchorIndex].y - fabricObject.pathOffset.y,
            },
            fabricObject.calcTransformMatrix()
          ),
          actionPerformed = fn(eventData, transform, x, y),
          newDim = fabricObject._setPositionDimensions({}),
          polygonBaseSize = fabricObject._getNonTransformedDimensions(),
          newX =
            (fabricObject.points[anchorIndex].x - fabricObject.pathOffset.x) /
            polygonBaseSize.x,
          newY =
            (fabricObject.points[anchorIndex].y - fabricObject.pathOffset.y) /
            polygonBaseSize.y
        fabricObject.setPositionByOrigin(absolutePoint, newX + 0.5, newY + 0.5)
        return actionPerformed
      }
    }
    const Edit = () => {
      console.log('canvas', canvas)
      console.log('Edit')
      var poly = canvas.getObjects()[0]
      canvas.setActiveObject(poly)
      poly.edit = !poly.edit
      if (poly.edit) {
        var lastControl = poly.points.length - 1
        poly.cornerStyle = 'circle'
        poly.cornerColor = 'rgba(0,0,255,0.5)'
        poly.controls = poly.points.reduce(function (acc, point, index) {
          const control = new fabric.Control({
            positionHandler: (a, b, c) =>
              polygonPositionHandler(a, b, c, control),
            actionHandler: anchorWrapper(
              index > 0 ? index - 1 : lastControl,
              actionHandler
            ),
            actionName: 'modifyPolygon',
            pointIndex: index,
          })
          acc['p' + index] = control
          return acc
        }, {})
      } else {
        poly.cornerColor = 'blue'
        poly.cornerStyle = 'rect'
        poly.controls = fabric.Object.prototype.controls
      }
      poly.hasBorders = !poly.edit
      canvas.requestRenderAll()
    }
    onMounted(() => {
      initCanvas()
    })
    return {
      //把切换事件返回出去
      Edit,
    }
  },
})
</script>

后面修改成为手动标绘多边形,且支持修改的,有时间就会更新,有不足的地方请留言。阿里嘎多~~~~~~。转载请标明出处,谢谢:

GitHub 加速计划 / vu / vue
207.54 K
33.66 K
下载
vuejs/vue: 是一个用于构建用户界面的 JavaScript 框架,具有简洁的语法和丰富的组件库,可以用于开发单页面应用程序和多页面应用程序。
最近提交(Master分支:2 个月前 )
73486cb5 * chore: fix link broken Signed-off-by: snoppy <michaleli@foxmail.com> * Update packages/template-compiler/README.md [skip ci] --------- Signed-off-by: snoppy <michaleli@foxmail.com> Co-authored-by: Eduardo San Martin Morote <posva@users.noreply.github.com> 4 个月前
e428d891 Updated Browser Compatibility reference. The previous currently returns HTTP 404. 5 个月前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐