We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
这是基于 React + Canvas 画的一朵樱花。
首先需要了解一些 canvas 的概念。使用 <canvas></canvas> 会创建一块画布,我们可以在这个上面绘制内容。
<canvas></canvas>
var canvas = document.getElementById('tutorial'); //获得 2d 上下文对象 var ctx = canvas.getContext('2d');
一般来说,canvas 创建的画布以左上角作为原点(0, 0)。
我们使用 beginPath 来创建一条路径。然后用 moveTo 移动到起始点坐标,用 closePath 闭合路径。
beginPath
moveTo
closePath
可以使用 stroke 来绘制图形轮廓,用 fill 来绘制填充内容。
stroke
fill
function draw(){ var canvas = document.getElementById('tutorial'); if (!canvas.getContext) return; var ctx = canvas.getContext("2d"); ctx.beginPath(); //新建一条path ctx.moveTo(50, 50); //把画笔移动到指定的坐标 ctx.lineTo(200, 50); //绘制一条从当前位置到指定坐标(200, 50)的直线. //闭合路径。会拉一条从当前点到path起始点的直线。如果当前点与起始点重合,则什么都不做 ctx.closePath(); ctx.stroke(); //绘制路径。 } draw();
可以通过 arc 来绘制一个圆形,它接受四个参数,分别是圆形坐标、半径、开始弧度、结束弧度、顺逆时针。 Math.PI 就是数学上的圆周率π,一般是 3.1415926...
arc
Math.PI
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();
弧度(rad)是数学上面的概念,一般是指从圆心拉了两条半径,这俩半径中间的圆弧,如果它的长度和半径相等,那么这个角度就是一弧度。
一般来说,一个圆有 2 * π 个弧度,也是因为圆周长是 2πR。
2 * π
2πR
const rad = 180 / π
以前初中就学过这俩知识,对于一个直角三角形来说,cos 就是较长的直角边除以斜边,sin 则是较短的直角边除以斜边。
在 JavaScript 里面会接收弧度作为参数,所以需要手动转换度数为弧度。
const cos = Math.cos(2 * rad) const sin = Math.sin(2 * rad)
一般我们绘制贝塞尔曲线都是用的二次贝塞尔曲线,它有一个起始点、控制点、结束点三个坐标来决定的。
感兴趣的可以看一下这篇文章:怎么理解贝塞尔曲线?
在 canvas 里面也提供了 quadraticCurveTo(cp1x, cp1y, x, y) 方法来绘制曲线。
quadraticCurveTo(cp1x, cp1y, x, y)
了解完上面的知识后,开始绘制我们的樱花。首先要知道,樱花包含花瓣和花蕊两部分,花蕊在花瓣正中间。
我们考虑用粉红色来绘制花瓣,用白色绘制花蕊。
樱花有五瓣,所以一瓣的夹角是 75°,也就是 75 / rad 弧度。
75 / rad
首先我们需要声明一个樱花类,它有半径、圆心坐标、颜色等属性。接着开始绘制。
class Flower { r = r; color = color; cx = 800; cy = 500; }
绘制最麻烦的一步就是花瓣的弧度,这是个贝塞尔曲线。观察图片,我们可以以花瓣凹进去的三角形(剪刀形状)到圆心距离作为半径,以剪刀两边的作为一个贝塞尔曲线的控制点。
那么这个控制点的坐标是什么呢?如上图所示,其实我们的控制点p1在分割线上,和原点距离是半径的长度,而终点在p2上面,长度大概是半径的1.2-1.4倍。p0p1 和 p0p2 大概构成了 25 °的角。
所以这里也很容易进行计算。首先计算出控制点 p1 的位置,肯定是 cx + R * Math.cos(a * part / rad),这里的 a 就是循环生成的,a * part / rad 就是指的是第几瓣的角度。
cx + R * Math.cos(a * part / rad)
a * part / rad
const x0 = cx + R * Math.cos((a * part) / rad); const y0 = cy + R * Math.sin((a * part) / rad);
然后我们找到 1/3 (25°)的坐标。设置 R1 为 1.3 倍半径。
const x1 = cx + R1 * Math.cos((a * part + 2 * part / 6) / rad); const y1 = cy + R1 * Math.sin((a * part + 2 * part / 6) / rad);
这样关键的两个点就画了出来,接着生成贝塞尔曲线。
ctx.moveTo(cx, cy); ctx.quadraticCurveTo(x0, y0, x1, y1);
然后我们绘制出剩下的一半花瓣。最终代码如下:
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); // 这个点其实在中点,也就是 37.5°的地方 const x2 = cx + R * Math.cos((a * part + 3 * part / 6) / rad); 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();
接着绘制花蕊,其实花蕊很容易绘制,因为它们分别处于 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);
这几个坐标点都找好了,但是不要忘了在终点绘制一个小圆点,这个更像花蕊上面的蕊头。
ctx.arc(ax0, ay0, 2, 0, 2 * Math.PI)
最终的代码如下:
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 = [] // 如果半径大于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();
最后,我把这个项目部署到了线上,可以访问 http://sakura.gyyin.top 来访问到。
The text was updated successfully, but these errors were encountered:
No branches or pull requests
樱花
这是基于 React + Canvas 画的一朵樱花。
canvas
首先需要了解一些 canvas 的概念。使用
<canvas></canvas>
会创建一块画布,我们可以在这个上面绘制内容。绘制路径
一般来说,canvas 创建的画布以左上角作为原点(0, 0)。
我们使用
beginPath
来创建一条路径。然后用moveTo
移动到起始点坐标,用closePath
闭合路径。可以使用
stroke
来绘制图形轮廓,用fill
来绘制填充内容。绘制圆形
可以通过
arc
来绘制一个圆形,它接受四个参数,分别是圆形坐标、半径、开始弧度、结束弧度、顺逆时针。Math.PI
就是数学上的圆周率π,一般是 3.1415926...弧度
弧度(rad)是数学上面的概念,一般是指从圆心拉了两条半径,这俩半径中间的圆弧,如果它的长度和半径相等,那么这个角度就是一弧度。
一般来说,一个圆有
2 * π
个弧度,也是因为圆周长是2πR
。cos 和 sin
以前初中就学过这俩知识,对于一个直角三角形来说,cos 就是较长的直角边除以斜边,sin 则是较短的直角边除以斜边。
在 JavaScript 里面会接收弧度作为参数,所以需要手动转换度数为弧度。
贝塞尔曲线
一般我们绘制贝塞尔曲线都是用的二次贝塞尔曲线,它有一个起始点、控制点、结束点三个坐标来决定的。
感兴趣的可以看一下这篇文章:怎么理解贝塞尔曲线?
在 canvas 里面也提供了
quadraticCurveTo(cp1x, cp1y, x, y)
方法来绘制曲线。开始绘制
了解完上面的知识后,开始绘制我们的樱花。首先要知道,樱花包含花瓣和花蕊两部分,花蕊在花瓣正中间。
我们考虑用粉红色来绘制花瓣,用白色绘制花蕊。
樱花有五瓣,所以一瓣的夹角是 75°,也就是
75 / rad
弧度。首先我们需要声明一个樱花类,它有半径、圆心坐标、颜色等属性。接着开始绘制。
花瓣
绘制最麻烦的一步就是花瓣的弧度,这是个贝塞尔曲线。观察图片,我们可以以花瓣凹进去的三角形(剪刀形状)到圆心距离作为半径,以剪刀两边的作为一个贝塞尔曲线的控制点。
那么这个控制点的坐标是什么呢?如上图所示,其实我们的控制点p1在分割线上,和原点距离是半径的长度,而终点在p2上面,长度大概是半径的1.2-1.4倍。p0p1 和 p0p2 大概构成了 25 °的角。
所以这里也很容易进行计算。首先计算出控制点 p1 的位置,肯定是
cx + R * Math.cos(a * part / rad)
,这里的 a 就是循环生成的,a * part / rad
就是指的是第几瓣的角度。然后我们找到 1/3 (25°)的坐标。设置 R1 为 1.3 倍半径。
这样关键的两个点就画了出来,接着生成贝塞尔曲线。
然后我们绘制出剩下的一半花瓣。最终代码如下:
花蕊
接着绘制花蕊,其实花蕊很容易绘制,因为它们分别处于 1/3、1/2、2/3 处。
这几个坐标点都找好了,但是不要忘了在终点绘制一个小圆点,这个更像花蕊上面的蕊头。
最终的代码如下:
总结
最后,我把这个项目部署到了线上,可以访问 http://sakura.gyyin.top 来访问到。
The text was updated successfully, but these errors were encountered: