Preface

I have received a job these days and need to make a parking lot diagram. The first thing that comes to my mind is to use Canvas to draw. Since Canvas was only used briefly in the early stage, and not officially used in the project, this time I also touched the document cross the river 😂.

How to draw

Canvas is a canvas, an Html tag that requires a script to draw graphics. <canvas> simple to use

<canvas id="canvas"></canvas>

Add tags directly on the page, you must use scripts to draw graphics

var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
// 设置宽高
canvas.width = 500;
canvas.height = 500;

ctx.beginPath(); // 开始路径
ctx.rect(10, 10, 100, 100); // 绘制矩形

ctx.fillStyle = '#eee'; // 填充颜色
ctx.fill(); // 路径填充

You can see that a simple rectangle will appear in the canvas
image.png
where getContext is to get the Canvas object; it has two parameters:

  • contextType context type (2d, webgl, webgl2)
  • contextAttributes context attributes; for details, please refer to MDN

The canvas has a default height of 300 × 150 . There is one point to note about the height setting here: if we use css to set the height, the canvas will be scaled according to the ratio of 300 × 150, if you set 500 × 500, it may be deformed. So we'd better use Javascript or set the high width directly on the label.

Drawing steps

From the above series of use cases, we can summarize the approximate method of drawing the path

Create the canvas

Use ID to get the canvas object

var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');

Start drawing the path

Use beginPath start drawing

ctx.beginPath();

Draw path

Here we can use the various methods of drawing paths provided by Canvas; some common drawing methods

Method Description
arc()Create arc
rect()Create rectangle
fillRect()Draw a rectangular path area
strokeRect()Draw a rectangular path stroke
arcTo()Create an arc/curve between two tangents
moveTo()Move the path to the specified point in the canvas without creating a line
lineTo()Add a new point, and then create a line from that point to the last specified point in the canvas
clip()Cut an area of ​​any shape and size from the original canvas
quadraticCurveTo()Create a quadratic Bézier curve
bezierCurveTo()Create a cubic Bézier curve

Fill or stroke

After drawing the path, you can choose to close the path closePath or directly fill or stroke the path. These are some conventional methods

ctx.fillStyle = '#eee'; // 填充颜色
ctx.fill(); // 路径填充

ctx.strokeStyle = 'red'; // 路径描边颜色
ctx.stroke(); // 路径描边

Each graphic pattern drawn can be divided into these basic 4 steps. What we need to understand is actually the coordinate points drawn each time. As long as the coordinate points are confirmed, the drawn graph still has no errors.

Canvas operation

When the parking lot is drawn, it is necessary to click the parking space to display the parking space usage; since clicking on Canvas can only monitor the clicked coordinate point, it is necessary to determine whether the user clicked position is in the parking space, and now we know the starting point coordinates and the parking space width of the parking space High, so the judgment condition is

// 用户点击坐标 point
// 车位绘制信息 polylinePoints
  function checkPointInPolyline(point, polylinePoints) {
    // 当 x > 车位起始点 && x < 起始点 + 车位宽度 && y > 起始点 && y < 起始点 + 车位高度
    if (
      point.x >= polylinePoints.x &&
      point.x <= polylinePoints.x + polylinePoints.w &&
      point.y >= polylinePoints.y &&
      point.y <= polylinePoints.y + polylinePoints.h
    ) {
      return true;
    } else {
      return false;
    }
  }

We all know that the canvas is drawn from the origin (0, 0) upper left corner of the page, but because the parking lot is a vertically centered layout, when we click on the origin of the canvas, the coordinates
1213.gif
we can see that we get and It is not close to (0, 0) . This is because the mouse documnet the upper left corner of 060a7061fdf689 as the origin to obtain the coordinates; therefore, if you click a point in the parking space, you need to convert the (x, y)
Here you need to use getBoundingclientRect , which is used to obtain the position of the left, top, right and bottom of an element in the page relative to the browser window; use the obtained left , top values ​​to convert

canvas.addEventListener('click', function(e) {
  console.log(convertPoint(e.x, e.y))
})

function convertPoint(x, y) {
  var _info = canvas.getBoundingClientRect()
  return {
    x: x - _info.left,
    y: y - _info.top
  }
}

As you can see next, the coordinate point is close to the origin of the (0, 0)
1213.gif

Font

To draw fonts in Canvas, the key is to use the fillText(text, x, y [, maxWidth]) function:

  • text is the text
  • x, y is the starting point of drawing
  • maxWidth The maximum width occupied by the filled text

A complete font drawing is also very simple

ctx.fillStyle = '#333';
ctx.font = '18px SimSun, Songti SC';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText('imondo.cn', 200, 200);

image.png
But when we want to use a custom font, it is @font-face use the conventional 060a7061fdf7f2 setting, because the browser loads fonts generally lazily. During the drawing process, the font has not been loaded successfully; here is a new one. API new FontFace , you can monitor the font loading, and it is a Pormise

  const myFont = new FontFace('myFont', 'url(./webfont.ttf)');
  var _this = this;
  myFont
    .load()
    .then((font) => {
      document.fonts.add(font);
    })
    .then(function () {
      ctx.fillStyle = color;
      ctx.font = fontSize + ' myFont';
      ctx.textAlign = 'center';
      ctx.textBaseline = 'middle';
      ctx.fillText(text, x, y);
    });

IE , of course, don’t consider 060a7061fdf82a (IE: I feel offended 😂)

Canvas rotation zoom

Canvas rotation and scaling use rotate and scale respectively. The most important thing to note is that they are all based on the default center point (0, 0) to rotate or zoom, so before proceeding, we need to use translate to change the center point.
When we need to rotate the text by 90°, we need to change the center point first, and then rotate it. After the rotation, we need to restore the center point, otherwise the next time beginPath
drawn, it will be drawn based on the center point after translate

ctx.beginPath()
ctx.translate(200, 200);
ctx.rotate( 90 * Math.PI / 180)
ctx.translate(-200, -200);
ctx.fillStyle = '#333';
ctx.font = '18px SimSun, Songti SC';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText('imondo.cn', 200, 200);

image.png
same is true for scaling operations

ctx.translate(200, 200);
ctx.scale(1.5, 1.5);
ctx.translate(-200, -200);

image.png
In fact, the coordinates at the beginning of drawing are the coordinates of translate .

Mobile obfuscation

When the entire parking lot is drawn, it looks pretty good; but when it is opened on a mobile phone, it is blurred and makes people myopia. Checking the entire network, it is still a problem of the pixel ratio of mobile devices. The solution is to detect the pixel ratio of the device and draw the canvas element corresponding to the multiple ratio

function createHDCanvas(w = 300, h = 150) {
  var ratio = window.devicePixelRatio || 1;
  var canvas = document.getElementById('canvas');
  canvas.width = w * ratio; // 实际渲染像素
  canvas.height = h * ratio; // 实际渲染像素
  canvas.style.width = `${w}px`; // 控制显示大小
  canvas.style.height = `${h}px`; // 控制显示大小
  canvas.getContext('2d').setTransform(ratio, 0, 0, ratio, 0, 0);
  return canvas;
}

to sum up

It has been almost half a day since the whole drawing, mainly because I Canvas not familiar with 060a7061fdf969, but after the drawing is completed, I have a clearer understanding of the whole drawing process; I still have a certain reserve of some business technologies in the later period.

Finally, attach:


Reference:

Welcome to pay attention to [What the front-end learns] to communicate together

image


Mondo
968 声望19 粉丝

现在开始,从心出发