最近对canvas画布非常感兴趣,起初是想要实现简单的3D效果,发现有点困难,还是一步一步来了解canvas吧,做了个简单的流星小动画效果。
一、画星星
首先我们需要在画布上画上一颗闪亮的星星,这里我们封装了一个方法,传入参数x(横坐标)、y(纵坐标)、r(星星的内半径)
function draw(x, y, r) {
gc.beginPath();
//设置是个顶点的坐标,根据顶点制定路径
for (var i = 0; i < 5; i++) {
gc.lineTo(Math.cos((18+i*72)/180*Math.PI)*2*r+x,
-Math.sin((18+i*72)/180*Math.PI)*2*r+y);
gc.lineTo(Math.cos((54+i*72)/180*Math.PI)*r+x,
-Math.sin((54+i*72)/180*Math.PI)*r+y);
}
gc.closePath();
//设置边框样式以及填充颜色
gc.lineWidth="1";
gc.fillStyle = "#F6F152";
gc.strokeStyle = "#F5270B";
gc.fill();
gc.stroke();
}
二、动画
现在的星星画好了,那么之后我们要实现让星星动起来了,怎么动呢?当然是横纵坐标的变化了呀,但是我们知道画布上的星星并不能如html中的div一样作为一个单独的盒子来移动,我们都知道动画的实现其实也可以是每个静止的状态整合起来达到动态的效果,所以我们可以在新的位置画上一个新的星星,再把原来位置的星星擦除就可以实现了,真棒
x=Math.random()*500
y=Math.random()*50
r=Math.random()*5 + 3
id = setInterval(() => {
gc.clearRect(0,0,1000,600);
if(x < 1000){
x += 2;
y += 2;
draw(x, y, r);
}
}, 10);
其中擦除我这用了canvas的clearRect方法,对整个画布区域进行了擦除,小伙伴儿们有其他更好的方法也可以评论区说一下哟
三、流星
所谓流星自然不能只有一颗星星,那么我们就用计时器来实现产生多个星星吧
let c = { r: 10,x:10,y:10 };
let id = null;
const cv = document.querySelector("canvas");
const gc = cv.getContext("2d");
const a = document.querySelector("#a");
let circleArr = [];
setInterval(() => {
circleArr.push({
x:Math.random()*500,
y:Math.random()*50,
r:Math.random()*5 + 3,
})
}, 500);
id = setInterval(() => {
gc.clearRect(0,0,1000,600);
let newArr = [];
for(var i = 0;i < circleArr.length;i++){
if(circleArr[i].x < 1000){
circleArr[i].x += 2;
circleArr[i].y += 2;
newArr.push(circleArr[i]);
draw(circleArr[i].x, circleArr[i].y, circleArr[i].r);
}
}
circleArr = newArr;
}, 10);
function draw(x, y, r) {
gc.beginPath();
//设置是个顶点的坐标,根据顶点制定路径
for (var i = 0; i < 5; i++) {
gc.lineTo(Math.cos((18+i*72)/180*Math.PI)*2*r+x,
-Math.sin((18+i*72)/180*Math.PI)*2*r+y);
gc.lineTo(Math.cos((54+i*72)/180*Math.PI)*r+x,
-Math.sin((54+i*72)/180*Math.PI)*r+y);
}
gc.closePath();
//设置边框样式以及填充颜色
gc.lineWidth="1";
gc.fillStyle = "#F6F152";
gc.strokeStyle = "#F5270B";
gc.fill();
gc.stroke();
}
这里我把每个星星的位置大小存放在数组里面,方便数据的操作,在星星的横坐标超出画布的时候,将星星删除,避免数据的污染,这就好啦