Canvas 彩色像素滚动条动画 案例分析
最近在学习canvas学习过程中记录下我个人对canvas用法的理解与分析,之前没有用canvas做案例的时候 就只知道canvas有一些属性,但是用到的时候才知道自己知道的canvas是那么少。下面我就分析一下今天我研究一天的canvas案例吧。多有不足之处 请看到的同学批评指正。
大概就是类似图片样式滚动显示效果。
1、HTML代码部分 写进<canvas></canvas>标签
2、用javascript代码控制canvas画布,下面是代码部分 代码的解析我就直接在代码展示区域注释了
3、主要是通过案例,理清楚canvas的绘制流程,和需要注意的事项
particle_no = 25; 首先 缓动函数 requestAnimationFrame 的作用:
requestAnimationFrame是什么?
以前我们做动画需要一个定时器,每间隔多少毫秒就做出一些改变。现在有个好消息:浏览器厂商已经决定提供一个专门做动画的方法,即requestAnimationFrame(),而且基于浏览器的层面也能更好的进行优化。但是呢,这只是一个做动画的基础API,即不基于DOM元素的style变化,也不基于canvas,或者WebGL。所以,具体的动画细节需要我们自己写。
我们为什么要用它?
对于同时进行的n个动画,浏览器能够进行优化,把原本需要N次reflow和repaint优化成1次,这样就实现了高质量的动画。举个例子,现在有基于JS的动画,还有基于CSS的transitions,或者SVG SMIL. Plus,如果浏览器的某个tab正在运行这样一个动画,然后你切到另一个tab,或者干脆最小化,总之就是你看不见它了,这时浏览器就会停止动画。这将意味着更少的CPU,GPU和更少的内存消耗,这样电池的使用寿命就大大延长了。
window.requestAnimFrame = (function(){ return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function( callback ){ window.setTimeout(callback, 1000 / 60); }; })(); //获取canvas标签,并将其设置为2d动画模式 var canvas = document.getElementsByTagName("canvas")[0]; var ctx = canvas.getContext("2d"); 定义计数器和碎片数组,初始化canvas标签的宽度和高度 var counter = 0; var particles = []; var w = 400, h = 200; canvas.width = w; canvas.height = h;
重置函数主要是初始化canvas画布的状态。 function reset(){ ctx.fillStyle = "#272822";//画布的填充颜色 ctx.fillRect(0,0,w,h);//画布的绘制范围 坐标从(0,0)开始 宽为w 高为h ctx.fillStyle = "#171814";//画布中进度条的填充颜色 ctx.fillRect(25,80,350,25);//进度条的绘制起始点级宽度和高度 }
进度条方法 function progressbar(){ this.widths = 0; this.hue = 0;
进度条的绘制方法 this.draw = function(){
//HSL声明使用色调Hue(H)、饱和度Saturation(s)和亮度Lightness(L)来设置颜色。
//Hue衍生于色盘:0和360是红色,接近120的是绿色,240是蓝色。
//Saturation值是一个百分比:0%是灰度,100%饱和度最高
//Lightness值也是一个百分比:0%是最暗,50%均值,100%最亮。
//由下文可知 hue+=0.8的值在150ms之后大于120变为绿色
ctx.fillStyle = 'hsla('+this.hue+', 100%, 40%, 1)';canvas画布中填充颜色使用 hsla clolor ctx.fillRect(25,80,this.widths,25); canvas画布的绘制范围
//createLinearGradient创建线性渐变对象
//x0 渐变开始点的 x 坐标
//y0 渐变开始点的 y 坐标
//x1 渐变结束点的 x 坐标
//y1 渐变结束点的 y 坐标
var grad = ctx.createLinearGradient(0,0,0,130); 黑色矩形渐变绘制 grad.addColorStop(0,"transparent"); grad.addColorStop(1,"rgba(0,0,0,0.5)"); ctx.fillStyle = grad; 填充canvas画布中的矩形进度条的颜色 ctx.fillRect(25,80,this.widths,25); } }
//碎片的制作方法 function particle(){
//提起碎片的位置 this.x = 23 + bar.widths; this.y = 82;
//碎片在x轴方向的移动速度 this.vx = 0.8 + Math.random()*1; this.v = Math.random()*5; //不知道这个变量是什么作用,去掉之后也不影响程序 this.g = 1 + Math.random()*3; //应该是碎片重力影响力 this.down = false; //碎片的绘制方法 this.draw = function(){ ctx.fillStyle = 'hsla('+(bar.hue+0.3)+', 100%, 40%, 1)';//根据hue变化的填充色 var size = Math.random()*2;//碎片的随机大小 最大不会超过2像素 ctx.fillRect(this.x, this.y, size, size);//碎片的绘制 } } bar = new progressbar();
//canvas的绘制方法 function draw(){ reset(); counter++;//counter为计时器。循环的时间差 bar.hue += 0.8; bar.widths += 2;
//当当前进度填充的宽度超过进度条的宽度之后执行,当进度条的长度大于315时 if(bar.widths > 350){
//当间隔时间大于215ms时,将进度条重置为初始状态。如果不判断这个状态的话就只能进行一次不会循环的显示进度条 if(counter > 215){ reset(); bar.hue = 0; bar.widths = 0; counter = 0; particles = []; } else{
//时间不到的215毫秒的话,就显示最终的绿色状态 bar.hue = 126;//最终状态是绿色 bar.widths = 351; bar.draw(); } } else{ bar.draw(); for(var i=0;i<particle_no;i+=10){ particles.push(new particle());//应该是碎片的三种颜色状态 } } update();//更新当前状态 } //进度填充更新 function update(){ for(var i=0;i<particles.length;i++){ var p = particles[i]; p.x -= p.vx;//当前行进的宽度 - 滚动的速度
if(p.down == true){ p.g += 0.1;//重力影响 力 p.y += p.g;//下降时 粒子的竖直方向y轴坐标 } else{ if(p.g<0){//如果当前重力影响力小于0,则粒子向上运动 p.down = true; p.g += 0.1; p.y += p.g; } else{ p.y -= p.g; p.g -= 0.1; } } p.draw(); } } //递归调用绘制函数 draw() function animloop() { draw(); requestAnimFrame(animloop); } animloop();
浙公网安备 33010602011771号