Canvas Basic Use 2 [Introduction Tutorial]

In the previous article, please see the basic use of canvas 1

1. Conversion

convert

  • In the canvas, you can also have some effects similar to css2D conversion like css
  1. displacement
    • grammar:ctx.translate(x, y)
    • Note: Be sure to perform displacement before drawing (stroke or fill)
  2. zoom
    • grammar:ctx.scale(x, y)
    • Note: Be sure to scale before drawing (stroke or fill)
  3. to rotate
    • grammar:ctx.rotate(弧度值)
      • Angle to radian formula:弧度 = Math.PI/180*角度
    • Note: Be sure to rotate before drawing (stroke or fill)
    • The center of rotation is the 0,0 point of the canvas, and the center of rotation can be modified with displacement

image.png

  1. Notice:
    • All the transformation operations of canvas are not just manipulating a certain shape, but transforming the entire canvas
    • If you need to perform different transformations on multiple shapes, you need to save the brush state before each drawing, and reset the brush state after drawing
      • Save brush state:ctx.save();
        • before the general existence and conversion
      • Reset brush state:ctx.restore();
        • generally exists after conversion
// 绘制两个矩形
ctx.strokeRect(100, 100, 100, 100);
ctx.strokeRect(300, 100, 100, 100);

Screenshot 2023-07-09 22.15.46.png

// 对画布进行旋转
ctx.rotate(0.5);
ctx.strokeRect(100, 100, 100, 100);
ctx.strokeRect(300, 100, 100, 100);

Screenshot 2023-07-09 22.16.52.png

// 将 旋转和其中一个矩形绘制 存储为一次记录
ctx.save();
ctx.rotate(0.5);
ctx.strokeRect(100, 100, 100, 100);
ctx.restore();

ctx.strokeRect(300, 100, 100, 100);

Screenshot 2023-07-09 22.18.05.png

2. Gradient color

  1. The gradient color of canvas is to configure the gradient color scheme in advance (transition from color 1 to color 2), and then set the gradient color scheme to the fill style
  2. gradient form
    • linear gradient
      • Create the gradient:const lg = ctx.createLinearGradient(起点x坐标, 起点y坐标, 终点x坐标, 终点y坐标)
        • specify gradient range
      • Add gradient color:lg.addColorStop(0, 'red')
        • Add color to the specified position, 0 means the start coordinate, 1 means the end coordinate, and the middle part will be automatically filled with gradient color
  const canvas = document.querySelector(".mycanvas");

  canvas.width = 800;
  canvas.height = 400;

  const ctx = canvas.getContext("2d");

  const lg = ctx.createLinearGradient(0, 0, 800, 400);
  
  lg.addColorStop(0, 'red');
  lg.addColorStop(1, 'green');

  ctx.fillStyle = lg;
  ctx.fillRect(0, 0, 800, 400);

Screenshot 2023-07-09 22.47.33.png

  • radial gradient
    • Create the gradient:const lg = ctx.createRadialGradient(x1, y1, r1, x2, y2, r2);
      • x1: x-axis coordinate of the center of the starting circle
      • y1: the y-axis coordinate of the center of the starting circle
      • r1: starting circle radius
      • x2: x-axis coordinate of the end circle center
      • y2: the y-axis coordinate of the center of the end circle
      • r2: End circle radius
    • Add gradient color:lg.addColorStop(0, 'red')
      • Synchronous Gradient
const canvas = document.querySelector(".mycanvas");

canvas.width = 800;
canvas.height = 400;

const ctx = canvas.getContext("2d");

const lg = ctx.createRadialGradient(200, 200, 50, 200, 200, 200);

lg.addColorStop(0, 'red');
lg.addColorStop(1, 'green');

ctx.fillStyle = lg;
ctx.fillRect(0, 0, 800, 400);

Screenshot 2023-07-09 22.53.54.png

  1. Different gradients in multiple regions
    • The essence is to configure multiple sets of gradient schemes and draw them into different shapes
const canvas = document.querySelector(".mycanvas");

canvas.width = 800;
canvas.height = 400;

const ctx = canvas.getContext("2d");

const rg = ctx.createRadialGradient(200, 200, 50, 200, 200, 200);
rg.addColorStop(0, 'red');
rg.addColorStop(1, 'green');

ctx.fillStyle = rg;
ctx.fillRect(0, 0, 400, 400);

const lg = ctx.createLinearGradient(400, 0, 800, 0);
lg.addColorStop(0, 'blue');
lg.addColorStop(1, 'yellow');
ctx.fillStyle = lg;
ctx.fillRect(400, 0, 400, 400);

Screenshot 2023-07-09 23.03.24.png

3. Bezier curve

  • Bezier curve (Bezier curve) is a very important parametric curve in computer graphics. It describes a curve through an equation. According to the highest order of the equation, it is divided into linear Bezier curve and quadratic Bezier curve. , cubic Bezier curves, and higher order Bezier curves.
    • The Bezier curve needs to provide parameters of several points, the first is the start and end of the curve
    • If the number of control points is 0, we call it linear Bezier;
    • If the number of control points is 1, it is a second-order Bezier curve;
    • If the number of control points is 2, it is a third-order Bezier curve, and so on.
  1. second-order Bezier curve
    • In fact, two straight lines are drawn from three points.
    • Then start at the start of each line at the same time and move towards the end, getting points proportionally. These points are then reconnected to produce n - 1 straight lines.
    • In this way, we continue the same operation until it becomes a straight line, and then get a point proportionally, which is the point where the curve passes.
    • When we increase the scale a little bit (from 0 to 1), we get all the points in the middle of the curve, and finally draw a complete curve.

  1. Let's take a look at the third-order Bezier curve
    • It is the same as the second-order Bezier curve, but the number of control points becomes two

  1. In canvas, we don't need to manually calculate so many points, canvas directly provides related API
    • Second-order Bezier curve:ctx.quadraticCurveTo(p1x, p1y, p2x, p2y)
    • Third-order Bezier curve:ctx.bezierCurveTo(p1x, p1y, p2x, p2y, p3x, p3y)
    • Before that, you need to use moveTo to determine the position of p0

second order

const cvs = document.querySelector(".cvs");
cvs.width = 400;
cvs.height = 400;

const ctx = cvs.getContext("2d");

ctx.beginPath();
ctx.moveTo(100, 100);
ctx.quadraticCurveTo(300, 200, 200, 300);
ctx.stroke();

image.png
third order

const cvs = document.querySelector(".cvs");
cvs.width = 400;
cvs.height = 400;

const ctx = cvs.getContext("2d");

ctx.beginPath();
ctx.moveTo(100, 100);
ctx.bezierCurveTo(60, 80, 150, 30, 170, 150);
ctx.stroke();

image.png
Multi-stage

ctx.beginPath();
ctx.moveTo(75, 25);
ctx.quadraticCurveTo(25, 25, 25, 62.5);
ctx.quadraticCurveTo(25, 100, 50, 100);
ctx.quadraticCurveTo(50, 120, 30, 125);
ctx.quadraticCurveTo(60, 120, 65, 100);
ctx.quadraticCurveTo(125, 100, 125, 62.5);
ctx.quadraticCurveTo(125, 25, 75, 25);
ctx.stroke();
ctx.moveTo(75, 40);
ctx.bezierCurveTo(75, 37, 70, 25, 50, 25);
ctx.bezierCurveTo(20, 25, 20, 62.5, 20, 62.5);
ctx.bezierCurveTo(20, 80, 40, 102, 75, 120);
ctx.bezierCurveTo(110, 102, 130, 80, 130, 62.5);
ctx.bezierCurveTo(130, 62.5, 130, 25, 100, 25);
ctx.bezierCurveTo(85, 25, 75, 37, 75, 40);
ctx.fill();

4. Draw pictures

  1. Create a picture (non-canvas operation)
    • Create a picture object:const img = new Image();
    • Set the resource address:img.src = "图片地址"
    • Resource loading complete:img.onload = function(){ / * 图片加载完成 */ }
  2. Draw pictures to canvas
    • Three parameters:gd.drawImage(图片对象, x, y)
      • Start drawing from the x,y coordinates of the canvas
const canvas = document.querySelector(".mycanvas");

canvas.width = 800;
canvas.height = 400;

const ctx = canvas.getContext("2d");

const img = new Image();
img.src = "../1.png";

img.onload = function(){
    
    
  ctx.drawImage(this, 0, 100);
}

Screenshot 2023-07-09 23.18.25.png

  • Five parameters:gd.drawImage(图片对象, x, y, w, h)
    • Start drawing from the x, y coordinates of the canvas, and draw to an area of ​​width w and height h
const canvas = document.querySelector(".mycanvas");

canvas.width = 800;
canvas.height = 400;

const ctx = canvas.getContext("2d");

const img = new Image();
img.src = "../1.png";

img.onload = function(){
    
    
  ctx.drawImage(this, 0, 100, 200, 200);
}

Screenshot 2023-07-09 23.18.59.png

  • Nine parameters:gd.drawImage(图片对象, sx, sy, sw, sh, dx, dy, dw, dh)
    • s = source original image position width and height
    • d = destination Where is the target (canvas) drawn and how big is it
const canvas = document.querySelector(".mycanvas");

canvas.width = 800;
canvas.height = 400;

const ctx = canvas.getContext("2d");

const img = new Image();
img.src = "../1.png";
// 图片资源宽高
const imgW = 128;
const imgH = 194;
img.width = 128;
img.height = 194;

img.onload = function(){
    
    
  ctx.drawImage(this, 0, 0, imgW/4, imgH/4, 0, 100, imgW/4, imgH/4);
}

Screenshot 2023-07-09 23.20.21.png

5. Events

  1. There is no event system in the canvas, you can only manually detect the event area by adding events to the canvas element and cooperating with the event object
  2. Rectangular detection formula:
    • 点击x > 矩形x && 点击x < 矩形x + 矩形w && 点击y > 矩形y && 点击y < 矩形y + 矩形h
  3. Circle detection formula:
    • Using the Pythagorean theorem: a^2 + b^2 = c^2
    • a = center x - click x
    • b = center y - click on y
    • c = Math.sqrt( a * a + b * b )
    • If c < r, then in the circular area
  4. automatic detection
    • ctx.isPointInPath(x, y)
    • Return value: Boolean value, indicating whether the specified coordinates are within a path range

Six, export (understand)

download.onclick = function(){
    
    
  // 将canvas数据转成base64数据
  const base64 = canvas.toDataURL("image/png");
  // 将base64数据解码
  const strBase64 = atob( base64.split(",")[1] );
  // 创建utf-8原始数据(长度为base64解码后的字符长度)
  const utf_8 = new Uint8Array(strBase64.length);
  // 将base64解码后的数据转成Unicode编码后,存入utf-8数组
  for(let n=0;n<strBase64.length;n++){
    
    
    utf_8[n] = strBase64.charCodeAt(n)
  }
  // 根据utf-8数据,创建文件对象
  const file = new File([utf_8], "测试图片", {
    
    type:"image/png"});
  // 根据文件对象创建url字符
  const href = URL.createObjectURL(file);
  // 准备a标签,用于下载文件
  const a = document.createElement("a");
  a.href = href;
  a.download = "测试图片";
  document.body.appendChild(a);
  a.click();
  // 删除a标签
  a.remove();
  // 释放指向文件资源的url字符
  URL.revokeObjectURL(href);
}

7. Summary

  • Displacement:ctx.translate(x, y)
  • Rotation:ctx.rotate(弧度值)
  • Zoom:ctx.scale(x, y)
  • Save brush state:ctx.save()
  • Reset brush state:ctx.restore()
  • Create a linear gradient:ctx.createLinearGradient(起点x坐标, 起点y坐标, 终点x坐标, 终点y坐标)
  • Create a radial gradient:const lg = ctx.createRadialGradient(x1, y1, r1, x2, y2, r2);
  • Add gradient color:lg.addColorStop(0, 'red')
  • Draw the picture:gd.drawImage(图片对象, x, y)
  • Check if the specified coordinates are within a certain path range:ctx.isPointInPath(x, y)

Eight, practice

  1. mechanical clock
  2. sporty little man
  3. airplane war
  4. line chart

Guess you like

Origin blog.csdn.net/weixin_41636483/article/details/132024621