Fabric.js拖拽平移画布方法示例

2023-02-16 10:07:38
目录
正文原理解析按下鼠标时移动鼠标时松开鼠标时代码仓库

正文

使用>fabric.js 创建出来的画布默认是不能拖拽移动的。

不过我们可以利用一些小技巧让画布具有被拖拽的能力,fabric.js 官网也提供了一个 demo ,但文档上并没有详细的讲解拖拽画布的实现原理。

本文就粗略分析一下这个原理。

原理解析

鼠标拖拽的原理其实很简单,主要就3步:

    鼠标点击元素移动鼠标松开鼠标

    在鼠标移动时,获取鼠标当前位置,然后修改被拖拽元素的位置。

    当松开鼠标时,也要获取松手那刻鼠标所在位置,然后设置元素的位置。

    先看看官方给出的例子再逐步分析

    <canvas id="c" width="500" height="500" style="border: 1px solid #ccc;"></canvas>
    <script src="../js/fabric.js"></script>
    <script>
      // 创建画布
      let canvas = new fabric.Canvas('c', {
        allowTouchScrolling: true
      })
      // 矩形
      const rect = new fabric.Rect({
        width: 100,
        height: 100,
        left: 10,
        top: 10,
        fill: 'pink'
      })
      // 三角形
      const triangle = new fabric.Triangle({
        top: 100,
        left: 100,
        width: 80, // 底边长度
        height: 100, // 底边到对角的距离
        fill: 'blue'
      })
      // 将矩形和三角形添加到画布中
      canvas.add(rect, triangle)
      // 按下鼠标事件
      canvas.on('mouse:down', function (opt) {
        var evt = opt.e;
        if (evt.altKey === true) {
          this.isDragging = true
          this.lastPosX = evt.clientX
          this.lastPosY = evt.clientY
        }
      })
      // 移动鼠标事件
      canvas.on('mouse:move', function (opt) {
        if (this.isDragging) {
          var e = opt.e;
          var vpt = this.viewportTransform;
          vpt[4] += e.clientX - this.lastPosX
          vpt[5] += e.clientY - this.lastPosY
          this.requestRenderAll()
          this.lastPosX = e.clientX
          this.lastPosY = e.clientY
        }
      })
      // 松开鼠标事件
      canvas.on('mouse:up', function (opt) {
        this.setViewportTransform(this.viewportTransform)
        this.isDragging = false
      })
    </script>
    

    拖拽画布的代码来自官方案例。我删减了部分元素。

    从上面的代码可以看出,主要事件是 mouse:downmouse:movemouse:up

    按下鼠标时

    canvas.on('mouse:down', function (opt) {
      var evt = opt.e;
      if (evt.altKey === true) {
        this.isDragging = true
        this.lastPosX = evt.clientX
        this.lastPosY = evt.clientY
      }
    })
    

    通过 mouse:down 事件,设置了按住 alt 键时再按下鼠标左键,才能触发拖拽事件(开始)。

    自定义3个属性:

      isDragging: 拖拽状态,true 表示可拖拽lastPosX: 画布上一个x坐标lastPosY: 画布上一个y坐标

      为什么要记录 lastPosXlastPosY 呢?

      把鼠标点击时,鼠标所在的位置记录下来。之后移动时,再通过鼠标新出现的位置和点击时的位置对比,就能计算出鼠标移动了多少距离,然后再调整画布移动的距离即可。

      移动鼠标时

      canvas.on('mouse:move', function (opt) {
        if (this.isDragging) {
          var e = opt.e;
          var vpt = this.viewportTransform;
          vpt[4] += e.clientX - this.lastPosX
          vpt[5] += e.clientY - this.lastPosY
          this.requestRenderAll()
          this.lastPosX = e.clientX
          this.lastPosY = e.clientY
        }
      })
      

      通过 mouse:move 可以监听鼠标的移动。

      此时就要通过 isDragging 判断是否进入拖拽状态。

      viewportTransformfabric.js 在画布上的一个属性。

      官方文档是这样介绍的:

      The transformation (a Canvas 2D API transform matrix) which focuses the viewport

      上面的代码,修改了 viewportTransform 下标为 45 的元素。

        viewportTransform[4]: 水平位移(x轴)viewportTransform[5]: 垂直位移(y轴)

        e.clientX - this.lastPosX 就是鼠标移动的x轴方向的距离,e.clientY - this.lastPosY 可以计算出鼠标移动的y轴方向的距离。

        如果想了解 viewportTransform 每个元素代表什么,可以看看 《Fabric.js 变换视窗》

        requestRenderAll() 是在每次移动完画布就刷新一下。

        刷新完画布,就把上一个点(x和y坐标)改成最新的:this.lastPosX = e.clientXthis.lastPosY = e.clientY ,给下次移动鼠标时提供一个参考值,方便计算。

        松开鼠标时

        canvas.on('mouse:up', function (opt) {
          this.setViewportTransform(this.viewportTransform)
          this.isDragging = false
        })
        

        使用 setViewportTransform 设置画布的视图。

        并退出拖拽模式:isDragging = false

        以上就是在 fabric.js 中拖拽画布的方法。

        代码仓库

        ⭐拖拽移动画布

        以上就是Fabric.js>