Canvas绘制圆形
圆形也是开发中常见的图形,本章我将会学习如何和绘制一个圆形,并开发一个在canvas中的圆形跟随鼠标的案例,主要是圆形的内容实在是不多,单独一章内容太少,写入矩形,但又不恰当,基础图形不止圆形一个,所以想了一下,还是单独开一章节加一个案例的形式来写作。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
#container {
border: 1px solid black;
}
</style>
</head>
<body>
<canvas id="container" width="1000" height="600"></canvas>
<script src="./index.js"></script>
</body>
</html>
绘制一个基础的圆
context.arc()是canvas提供的一个圆弧绘制工具,可以根据不同的参数绘制出,半圆,整圆,圆弧等图形
const canvas = document.getElementById("container");
const context = canvas.getContext("2d");
context.arc(x, y, radius, startAngle, endAngle, [anticlockwise]);
参数解释:
- x:圆弧中心(圆心)的 x 轴坐标。
- y:圆弧中心(圆心)的 y 轴坐标。
- radius:圆弧的半径,必须为正值
- startAngle:圆弧的起始点,从 x 轴方向开始计算,以弧度为单位。
- endAngle:圆弧的终点,从 x 轴方向开始计算,以弧度为单位。
- anticlockwise:可选的布尔值,如果为true,逆时针绘制圆弧,反之,顺时针绘制。默认为false顺时针。
绘制一个顺/逆时针的圆弧,顺时针路径为一个弧度,逆时针相反,注意(x,y)是圆心距离画布的位置,并非圆的边缘,所以在确定圆的位置的时候,要考虑是否能够显示完整的半径。
// 顺时针
// 起始点0 结束点1 顺时针:图一
context.beginPath();
context.arc(200, 150, 100, 0, 1, false);
context.stroke()
// 起始点0 结束点1 逆时针:图二
context.beginPath();
context.arc(500, 150, 100, 0, 1, true);
context.stroke()
// 顺时针绘制一个大圆弧 起始点1 结束点6 顺时针:图三
context.beginPath();
context.arc(800, 150, 100, 1, 6, false);
context.stroke()
// 绘制一个半圆 顺时针:图四
context.beginPath();
context.arc(200, 450, 100, 0, Math.PI, false);
context.fill()
// 绘制一个半圆 逆时针:图五
context.beginPath();
context.arc(500, 450, 100, 0, Math.PI, true);
context.fill()
// 绘制一个90度的扇形圆弧 顺时针:图六
context.beginPath();
context.arc(800, 450, 100, 0, Math.PI / 2, false);
context.fill()
解释:
- 图一为例,1圆弧约等于57°,完整的弧度为360°,弧度的理解可以参考百度百科弧度
- 绘制的起始点默认为0,可以理解为3点钟位置,然后分别顺/逆时针绘制一个圆弧,弧度的表达也可写成圆周率Π即代码表达
Math.PI,1Π=180°,可以结合图四参考理解,当然,写成3.14也是正确的,比如3.14 * 2就会绘制一个完成圆,3.14 / 2 就会绘制一个角度为90°的圆弧,这里要注意,fill()并不会补全为一个完整的扇形,因为闭合是以两点划线,也就是开始点和结束点连接,形成闭合。
实现一个跟随鼠标的彩球扩散特效
实现思路:
- 绑定canvas的鼠标移动事件
- 在鼠标移动时,用定时器改变小球的位置与大小(在退出时记得清除定时器哦)
- 将半径小于0的小球删除,因为已经失去了显示的意义,删除可以节省性能
const canvas = document.getElementById("container");
const context = canvas.getContext("2d");
const ballList = [] // 储存圆得实例
let timer = null
class Ball {
constructor(id, x, y, radius) {
this.id = id // id
this.x = x // 距离画布的水平位置
this.y = y // 距离画布的垂直位置
this.radius = radius // 半径
this.moveX = parseInt(Math.random() * 10) - 5 // 每50毫秒移动的距离,如果需要一个扩散的效果,那么就需要一些负数移动所以这里再 -5
this.moveY = parseInt(Math.random() * 10) - 5
}
renderRound() {
// 渲染圆
const { x, y, radius } = this
context.beginPath();
context.arc(x, y, radius, 0, Math.PI * 2, false);
const color = this.getRandomColor()
context.fillStyle = color;
context.fill()
context.closePath();
}
updateRound() {
// 更新圆
this.x += this.moveX // 更新圆得位置
this.y += this.moveY // 更新圆得位置
this.radius -= 0.5 // 更新圆的大小
if (this.radius <= 0) {
// 半径小于0,直接删除当前得实例
this.removeRound()
} else {
// 渲染圆
this.renderRound()
}
}
removeRound() {
// 删除圆
for (let i = 0; i < ballList.length; i++) {
if (this.id === ballList[i].id) {
ballList.splice(i, 1)
}
}
}
getRandomColor() {
// 获取随机颜色
const colorStr = '1,2,3,4,5,6,a,b,c,d,e,f'
const colorSplit = colorStr.split(',')
let color = '#'
for (let i = 0; i < 6; i++) {
const r = parseInt(Math.random() * colorSplit.length)
color += colorSplit[r]
}
return color
}
}
canvas.addEventListener('mousemove', function (event) {
// 鼠标每次移动时,创建一个圆
const id = new Date().getTime() * parseInt(Math.random() * 10)
const ball = new Ball(id, event.offsetX, event.offsetY, 20)
ballList.push(ball)
})
timer = setInterval(() => {
context.clearRect(0, 0, canvas.width, canvas.height);
for (let i = 0; i < ballList.length; i++) {
if (ballList[i]) {
ballList[i].updateRound()
}
}
}, 50);
// // 根据需要清除定时器
// clearInterval(timer)
结尾
本章节我们再次回顾了canvas面向对象的编程思维,所用到的也是之前章节的部分技术,我们在学习圆形绘制的时候,可能通过文字表达,会有一些生涩难懂,也有可能是我表达的不够准确,望见谅,有好的建议和希望我加入的其他抒写方式,也可以私我,合适的话我调整,争取能写出通俗能懂得文章。
感谢观看!!!