• canvas-绘图库fabric.js简介


    一般情况下简单的绘制,其实canvas原生方法也可以满足,比如画个线,绘制个圆形、正方形、加个文案。

      let canvas = document.getElementById('canvas');
      canvas.width = 1200;
      canvas.height = 600;
      canvas.style.width = '1200px';
      canvas.style.height = '600px';
      let ctx = canvas.getContext('2d');
    
      ctx.moveTo(400, 100);
      ctx.lineTo(400, 200);
      ctx.lineTo(500, 200);
      ctx.strokeStyle = "#00F";
      ctx.stroke();
      ctx.beginPath();
    
      ctx.arc(150, 150, 100, 0, 2 * Math.PI, true);
      ctx.fillStyle = '#ccc';
      ctx.fill();
      ctx.beginPath();
    
      let str1 = '苟利国家生死以,';
      let str2 = '岂因祸福避趋之!';
      ctx.font = '50px Microsoft Yahei';
      ctx.strokeStyle = 'red';
      ctx.textAlign = 'center';
      ctx.strokeText(str1, 800, 50);
    
      ctx.font = '50px SimHei';
      ctx.fillStyle = 'blue';
      ctx.textAlign = 'center';
      ctx.fillText(str2, 800, 100);
      //获取文本的宽度,以便以后能动态的使文本居中。
      let strWidth = ctx.measureText(str2).width;
      console.log(strWidth);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    看效果图
    在这里插入图片描述
    如果真的只是这点需求,原生方法也很好,省的加载一个js库。不过现实往往还是很残酷的,怎么可能这么简单,这里都没有交互,比如在现有的图形上做位移、拖拽等等,复杂度就上来了,这时一个好的canvas js库就很有必要了。
    fabric.js 算是我用到过的比较全面且好用的一个canvas js库;
    先上代码:

    const data = {
    	line: [
    		'1648.607594936709', '654.1772151898734', '2100.253164556962', '1290.126582278481'
    	],
    	area: [
    		"1604.0506329113923", "607.5949367088607", "1648.607594936709", "654.1772151898734", "2100.253164556962", "1290.126582278481"
    , "2211.645569620253", "1429.873417721519", "285.56962025316454" , "1429.873417721519" , "617.7215189873417" , "662.2784810126582"
    	]
    };
    // 可以看出上面数据一个是画线,一个是画不规则区域,这是实际项目中用到的数据,拿到这里自有妙处,后面会说
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    fabric.js使用

    import { fabric } from ‘fabric’;

    // canvasDraw是canvas的 id
    const canvasBox = new fabric.StaticCanvas('canvasDraw', {
      backgroundColor: "transparent"
     });
     // 这个是设置
     // canvas.style.width 和 canvas.width
     // canvas.style.height 和 canvas.height
    canvasBox.setDimensions({
     width: 600,
     height: 300
    });
    // 下面方法等同于 setDimensions
    // canvasBox.setWidth(width);
    // canvasBox.setHeight(height);
    
    // 这个是设置的 canvas.style.width 和 canvas.style.height
    canvasBox._setCssDimension('width', 2400);
    canvasBox._setCssDimension('height', 1500);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    到此fabric初始化就算完成了,这里有个很重要的点,官方文档和几乎所有写fabric教学的博客都没有讲,那就是如何将canvas.style.width 和 canvas.width 赋予不同的数值,这是个很实用的点,因为坐标点是按canvas.width来的,但是我们的canvas.style.width必须和设计保持一致
    比如说:我们需要在一张图片上做绘制,那坐标点是从图片原图上标注的,而设计不可能按原图大小展示,这时就会出现坐标点和canvas.style.width不一致,有两个方法解决这个问题:
    1、坐标点根据 canvas.style.width / img.width 的比率做调整
    2、canvas.width 和 img.width保持一致,canvas.style.width 和 设计稿 width一致
    很显然第二个方案更简单且实用
    既然官网没提供方法那我们就看源码都做了什么,因为canvas.width是必然要设置的
    我们发现setDimensions时调用了 _setBackstoreDimension 和 _setCssDimension
    在这里插入图片描述
    很明显这里是canvas.width
    在这里插入图片描述
    而这里是canvas.style.width
    在这里插入图片描述
    今天先简单点,只看画线和画不规则图形

    function drawLine(arr, color, opacity) {
     // [x1, y1, x2, y2]
      const line =  new fabric.Line(arr, {
        strokeWidth: 10, //线宽
        stroke: color, //线的颜色
        selectable: false,
        opacity: opacity
      });
      this.canvasBox.add(line);
    }
    function drawPolygon(arr, color, opacity) {
      const newArr = formatData(arr);
      const polygon = new fabric.Polygon(
        newArr,
        {
          fill: color,
          strokeWidth: 1,
          stroke: "#000",
          opacity: opacity
        }
      );
      this.canvasBox.add(polygon);
    }
    function formatData(arr) {
      // 将 [100,50,200,40] 坐标点转为 {x: 100, y: 50}
      let newArr = [];
      arr.forEach((val, i) => {
        i = i + 1;
        // 偶数不操作
        if ((i % 2) !== 0) {
          newArr.push({
            x: parseInt(val),
            y: parseInt(arr[i])
          });
        }
      });
      return newArr;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    这时大家就会看到 我有个 parseInt的操作,因为当我使用原数据绘制时,线可以出来但Polygon却没有,搞得很郁闷,查了很长时间,最后当我盯着数据发呆时,看着长长的小数位 突发奇想,于是parseInt诞生了,页面也能看到区域了,真的是坑,这个点不做项目是绝无可能发现的。
    也是我今天冒着延期项目也要搞这么一篇文章的原因,虽然fabric知识点不多但绝对满满的干货,更是告诉大家遇到问题后不要怕、更不能放弃,永远都能找到解题的方法,条条大路通罗马,一条不行就换一条,总会解决的!!!
    之前时间太紧,没来得及说明下为什么用了parseInt就可以了,其实这个跟Number类型的特性有关,即:javascript以64位双精度浮点数存储所有Number类型值,计算机存储的为二进制,而能存储的二进制为62位,超出就会有舍入操作,因此 JS 中能精准表示的最大整数是Math.pow(2, 53) - 1,十进制即9007199254740992大于 9007199254740992 的可能会丢失精度,而我们的数据中有超出16位的,问题就出来了。
    详细的解释大家可以看我这篇文章–JS-数据类型之数字(Number)

  • 相关阅读:
    kubernetes(K8S)学习笔记P1:基本概念和架构
    gorm-增删改查
    分布式监控平台——Zabbix
    [附源码]java毕业设计网上书店系统
    工程管理系统简介 工程管理系统源码 java工程管理系统 工程管理系统功能设计
    尿频中医如何辩证治疗
    前端编程技术UP之研究大佬代码
    二次封装这几个 element-ui 组件后,让代码更加优雅了
    【Linux操作系统】进程间通信(管道、共享内存、信号量)
    Python函数的参数与返回值
  • 原文地址:https://blog.csdn.net/weixin_44384273/article/details/133085053