Appearance
使你的鼠标和屏幕互动
使你的鼠标和屏幕互动
在第 5 节,我们实现了随机粒子;第 6 节,我们让随机粒子动了起来,并且简单介绍了 Canvas 制作动画的原理。
本节我们一起来看一下 Canvas 是怎么和我们的鼠标互动的。
我们先来看一下这个效果。
然后我们分析一下这个效果:鼠标移动,会在经过的地方创建一个圆,圆的半径由小变大,达到某个固定大小时该圆消失。圆的颜色也是在随机变化的(gif 图片时间较短,效果不明显)。
创建 Canvas 元素
首先我们还是要创建并获取 Canvas 元素,相信大家对此步骤应该很熟悉了吧。
这里也顺带将需要的参数直接写好了,我们将一些可以控制的变量直接写在参数中,这样在后面就可以获取参数直接使用。设置参数主要是为了更改方便。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
* {
padding: 0;
margin: 0;
}
#canvas {
background: #000;
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<script>
var canvas = document.getElementById('canvas'),
ctx = canvas.getContext('2d'),
WIDTH = canvas.width = document.documentElement.clientWidth,
HEIGHT = canvas.height = document.documentElement.clientHeight,
para = {
num: 100,
color: false, // 颜色 如果是false 则是随机渐变颜色
r: 0.9, // 圆每次增加的半径
o: 0.09, // 判断圆消失的条件,数值越大,消失的越快
a: 1
},
color,
color2,
round_arr = []; // 存放圆的数组
</script>
</body>
</html>
我们就创建一个黑色的全屏 Canvas 元素。
onmousemove
事件
在创建完了 Canvas 元素之后,我们要写鼠标移动的事件了,我们要考虑一下鼠标事件怎么写。
观察一下刚刚的 gif 图片,可以看出,在鼠标移动的过程中,不断地在鼠标滑过的位置产生一个逐渐变大的圆。
那么怎么让效果动起来呢?这就用到第 6 节讲到的知识了,我们在 Canvas 中创建动画的方式就是不断地清除屏幕内容然后重绘。
我们可以看出来,移动的轨迹是由一个一个的圆构成的,如果移动的速度过快的话,那么就可以明显看出一个一个的圆。
既然轨迹是由很多圆构成,那么我们就应该使用数组储存圆的信息(坐标、半径),然后在鼠标移动的时候将鼠标的位置信息储存在数组中。
所以在鼠标移动的过程我们首先要获得鼠标的坐标,然后将鼠标的坐标以及其他信息 push 到数组中去:
window.onmousemove = function (event) {
mouseX = event.clientX;
mouseY = event.clientY;
round_arr.push({
mouseX: mouseX,
mouseY: mouseY,
r: para.r, // 设置半径每次增大的数值
o: 1, // 判断圆消失的条件,数值越大,消失得越快
})
};
设置 color
我们已经将圆的相关信息储存在 round_arr
数组中了,现在要在 animate()
函数中将圆显示出来。animate()
函数我们稍后再介绍。
创建圆需要的坐标信息以及半径,我们在鼠标移动的事件中都已经将其 push 到 round_arr
数组中了,还有一个条件是需要设置的,那就是颜色。
怎么对颜色进行处理呢?在 para
参数中,我们可以看出,其中有设置 color
值。如果 color
值不为 false
,那么设置的圆的颜色就是设置的 color
值;如果设置的 color
值为 false
,那么圆的颜色就是随机的。
if (para.color) {
color2 = para.color;
} else {
color = Math.random() * 360;
}
那么怎么设置颜色的渐变呢?我们将 color
的颜色值依次增加一个增量。
if (!para.color) {
color += .1;
color2 = 'hsl(' + color + ',100%,80%)';
}
要让颜色一直改变,我们要将上面颜色改变的代码放在一个一直执行的函数。我们将上面改变颜色的代码放在下面我们要介绍的 animate()
函数中。
animate()
函数
我们需要一个一直在执行的函数,这个函数主要负责动画的 animate()
函数。从函数名就可以看出这个函数的作用,的确,我们需要在该函数中写动画。
第 6 节写动画的主要思想是 —— 清除屏幕再重新绘制,这里的 animate()
函数也是这样的。
我们先来清除屏幕。
ctx.clearRect(0, 0, WIDTH, HEIGHT);
接着使用 round_arr
数组中的数据将一个一个的圆绘制出来。
for (var i = 0; i < round_arr.length; i++) {
ctx.fillStyle = color2;
ctx.beginPath();
ctx.arc( round_arr[i].mouseX ,round_arr[i].mouseY,round_arr[i].r,0, Math.PI * 2);
ctx.closePath();
ctx.fill();
round_arr[i].r += para.r;
round_arr[i].o -= para.o;
if( round_arr[i].o <= 0){
round_arr.splice(i,1);
i--;
}
}
然后我们还需要一直执行这个函数:
window.requestAnimationFrame(animate);
我们来看下完整的 animate()
函数:
function animate() {
if (!para.color) {
color += .1;
color2 = 'hsl(' + color + ',100%,80%)';
}
ctx.clearRect(0, 0, WIDTH, HEIGHT);
for (var i = 0; i < round_arr.length; i++) {
ctx.fillStyle = color2;
ctx.beginPath();
ctx.arc( round_arr[i].mouseX ,round_arr[i].mouseY,round_arr[i].r,0, Math.PI * 2);
ctx.closePath();
ctx.fill();
round_arr[i].r += para.r;
round_arr[i].o -= para.o;
if( round_arr[i].o <= 0){
round_arr.splice(i,1);
i--;
}
}
window.requestAnimationFrame(animate);
};
小结
以上,我们就写完了一个完整的鼠标跟随效果的例子,让我们来看一下主要的有哪些步骤:
- 创建 Canvas 元素,设置参数
- 鼠标移动事件,将坐标信息 push 到数组
- 设置颜色
- 设置动画
animate()
函数
我们来看一下这个例子的完整代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
* {
padding: 0;
margin: 0;
}
#canvas {
background: #000;
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<script>
var canvas = document.getElementById('canvas'),
ctx = canvas.getContext('2d'),
WIDTH = canvas.width = document.documentElement.clientWidth,
HEIGHT = canvas.height = document.documentElement.clientHeight,
para = {
num: 100,
color: false, // 颜色 如果是false 则是随机渐变颜色
r: 0.9,
o: 0.09, // 判断圆消失的条件,数值越大,消失的越快
a: 1,
},
color,
color2,
round_arr = [];
window.onmousemove = function (event) {
mouseX = event.clientX;
mouseY = event.clientY;
round_arr.push({
mouseX: mouseX,
mouseY: mouseY,
r: para.r,
o: 1
})
};
// 判断参数中是否设置了 color,如果设置了 color,就使用该值、
// 如果参数中的 color 为 false,那么就使用随机的颜色
if (para.color) {
color2 = para.color;
} else {
color = Math.random() * 360;
}
function animate() {
if (!para.color) {
color += .1;
color2 = 'hsl(' + color + ',100%,80%)';
}
ctx.clearRect(0, 0, WIDTH, HEIGHT);
for (var i = 0; i < round_arr.length; i++) {
ctx.fillStyle = color2;
ctx.beginPath();
ctx.arc( round_arr[i].mouseX ,round_arr[i].mouseY,round_arr[i].r,0, Math.PI * 2);
ctx.closePath();
ctx.fill();
round_arr[i].r += para.r;
round_arr[i].o -= para.o;
if( round_arr[i].o <= 0){
round_arr.splice(i,1);
i--;
}
}
window.requestAnimationFrame(animate);
};
animate();
</script>
</body>
</html>