好久没有写过原生JS了,突然没事做,写了一个跟着鼠标走的加载小动画,最终效果如下图:
这个效果实现起来非常简单,大概思路是:先用 CSS3 的 border-radius 属性将三个 div 的样式设置为圆形,然后定义一个椭圆路径,最后用定时器或帧函数使得三个 div 绕着椭圆路径旋转,同时椭圆路径的中点始终跟随者鼠标移动。
有了思路就可以开始写代码了,先把 html 和 css 部分写好:
跟着鼠标走的加载小动画
写好静态页面代码后,开始写 JS 代码:
(一)用 js 的方式生成3个小球
(二)定义椭圆路径
//定义椭圆路径
var path_length = 50; //定义路径的半长轴的长度
var path_width = 30; //定义路径的半短轴的长度
var path_angel = 0; //初始化与正半轴所成的角度角度为0(顺时针为正)
var angel_increase = 1.3; //小球运动角度增量(用于做小球旋转动画动画)
var ball_gap = 0.8; //小球间距(用于做小球旋转动画)
这里可能会有疑问,怎么定义椭圆路径?怎么在代码方面描述一个椭圆? 一般情况下,我们要用代码画一个图形的路径,就要用到图形对应的参数方程,比如椭圆的参数方程为:
其中,a为椭圆的半长轴的长度,b为半短轴的长度,α为与正半长轴所成的角度。于是,用 a, b, α 这两个量,就能确定某个构成椭圆路径的点的坐标。如果 a, b 长度不变,不断改变角度 α , 就能确定一个构成椭圆路径的几乎所有点的坐标,有了这些坐标,3个小球就能准确地围着椭圆的路径运动而不会偏离出去。
如果仍然难以理解,可以用一张图作辅助理解,如下图,红点M的轨迹是椭圆,M(x,y) = (|OA|cosa,|OB|sina) = (acosα, bsinα)。
(三)定义鼠标移动事件
由于椭圆路径的中点是跟着鼠标跑,所以我们需要定义鼠标移动事件来更新一对鼠标坐标的变量,在此前,先把一对鼠标坐标变量定义好。
//定义实时鼠标坐标
var mouseX = 0;
var mouseY = 0;
由于不同的浏览器,监听鼠标移动事件的方式不一样,所以需要用兼容性写法监听鼠标移动事件。
//鼠标移动事件(兼容性写法)
if (document.addEventListener) { //FireFox,Chrome,Opera…
container.addEventListener('mousemove',onMouseMove,false); //事件会在鼠标指针移动时发生。
}
else if (document.attachEvent) { //IE
container.attachEvent('onmousemove', onMouseMove, false); //事件会在鼠标指针移动时发生。
}
else { //Other(IE,FireFox,Chrome,Opera等,绝大部分浏览器支持方法 onclick 监听)
container.onmousemove = onMouseMove;
}
编写鼠标移动事件的回调处理函数,实时更新鼠标坐标变量。
//鼠标移动事件
function onMouseMove(event){
//更新坐标
mouseX = event.clientX + document.body.scrollLeft - document.body.clientLeft;
mouseY = event.clientY + document.body.scrollTop - document.body.clientTop;
}
(四)编写小球旋转加载动画
在 js 中编写动画,一般使用帧事件或者定时器,在这里我使用了帧事件函数 requestAnimFrame 方式来编写动画(如果有对 requestAnimFrame 不了解的童鞋,先自行查询)。由于不同浏览器对帧事件的兼容性不相同,所以先要对帧事件函数进行兼容性处理。
//定义兼容性帧事件
window.requestAnimFrame = (function(){
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function( callback ){
window.setTimeout(callback, 1000 / 60);
};
})();
//兼容性取消帧事件
window.cancelAnimationFrame = (function () {
return window.cancelAnimationFrame ||
window.webkitCancelAnimationFrame ||
window.mozCancelAnimationFrame ||
window.oCancelAnimationFrame ||
function (timer) {
window.clearTimeout(timer);
};
})();
接下来在帧事件中编写小球绕着椭圆路径旋转的动画。
//监听帧事件,帧渲染和帧绘制的变量
var timer = null;
//根据椭圆路径,执行小球运动
function drawFrame(){
for(var i=0; i
其中,ball.style.left = path_length * Math.cos(angel); 对应了椭圆的参数方程的 x=acosα。
同理,ball.style.top = path_width * Math.sin(angel); 对应了椭圆的参数方程的 y=bsinα。
(五)最后,调用编写好的动画即可。
timer = requestAnimationFrame(drawFrame);
最后,把以上代码整合起来,完整代码如下:
跟着鼠标走的加载小动画