The cherry blossom
Carry laowen. This is a cherry blossom based on React + Canvas.
canvas
First, you need to understand some concepts of canvas. Using
creates a canvas on which we can draw content.
var canvas = document.getElementById('tutorial');
// Get the 2D context object
var ctx = canvas.getContext('2d');
Copy the code
Draw the path
In general, canvas creates a canvas with the upper-left corner as the origin (0, 0).
We use beginPath to create a path. Then use moveTo to moveTo the starting point and closePath to close the path.
You can use stroke to draw the shape outline and fill to draw the fill content.
function draw(){
var canvas = document.getElementById('tutorial');
if(! canvas.getContext)return;
var ctx = canvas.getContext("2d");
ctx.beginPath(); // Create a path
ctx.moveTo(50.50); // Move the brush to the specified coordinates
ctx.lineTo(200.50); // Draw a line from the current position to the specified coordinates (200, 50).
// Close the path. Draws a line from the current point to the start of the path. If the current point coincides with the starting point, do nothing
ctx.closePath();
ctx.stroke(); // Draw the path.
}
draw();
Copy the code
Draw a circular
You can draw a circle through Arc, which takes four parameters: circular coordinates, radius, start radian, end radian, clockwise and counterclockwise. Math.PI is the mathematical equivalent of PI, usually 3.1415926…
function draw(){
var canvas = document.getElementById('tutorial');
if(! canvas.getContext)return;
var ctx = canvas.getContext("2d");
ctx.beginPath();
ctx.arc(50.50.40.0.Math.PI * 2.false);
ctx.stroke();
}
draw();
Copy the code
radian
A radian, or rad, is a mathematical concept, and it’s usually an arc between two radii drawn from the center of a circle, and if its length is equal to the radius, then the Angle is one radian.
In general, a circle has 2 PI radians, also because the circumference is 2 PI R.
const rad = 180/ PI.Copy the code
The sine and cosine
We learned these two things in junior high school, but for a right triangle, cosine is the longer side over the hypotenuse, and sine is the shorter side over the hypotenuse.
JavaScript accepts radians as arguments, so you need to manually convert degrees to radians.
const cos = Math.cos(2 * rad)
const sin = Math.sin(2 * rad)
Copy the code
Bessel curve
In general, quadratic Bezier curves are used to draw Bezier curves, which are determined by three coordinates: a starting point, a control point and an end point.
If you’re interested, take a look at this article: How to understand bezier curves?
The Canvas also provides quadraticCurveTo(cp1x, CP1y, x, y) methods to draw curves.
Began to draw
After knowing the above, start painting our cherry blossoms. The first thing to know is that cherry blossoms have two parts: petals and stamens, which are in the center of the petals.
We consider drawing petals in pink and stamens in white.
Cherry blossoms have five petals, so the Angle between one petal is 75 degrees, which is 75 over rad radians.
First we need to declare a cherry blossom class with attributes such as radius, center coordinates, color, and so on. And then you start drawing.
class Flower {
r = r;
color = color;
cx = 800;
cy = 500;
}
Copy the code
petals
The most difficult part of drawing is the curve of the petal, which is a Bezier curve. Looking at the picture, we can take the distance from the triangle (scissor shape) where the petal is recessed to the center of the circle as the radius, and the control points on either side of the scissor as a Bezier curve.
So what are the coordinates of this control point? As shown in the figure above, in fact, our control point P1 is on the dividing line, the distance from the origin is the length of the radius, and the end point is above P2, the length is about 1.2-1.4 times of the radius. P0p1 and P0P2 form an Angle of about 25 degrees.
So it’s also easy to calculate here. First, calculate the position of control point P1, which must be cx + R * math. cos(a * part/rad), where a is generated in the loop, and a * part/rad refers to the Angle of the lobe.
const x0 = cx + R * Math.cos((a * part) / rad);
const y0 = cy + R * Math.sin((a * part) / rad);
Copy the code
And then we find 1/3 of 25 degrees. Set R1 to 1.3 times the radius.
const x1 = cx + R1 * Math.cos((a * part + 2 * part / 6) / rad);
const y1 = cy + R1 * Math.sin((a * part + 2 * part / 6) / rad);
Copy the code
So the two key points are drawn, and the Bezier curve is generated.
ctx.moveTo(cx, cy);
ctx.quadraticCurveTo(x0, y0, x1, y1);
Copy the code
Then we draw the remaining half of the petals. The final code is as follows:
const x0 = cx + R * Math.cos((a * part) / rad); const y0 = cy + R * Math.sin((a * part) / rad); const x1 = cx + R1 * Math.cos((a * part + 2 * part / 6) / rad); const y1 = cy + R1 * Math.sin((a * part + 2 * part / 6) / rad); // Const x2 = cx + R * Math. Cos ((a * part + 3 * part / 6)/rad); // Const x2 = cx + R * Math. const y2 = cy + R * Math.sin((a * part + 3 * part / 6) / rad); const x3 = cx + R1 * Math.cos((a * part + 4 * part / 6) / rad); const y3 = cy + R1 * Math.sin((a * part + 4 * part / 6) / rad); const x4 = cx + R * Math.cos((a * part + part) / rad); const y4 = cy + R * Math.sin((a * part + part) / rad); // petal ctx.beginPath(); ctx.moveTo(cx, cy); ctx.quadraticCurveTo(x0, y0, x1, y1); ctx.lineTo(x2, y2); ctx.lineTo(x3, y3); ctx.quadraticCurveTo(x4, y4, cx, cy); ctx.fill(); ctx.stroke();Copy the code
The blossom
And then we draw the stamens, and the stamens are really easy to draw, because they’re at 1/3, 1/2, 2/3.
const ax0 = cx + R / 3 * Math.cos((a * part + 2 * part / 6) / rad);
const ay0 = cy + R / 3 * Math.sin((a * part + 2 * part / 6) / rad);
const ax1 = cx + R / 2 * Math.cos((a * part + 3 * part / 6) / rad);
const ay1 = cy + R / 2 * Math.sin((a * part + 3 * part / 6) / rad);
const ax2 = cx + R / 3 * Math.cos((a * part + 4 * part / 6) / rad);
const ay2 = cy + R / 3 * Math.sin((a * part + 4 * part / 6) / rad);
Copy the code
These coordinates are found, but don’t forget to draw a little dot at the end, this is more like the stamen head above the flower.
ctx.arc(ax0, ay0, 2.0.2 * Math.PI)
Copy the code
The final code looks like this:
const { ctx, cx, cy, r: R } = this
ctx.save();
ctx.strokeStyle = "#fff";
const ax0 = cx + R / 3 * Math.cos((a * part + 2 * part / 6) / rad);
const ay0 = cy + R / 3 * Math.sin((a * part + 2 * part / 6) / rad);
const ax1 = cx + R / 2 * Math.cos((a * part + 3 * part / 6) / rad);
const ay1 = cy + R / 2 * Math.sin((a * part + 3 * part / 6) / rad);
const ax2 = cx + R / 3 * Math.cos((a * part + 4 * part / 6) / rad);
const ay2 = cy + R / 3 * Math.sin((a * part + 4 * part / 6) / rad);
let ary = []
// If radius is greater than 40
if (R > 40) {
ary = [{
x: ax0,
y: ay0
}, {
x: ax1,
y: ay1
}, {
x: ax2,
y: ay2
}];
} else {
ary = [{
x: ax1,
y: ay1
}];
}
ctx.beginPath();
for (let i = 0; i < ary.length; i++) {
ctx.moveTo(cx, cy);
ctx.lineTo(ary[i].x, ary[i].y);
ctx.arc(ary[i].x, ary[i].y, 2.0.2 * Math.PI)
}
ctx.stroke();
ctx.restore();
Copy the code
conclusion
Finally, I deployed the project online, which can be accessed at Sakura.gyyin.top.
Welcome to Github: github.com/yinguangyao…