canvas-Introduction to the drawing library fabric.js

In general, for simple drawing, the native methods of canvas can also be used, such as drawing a line, drawing a circle, a square, and adding copywriting.

  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);

Look at the renderings.
Insert image description here
If this is really the only need, the native method is also very good, saving the need to load a js library. However, the reality is often very cruel. How can it be so simple? There is no interaction here, such as displacement, dragging, etc. on the existing graphics. The complexity rises. At this time, a good canvas js library is very useful. It's necessary.
fabric.js is a relatively comprehensive and easy-to-use canvas js library that I have used;
let’s start with the code:

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"
	]
};
// 可以看出上面数据一个是画线,一个是画不规则区域,这是实际项目中用到的数据,拿到这里自有妙处,后面会说

fabric.js uses

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);

Even if the fabric initialization is completed at this point, there is a very important point here that the official documents and almost all blogs about fabric teaching do not mention, that is, how to assign different values ​​​​to canvas.style.width and canvas.width. This is A very practical point, because the coordinate points are based on canvas.width, but our canvas.style.width must be consistent with the design.
For example: we need to draw on a picture, and the coordinate points are based on the original image of the picture. marked on, and the design cannot be displayed according to the original size. At this time, the coordinate points will be inconsistent with canvas.style.width. There are two methods to solve this problem:
1. The coordinate points are based on canvas.style.width / img. Adjust the ratio of width
2. Keep canvas.width consistent with img.width, and canvas.style.width consistent with the width of the design draft.
Obviously the second solution is simpler and more practical.
Since the official website does not provide a method, we have to look at the source code to do it. What, because canvas.width must be set.
We found that _setBackstoreDimension and _setCssDimension were called when settingDimensions.
Insert image description here
Obviously here is canvas.width
Insert image description here
and here is canvas.style.width
Insert image description here
. Let’s keep it simple today. Just look at drawing lines and irregularities. graphics

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;
}

At this time, everyone will see that I have a parseInt operation, because when I use the original data to draw, the line can come out but the Polygon does not. It makes me very depressed. I checked it for a long time, and finally when I stared at the data in a daze , looking at the long decimal places, I suddenly had a whim , so parseInt was born, and the area can also be seen on the page. It is really a pitfall. It is absolutely impossible to discover this point without doing a project.
This is also the reason why I have to write such an article today despite the postponement of the project. Although there is not much knowledge about fabric, it is absolutely full of useful information. It also tells everyone not to be afraid and not to give up when encountering problems. You will always find a solution. All roads lead to Rome, if one method doesn't work, just try another one, and it will always work out! ! !
Time was too tight before, so I didn’t have time to explain why parseInt was used. In fact, this is related to the characteristics of the Number type, that is: JavaScript stores all Number type values ​​as 64-bit double-precision floating point numbers, and the computer stores them in binary, but can The stored binary is 62 bits, and there will be rounding operations if it exceeds it. Therefore, the largest integer that can be accurately expressed in JS is Math.pow(2, 53) - 1. In decimal, it is 9007199254740992. If it is larger than 9007199254740992, the accuracy may be lost, and ours If there are more than 16 bits in the data, a problem will arise.
For a detailed explanation, you can read my article – JS-Data Type Number (Number)

Guess you like

Origin blog.csdn.net/weixin_44384273/article/details/133085053