Fabric.js 拖拽顶点修改多边形形状

本文简介

戴尬猴,我是德育处主任

这次要介绍的一个demo是"拖拽多边形定点修改多边形形状"。

其实 Fabric.js 官网也有这个demo:Fabric.js demos · Custom controls, polygon 。但这个demo可能对于刚接触 Fabric.js 的工友来说有点过于复杂,所以本文就把该demo进一步简化,简化到老奶奶也能看得懂的!

先看看效果(录制gif的工具有点小瑕疵,导致多边形红色填充色"被弄脏了"):

完整代码在文末。

原理分析

要实现"拖拽多边形定点修改多边形形状"这个功能有很多方案,比如 Fabric.js demos · Custom controls, polygon 中,通过自定义控件来实现。又或者用 《Fabric.js 讲解官方demo:Stickman》 文章中的方法去实现。

使用 Fabric.js 官网给出的demo会更优雅,推荐在工作中使用。但如果你看了官网的demo还不太懂怎么创建自定义控件,可以看看 《Fabric.js 自定义控件》 这篇文章。

本文使用对学习阶段来说更容易理解的方案去实现上述功能。

先列出所有步骤:

  1. 绑定页面上指定画布 new fabric.Canvas()
  2. 创建多边形,且禁止用户直接操作多边形 new fabric.Polygon()
  3. 在多边形的每个顶点上创建小圆形(当做修改多边形时的控制器) new fabric.Circle()
  4. 监听元素移动,如果移动的是小圆形,那么多边形对应的顶点也跟着移动 canvas.on('object:moving', callback)
  5. 刷新画布 canvas.renderAll()

以上就是需要做的所有操作了。

多边形的配置

我们创建出来的多边形是禁止用户直接操作的,想要修改多边形形状只能通过辅助的小圆来修改。

要禁止多边形的操作可以设置多边形以下两个属性为 false

js 复制代码
selectable: false, // 禁止选中
evented: false, // 当设置为"false"时,对象不能成为事件的目标。所有事件都会通过它传播。

还要将多边形的 objectCaching 设置为 false,只有这样做了,多边形才不会有缓存。

圆形的配置

创建圆形时,需要将其 originXoriginY 设置为 center ,这样圆形的圆心就是它的 topleft 了。这个做法和 《Fabric.js 讲解官方demo:Stickman》 是一样的。

除此之外还需要将 hasControlshasBorders 设置为 false ,这样做完圆形就不会显示控制角和控制边了,看上去会更像是多边形的控件。

最后还需要给每个圆形添加一个自定义属性,当圆形被移动时就可以用这个自定义属性判断当前移动的是哪个圆。

动手实现

如果理解了上面的讲解就看看下面的代码吧(都有备注了,应该比较好理解)

html 复制代码
<canvas id="c" width="500" height="400" style="border:1px solid #ccc"></canvas>

<script src="https://unpkg.com/fabric@5.3.0/dist/fabric.min.js"></script>
<script>

  // 绑定画布
  const canvas = new fabric.Canvas('c')

  // 多边形的顶点
  let points = [
    {x: 80, y: 80},
    {x: 150, y: 40},
    {x: 220, y: 80},
    {x: 200, y: 190},
    {x: 100, y: 160}
  ]

  // 多边形
  const polygon = new fabric.Polygon(
    points, // 顶点坐标集
    {
      fill: 'red', // 填充红色
      stroke: 'black', // 边框黑色
      strokeWidth: 2, // 边框粗细
      objectCaching: false, // 当"true"时,对象缓存在另一个画布上。当"false"时,除非必要(clipPath)默认为 true,否则不缓存对象。默认是true
      selectable: false, // 禁止选中
      evented: false, // 当设置为"false"时,对象不能成为事件的目标。所有事件都会通过它传播。
    }
  )

  // 圆形列表
  let circleList = []

  // 循环所有定点并创建圆形
  points.forEach((item, index) => {
    circleList.push(
      new fabric.Circle({
        left: item.x,
        top: item.y,
        strokeWidth: 5,
        radius: 12,
        fill: '#fff',
        stroke: '#666',
        originX: 'center', // x轴方向以中心点为原点
        originY: 'center', // y轴方向以中心点为原点
        hasControls: false, // 不显示控制器
        hasBorders: false, // 不显示控制器的边
        cid: `circle-${index}` // 自定义属性
      })
    )
  })

  // 将多边形和圆形对象添加到画布中
  canvas.add(polygon, ...circleList)

  // 监听画布上的元素移动事件
  canvas.on('object:moving', function(e) {
    // 当前移动的元素
    let target = e.target
    // 如果存在自定义属性和指定值就执行以下代码(本例主要筛选出刚刚创建的几个圆形)
    if ('cid' in target && target.cid.match(RegExp(/circle-/))) {
        // 通过cid可以判断出当前操作的是哪个圆形,并且圆形的cid最后一位对应多边形指定的顶点
        let index = target.cid.split('-')[1]
        // 获取多边形定点
        let points = polygon.points
        // 修改指定点顶点的x坐标
        points[index].x = target.left
        // 修改指定定点的y坐标
        points[index].y = target.top
        // 刷新画布
        canvas.renderAll()
    }
  })
</script>

代码仓库

修改多边形形状

推荐阅读

👍《Fabric.js 从入门到膨胀》

👍《Fabric.js 讲解官方demo:Stickman》

👍《Fabric.js 激活输入框》

👍《Fabric.js 元素被选中时保持原有层级》

👍《Fabric.js 精简输出的JSON》

👍《Fabric.js 上标和下标的使用偏方》

代码仓库

相关推荐
子兮曰18 小时前
Bun v1.3.14 深度解析:Image API、HTTP/3、全局虚拟存储与五十项变革
前端·后端·bun
kyriewen19 小时前
今天,百年巨头一次砍了9200人,而一个离职科学家的实话让全网睡不着觉
前端·openai·ai编程
问心无愧051319 小时前
ctf show web 入门42
android·前端·android studio
kyriewen20 小时前
老板逼我上AI,我偷偷在浏览器里跑LLaMA,省下20万API费
前端·react.js·llm
Beginner x_u20 小时前
前端八股整理(手写 02)|数组转树、数组扁平化、随机打乱一个数组
前端·数组·数组转树·数组扁平化
KaMeidebaby20 小时前
卡梅德生物技术快报|禽类成纤维细胞 FISH 实验:鸟类性别染色体基因定位技术实现与数据验证
前端·数据库·其他·百度·新浪微博
天若有情67320 小时前
前端高阶性能优化:跳出传统懒加载与预加载,基于用户行为做轻量预判加载
前端·性能优化
小小小小宇20 小时前
前端转后端:SQL 是什么
前端
张元清21 小时前
React Observer Hooks:7 种监听 DOM 而不写样板代码的方式
前端·javascript·面试
广州华水科技21 小时前
单北斗GNSS变形监测是什么?主要有怎样的应用与优势?
前端