于是:
var canvas = document.querySelector('canvas'); var context = canvas.getContext('2d'); // 存储实例 var store = {}; // 实例方法 var Ball = function () { this.x = 0; this.draw = function () { // 根据此时x位置重新绘制圆圈圈 // ... }; }; // 假设就一个圆圈圈 store[0] = new Ball(); // 绘制画布上所有的圆圈圈的方法 var draw = function () { // 位置变化 store[0].x++; // 根据新位置绘制圆圈圈 store[0].draw(); }; // 画布渲染 var render = function () { // 清除画布 context.clearRect(0, 0, canvas.width, canvas.height); // 绘制画布上所有的圆圈圈 draw(); // 继续渲染 requestAnimationFrame(render); }; render(); 6. 随机多个实例对象坐标尺寸透明度等属性假设现在有10个圆圈圈,如果每个圈圈的起始位置和运动速度都是一样的,是很无趣的,此时,我们就可以借助 Math.random() 构建随机属性,半径啊,位移速度啊,坐标都可以,如下代码:
var canvas = document.querySelector('canvas'); var context = canvas.getContext('2d'); // 存储实例 var store = {}; // 实例方法 var Ball = function () { // 随机x坐标也就是横坐标,以及变化量moveX,以及半径r this.x = Math.random() * canvas.width; this.moveX = Math.random(); this.r = 5 + 5 * Math.random(); this.draw = function () { // 根据此时x位置重新绘制圆圈圈 // ... }; }; // 假设10个圆圈圈 for (var indexBall = 0; indexBall < 10; indexBall += 1) { store[indexBall] = new Ball(); } // 绘制画布上10个圆圈圈 var draw = function () { for (var index in store) { // 位置变化 store[index].x += store[index].moveX; if (store[index].x > canvas.width) { // 移动到画布外部时候从左侧开始继续位移 store[index].x = -2 * store[index].r; } // 根据新位置绘制圆圈圈 store[index].draw(); } }; // 画布渲染 var render = function () { // 清除画布 context.clearRect(0, 0, canvas.width, canvas.height); // 绘制画布上所有的圆圈圈 draw(); // 继续渲染 requestAnimationFrame(render); }; render(); 7. 补全圆圈圈的canvas绘制canvas 画圆直接API手册上就有,例如这里:
var Ball = function () { // 随机x坐标也就是横坐标,以及变化量moveX,以及半径r this.x = Math.random() * canvas.width; this.moveX = Math.random(); this.r = 5 + 5 * Math.random(); this.draw = function () { // 根据此时x位置重新绘制圆圈圈 context.beginPath(); context.fillStyle="#369"; context.arc(this.x, canvas.height / 2, this.r, 0, Math.PI*2); context.closePath(); context.fill(); }; };于是,就可以看到下面这个实时 canvas 效果,如果你发现没有效果,请移步原文(?p=6017)或 点击这里 感受效果:
如果我们背景变成黑色,圆圈圈变成白色,尺寸再小一点,透明度再忽闪忽闪的变化,则就可以实现一个星空效果。这就是一开始 星星连线联动动效demo 中星空背景效果的实现套路。
四、canvas 2D炫酷动效需要的技术积累线和星星一起弹动的动效要比星空实现要复杂点,都大体上套路上是一样的,但是,所需要的技术积累要多一些,包括:
1. 了解canvas动效原理这个上一小节已经探讨过了,就是不断清除画布再绘制,清除再绘制。
2. 一定的JS基本功例如,了解实例对象的属性如何获取,以及上下文 this 指代什么;如何有效地遍历以及数据存储等等。
例如,本demo 6个星星所有坐标是个三维数组,并且,每个星座数组的个数都不一样,其中就涉及到查漏补缺的数据处理,但是,如果JS基本功扎实,这些都是手到擒来,分分钟就可以搞定的,反之,这效率怕是要大打折扣了。
3. 知道如何运用一些动画算法关于动画算法,之前有专门文章介绍过,参见“ 如何使用Tween.js各类原生动画运动缓动算法 ”一文,本文的弹动效果使用的就是其中的ElasticEaseOut算法。
准备好前后两个场景每个星星的坐标位置,然后,位置变化的值走ElasticEaseOut算法,弹动效果就出来了。
4. 了解canvas所有API,尤其基本的绘图API如何使用canvas绘制线条,绘制圆,绘制不规则图形;如何描边,如何填充,如何控制透明度等等,都是必须要牢固掌握的。
因为,无论是是圆圈圈,还是角星星,都离不开这些基础的API绘制。
还需要了解图像绘制API,例如,本demo的星星,实际上还可以基于图片资源绘制,难度会稍微降低些,但可能要牺牲点效果。
又例如,demo中的虚线连接,语法很简单,只需要起点坐标和终点坐标就可以,渲染的时候,只要实时根据两个星星中心点(假设坐标分别是(x0,y0)和(x1,y1))连线就可以了,永远跟着星星,星星弹动,线自然也跟着有弹动效果。
// 开始路径绘制 context.beginPath(); // 虚线设定 context.setLineDash([2,2]); // 设置路径起点 context.moveTo(x0, y0); // 绘制一条到终点点的直线 context.lineTo(x1, y1); // 设置线宽 context.lineWidth = 1.0; // 设置线的颜色 context.strokeStyle = '#fff'; // 进行线的着色,这时整条线才变得可见 context.stroke(); 5. 掌握常见的曲线函数也就是要有一定的数学功力,无论是CSS3的 transform 变幻还是我们平时所见的各种动画效果,其本质上都是数学函数运动和矩阵变换,因此,要想再图形可视化以及视觉动效领域有所建树,数学不能差。
通常而言,常见的图形绘制,或者运动轨迹之类,都是需要借助数学函数的,比方所我早些年写过的抛物线相关的文章“ JavaScript与元素间的抛物线轨迹运动 ”,又或者本文的六角星效果。这些图形绘制所需要的数学知识仅仅高中程度就可以,算是比较简单的,拿这里的六角星举例:
六角星实际上是两个等边三角形组成,且六个顶点正好在一个圆上,如下图所示:
所以我们只要根据圆心和圆弧公式就可以求得六个点的坐标位置了,计算公式为:
x=a+r*cosθ y=b+r*sinθ