井井客

搜索

Canvas 闪电动画

还是满逼真的一个动画~

Canvas 闪电动画

原文摘自:http://canvas.migong.org/category/canvas-animation/page/9

代码如下,建议可以看一下原文,里面有解释更多。

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Canvas 闪电动画</title>
    <style>
        html,body{
            padding: 0;
            margin: 0;
            overflow: hidden;
        }
        body{
            background: linear-gradient(#000, #151515);
        }
    </style>
</head>
<body>
    <canvas id="canvas"></canvas>
    <script>
        var canvasLightning = function(c, cw, ch){
            //初始化函数
            this.init = function(){
                this.loop();
            };    
        
            //变量
            var _this = this;
            this.c = c;
            this.ctx = c.getContext('2d');
            this.cw = cw;
            this.ch = ch;
            this.mx = 0;
            this.my = 0;
            
            this.lightning = [];
            this.lightTimeCurrent = 0;
            this.lightTimeTotal = 50;   //闪电更新时间
          
            //公用函数
            this.rand = function(rMi, rMa){return ~~((Math.random()*(rMa-rMi+1))+rMi);};    //随机函数
            this.hitTest = function(x1, y1, w1, h1, x2, y2, w2, h2){return !(x1 + w1 < x2 || x2 + w2 < x1 || y1 + h1 < y2 || y2 + h2 < y1);};
          
            //创建闪电
            this.createL = function(x, y, canSpawn){
                //添加到 lightning 数组
                this.lightning.push({
                    x: x,
                    y: y,
                    xRange: this.rand(5, 30),
                    yRange: this.rand(5, 25),
                    path: [{
                      x: x,
                      y: y    
                    }],
                    pathLimit: this.rand(10, 35),
                    canSpawn: canSpawn,
                    hasFired: false
                });
            };
          
            //更新闪电
            this.updateL = function(){
                var i = this.lightning.length;
                while(i--){
                    var light = this.lightning[i];
                    
                    //添加到 path 数组
                    light.path.push({
                        x: light.path[light.path.length-1].x + (this.rand(0, light.xRange)-(light.xRange/2)),
                        y: light.path[light.path.length-1].y + (this.rand(0, light.yRange))
                    });
                    //如果 path 数组长度 > pathLimit 则删除 lightning 数组中第 i 位置的第1个项目
                    if(light.path.length > light.pathLimit){
                        this.lightning.splice(i, 1)
                        //如果不删除,将出现连续绘制闪电
                    }
                    light.hasFired = true;
                };
            };
          
            //渲染闪电
            this.renderL = function(){
                var i = this.lightning.length;
                while(i--){
                    var light = this.lightning[i];
                    this.ctx.strokeStyle = 'hsla(0, 100%, 100%, '+this.rand(10, 100)/100+')';
                    this.ctx.lineWidth = 1;     //闪电线宽
                    
                    //判断后重新定义闪电线宽
                    if(this.rand(0, 30) == 0){
                        this.ctx.lineWidth = 2;
                    }
                    if(this.rand(0, 60) == 0){
                        this.ctx.lineWidth = 3;
                    }
                    if(this.rand(0, 90) == 0){
                        this.ctx.lineWidth = 4;
                    }
                    if(this.rand(0, 120) == 0){
                        this.ctx.lineWidth = 5;
                    }
                    if(this.rand(0, 150) == 0){
                        this.ctx.lineWidth = 6;
                    } 
                    
                    this.ctx.beginPath();   //开始路径
                    var pathCount = light.path.length;
                    this.ctx.moveTo(light.x, light.y);  //开始位置
                    for(var pc = 0; pc < pathCount; pc++){
                        this.ctx.lineTo(light.path[pc].x, light.path[pc].y);    //绘制线条
                      
                        if(light.canSpawn){
                            if(this.rand(0, 100) == 0){
                                light.canSpawn = false;
                                //闪电出现的位置
                                this.createL(light.path[pc].x, light.path[pc].y, false);
                            } 
                        }
                    }
                    
                    //随机改变闪电填充色透明度
                    if(!light.hasFired){
                        this.ctx.fillStyle = 'rgba(255, 255, 255, '+this.rand(4, 12)/100+')';
                        this.ctx.fillRect(0, 0, this.cw, this.ch);
                    }
                    
                    if(this.rand(0, 30) == 0){
                        this.ctx.fillStyle = 'rgba(255, 255, 255, '+this.rand(1, 3)/100+')';
                        this.ctx.fillRect(0, 0, this.cw, this.ch);
                    } 
                    
                    this.ctx.stroke();
                };
            };
          
            //闪电定时器
            this.lightningTimer = function(){
                this.lightTimeCurrent++;
                //每次更新后改变闪电位置
                if(this.lightTimeCurrent >= this.lightTimeTotal){
                    var newX = this.rand(100, cw - 100);
                    var newY = this.rand(0, ch / 2); 
                    var createCount = this.rand(1, 3);
                    while(createCount--){
                        //更新闪电出现的位置
                        this.createL(newX, newY, true);
                    }
                    this.lightTimeCurrent = 0;
                    //更新闪电出现的随机时间
                    this.lightTimeTotal = this.rand(30, 100);
                }
            }
            
            //清除 Canvas
            this.clearCanvas = function(){
                this.ctx.globalCompositeOperation = 'destination-out';          //重叠图形位置透明
                this.ctx.fillStyle = 'rgba(0,0,0,'+this.rand(1, 30)/100+')';    //填充颜色,随机透明度(产生背景闪烁的效果)
                this.ctx.fillRect(0,0,this.cw,this.ch);                         //填充矩形(清空整个 Canvas)
                this.ctx.globalCompositeOperation = 'source-over';              //默认,新图形绘制于已有图形的顶部
            };
          
            //监听可视化窗口
            window.addEventListener('resize', function(){
                _this.cw = _this.c.width = window.innerWidth;
                _this.ch = _this.c.height = window.innerHeight;
            },false);
            
            //动画循环
            this.loop = function(){
                var loopIt = function(){
                    requestAnimationFrame(loopIt, _this.c);
                    _this.clearCanvas();
                    _this.updateL();
                    _this.lightningTimer();
                    _this.renderL();
                };
                loopIt();
            };
        };

        //检测是否支持 Canvas
        var isCanvasSupported = function(){
            var elem = document.createElement('canvas');
            return !!(elem.getContext && elem.getContext('2d'));
        };

        //设置 requestAnimationFrame
        var setupRAF = function(){
            var lastTime = 0;
            var vendors = ['ms', 'moz', 'webkit', 'o'];
            for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x){
                window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
                window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame'];
            };
            
            //如果不支持 requestAnimationFrame
            if(!window.requestAnimationFrame){
                window.requestAnimationFrame = function(callback, element){
                    var currTime = new Date().getTime();
                    var timeToCall = Math.max(0, 16 - (currTime - lastTime));
                    var id = window.setTimeout(function() { callback(currTime + timeToCall); }, timeToCall);
                    lastTime = currTime + timeToCall;
                    return id;
                };
            };
            
            if (!window.cancelAnimationFrame){
                window.cancelAnimationFrame = function(id){
                    clearTimeout(id);
                };
            };
        };

        //加载完成执行初始设定函数
        window.onload = function(){
            if(isCanvasSupported){  //检测是否支持 Canvas
                var c = document.getElementById('canvas');
                var cw = c.width = window.innerWidth;
                var ch = c.height = window.innerHeight;
                var cl = new canvasLightning(c, cw, ch);
                setupRAF();
                cl.init();
            }
        }
    </script>
</body>
</html>

文章TAG:canvas

作者:井井客整理来源:互联网
本文标题:Canvas 闪电动画
本文链接:http://www.jingjingke.com/c/24291.html

上一篇:Canvas 飘浮的云动画
下一篇:Canvas 小游戏(儿时的记忆)

文章分类

相关阅读

随便看看