Article directory
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
- displacement
- grammar:
ctx.translate(x, y)
- Note: Be sure to perform displacement before drawing (stroke or fill)
- grammar:
- zoom
- grammar:
ctx.scale(x, y)
- Note: Be sure to scale before drawing (stroke or fill)
- grammar:
- to rotate
- grammar:
ctx.rotate(弧度值)
- Angle to radian formula:
弧度 = Math.PI/180*角度
- Angle to radian formula:
- 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
- grammar:
- 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
- Save brush state:
// 绘制两个矩形
ctx.strokeRect(100, 100, 100, 100);
ctx.strokeRect(300, 100, 100, 100);
// 对画布进行旋转
ctx.rotate(0.5);
ctx.strokeRect(100, 100, 100, 100);
ctx.strokeRect(300, 100, 100, 100);
// 将 旋转和其中一个矩形绘制 存储为一次记录
ctx.save();
ctx.rotate(0.5);
ctx.strokeRect(100, 100, 100, 100);
ctx.restore();
ctx.strokeRect(300, 100, 100, 100);
2. Gradient color
- 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
- 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
- Create the gradient:
- linear gradient
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);
- 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
- Create the 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);
- 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);
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.
- 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.
- 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
- 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 Bezier curve:
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();
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();
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
- 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(){ / * 图片加载完成 */ }
- Create a picture object:
- Draw pictures to canvas
- Three parameters:
gd.drawImage(图片对象, x, y)
- Start drawing from the x,y coordinates of the canvas
- Three parameters:
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);
}
- 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);
}
- 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);
}
5. Events
- 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
- Rectangular detection formula:
点击x > 矩形x && 点击x < 矩形x + 矩形w && 点击y > 矩形y && 点击y < 矩形y + 矩形h
- 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
- 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
- mechanical clock
- sporty little man
- airplane war
- line chart