zoukankan      html  css  js  c++  java
  • canvas 实现火焰的简单方式

    实现效果如下

    实验方法:

    1. 火焰的构造

     // 构造火焰
            function torch(){ 
                // 构造出来的菱形的对角线一半的长度
                this.width=random(18,30); 
                this.maxWidth=this.width;
                // 火焰位置
                if(mouse.x&&mouse.y){
                    this.location={
                        x:mouse.x,
                        y:mouse.y
                    }
                }else{
                     // 表示鼠标不在当前范围中则采用固定的位置
                    this.location={
                        x:Math.floor(ele.width/2),
                        y:Math.floor(ele.height/2)
                    }
                  
                }
                // 中心点
                this.rectCenterPoint = {x:this.location.x, y:this.location.y-this.width }; // 矩形中心点
                // this.windy=random(-.1,.1);
                // 运动速度
                this.speed={
                    x: random(-.2,.5),
                    y: random(1.5,2.5)
                }
                // 火焰存活时间
                this.life=this.width*random(1,2);
                this.remaining_life=this.maxWidth/this.life;
                this.radius = Math.sqrt(Math.pow(this.width,2)+Math.pow(this.width,2));
                this.g=random(20,70);
                
                // 绘制菱形
                this.rect=function(ctx){
                    ctx.beginPath(); 
                    ctx.shadowBlur=2;
                    ctx.shadowColor="rgb(215,148,21)";
    
                    // 画菱形
                    // ctx.translate(this.rectCenterPoint.x, this.rectCenterPoint.y);
                    // ctx.rotate(45*Math.PI/180);
                    // ctx.translate(-this.rectCenterPoint.x, -this.rectCenterPoint.y);
    
                    // // ctx.fillStyle = 'rgb(255,255,0,.5)';
                    // ctx.fillStyle=`rgba(${random(245,255)},${this.g},37,${random(.5,1)})`;
                    // ctx.fillRect(this.location.x, this.location.y,this.width,this.width);
                    // ctx.fill();
                    // ctx.rotate(-45*Math.PI/180);
                    // ctx.translate(-this.rectCenterPoint.x, -this.rectCenterPoint.y);
    
                    ctx.moveTo(this.location.x,this.location.y);
                    ctx.lineTo(this.location.x-this.width,this.location.y-this.width);
                    ctx.lineTo(this.location.x,this.location.y-2*this.width);
                    ctx.lineTo(this.location.x+this.width,this.location.y-this.width);
                    ctx.lineTo(this.location.x,this.location.y); 
                    // 渐变颜色                 
                    let grd = ctx.createRadialGradient(this.rectCenterPoint.x,this.rectCenterPoint.y,random(1,8),this.rectCenterPoint.x,this.rectCenterPoint.y, this.radius);
                    grd.addColorStop(1,`rgba(245,${this.g},37,.8)`);
                    grd.addColorStop(0,`rgb(244,${random(37,71)},37)`);
                    ctx.fillStyle=grd; 
                    ctx.fill();
                    ctx.closePath()
                }
            
            }
    
     function random(min,max){
              return min+Math.random()*(max-min);
            }

    菱形的构造有两种方法推荐,一种是直接用moveTo+lineTo 直接连接画出(推荐这种),

      一种是通过矩形的旋转与平移,但是矩形的旋转rotate,旋转之后是改变了canvas画布的方向,而不是单纯的矩形的旋转;也因为是改变了画布的方法,所以画布的坐标是根据旋转之后的的位置重新定位的

     

    上面是平移或旋转之后画布的位置(以坐标轴看出)

    2.初始化数据

    //初始化,存放火焰的数组
            let arrTorch=[]; 
             // 鼠标的当前位置 
            let mouse={};
            for(let i=0;i<8;i++){
                arrTorch.push(new torch());     
            }

    3.鼠标位置获取

    // 鼠标事件
            window.onmousemove= function (event){
                let e = event|| window.event;
                let scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
                let scrollY = document.documentElement.scrollTop || document.body.scrollTop;
                mouse.x = e.pageX || e.clientX + scrollX;
                mouse.y= e.pageY || e.clientY + scrollY;  
            }
            window.onmouseout = function() {
                mouse.x= null;
                mouse.y= null;
            }

    4.绘制画布

    //实例化
            function draw(){        
               ctx.clearRect(0,0,ele.width,ele.height);
                // ctx.globalCompositeOperation = 'destination-over'
                for (var i = 0; i < arrTorch.length; i++) {
                    var p = arrTorch[i];   
                    p.rect(ctx);              
                    p.width-=p.remaining_life;
                    // 每次移动 有关颜色的参数的变化
                    p.g+=random(50,65);
                    // 位置变化
                    p.location.y-=p.speed.y;
                    p.location.x= p.location.x-p.speed.x;
                    // 若菱形长度为0 或者生存时间为0 
                    if(p.width<0||p.remaining_life<0){
                        // 当前的菱形重新实例化一次
                        arrTorch[i]=new torch();
                    }
                }
               requestAnimationFrame(draw);
            }
           draw(); 

    5. 其他

    css 样式

    <style>
            html,body{
                margin:0;
                100%;
                height:100%; 
                /* font-size: 0;  */
            }
            canvas{
                background: #000;
                vertical-align: bottom;
                
                100%;
                height:100%;
            }
        </style>

    html

    <canvas id="torch" width="600px" height="600px"></canvas>

      注:canvas 是一个行内元素,css 设置大小是显示图片在屏幕内像素的大小     在html 中设置的大小是表示了图片本身的大小

    完整代码

      1 <!DOCTYPE html>
      2 <html lang="en">
      3 <head>
      4     <meta charset="UTF-8">
      5     <meta name="viewport" content="width=device-width, initial-scale=1.0">
      6     <meta http-equiv="X-UA-Compatible" content="ie=edge">
      7     <title>火把</title>
      8     <style>
      9         html,body{
     10             margin:0;
     11             100%;
     12             height:100%; 
     13             /* font-size: 0;  */
     14         }
     15         canvas{
     16             background: #000;
     17             vertical-align: bottom;
     18             
     19             /* 100%;
     20             height:100%; */
     21         }
     22     </style>
     23 </head>
     24 <body>
     25     <canvas id="torch" width="600px" height="600px"></canvas>
     26     <script>
     27         let ele=document.getElementById('torch');
     28         ele.width=document.documentElement.clientWidth;    
     29         ele.height=document.documentElement.clientHeight;
     30         let ctx=ele.getContext('2d');
     31         
     32         //初始化,存放火焰的数组
     33         let arrTorch=[]; 
     34          // 鼠标的当前位置 
     35         let mouse={};
     36         for(let i=0;i<8;i++){
     37             arrTorch.push(new torch());     
     38         }
     39         console.log(arrTorch);
     40        
     41         function random(min,max){
     42           return min+Math.random()*(max-min);
     43         }
     44 
     45         // 鼠标事件
     46         window.onmousemove= function (event){
     47             let e = event|| window.event;
     48             let scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
     49             let scrollY = document.documentElement.scrollTop || document.body.scrollTop;
     50             mouse.x = e.pageX || e.clientX + scrollX;
     51             mouse.y= e.pageY || e.clientY + scrollY;  
     52         }
     53         window.onmouseout = function() {
     54             mouse.x= null;
     55             mouse.y= null;
     56         }
     57         // 用requestAnimationFrame代替setInterval
     58         // 适配不同的浏览器缺少某个方法的一段算法 这段代码的作用就是解决一些浏览器没有requestAnimationFrame这个方法
     59         //像这样的一段算法,或者说代码,是有名词来称呼它的叫做 垫片(polyfill)
     60 
     61         window.requestAnimationFrame = window.requestAnimationFrame 
     62                                         || window.mozRequestAnimationFrame 
     63                                         || window.webkitRequestAnimationFrame 
     64                                         || window.msRequestAnimationFrame
     65                                         || function(callback){
     66                                             setInterval(callback,16.7)
     67                                             };
     68 
     69         // 构造火焰
     70         function torch(){ 
     71             // 构造出来的菱形的对角线一半的长度
     72             this.width=random(18,30); 
     73             this.maxWidth=this.width;
     74             // 火焰位置
     75             if(mouse.x&&mouse.y){
     76                 this.location={
     77                     x:mouse.x,
     78                     y:mouse.y
     79                 }
     80             }else{
     81                  // 表示鼠标不在当前范围中则采用固定的位置
     82                 this.location={
     83                     x:Math.floor(ele.width/2),
     84                     y:Math.floor(ele.height/2)
     85                 }
     86               
     87             }
     88             // 中心点
     89             this.rectCenterPoint = {x:this.location.x, y:this.location.y-this.width }; // 矩形中心点
     90             // this.windy=random(-.1,.1);
     91             // 运动速度
     92             this.speed={
     93                 x: random(-.2,.5),
     94                 y: random(1.5,2.5)
     95             }
     96             // 火焰存活时间
     97             this.life=this.width*random(1,2);
     98             this.remaining_life=this.maxWidth/this.life;
     99             this.radius = Math.sqrt(Math.pow(this.width,2)+Math.pow(this.width,2));
    100             this.g=random(20,70);
    101             
    102             // 绘制菱形
    103             this.rect=function(ctx){
    104                 ctx.beginPath(); 
    105                 ctx.shadowBlur=2;
    106                 ctx.shadowColor="rgb(215,148,21)";
    107 
    108                 // 画菱形
    109                 // ctx.translate(this.rectCenterPoint.x, this.rectCenterPoint.y);
    110                 // ctx.rotate(45*Math.PI/180);
    111                 // ctx.translate(-this.rectCenterPoint.x, -this.rectCenterPoint.y);
    112 
    113                 // // ctx.fillStyle = 'rgb(255,255,0,.5)';
    114                 // ctx.fillStyle=`rgba(${random(245,255)},${this.g},37,${random(.5,1)})`;
    115                 // ctx.fillRect(this.location.x, this.location.y,this.width,this.width);
    116                 // ctx.fill();
    117                 // ctx.rotate(-45*Math.PI/180);
    118                 // ctx.translate(-this.rectCenterPoint.x, -this.rectCenterPoint.y);
    119 
    120                 ctx.moveTo(this.location.x,this.location.y);
    121                 ctx.lineTo(this.location.x-this.width,this.location.y-this.width);
    122                 ctx.lineTo(this.location.x,this.location.y-2*this.width);
    123                 ctx.lineTo(this.location.x+this.width,this.location.y-this.width);
    124                 ctx.lineTo(this.location.x,this.location.y); 
    125                 // 渐变颜色                 
    126                 let grd = ctx.createRadialGradient(this.rectCenterPoint.x,this.rectCenterPoint.y,random(1,8),this.rectCenterPoint.x,this.rectCenterPoint.y, this.radius);
    127                 grd.addColorStop(1,`rgba(245,${this.g},37,.8)`);
    128                 grd.addColorStop(0,`rgb(244,${random(37,71)},37)`);
    129                 ctx.fillStyle=grd; 
    130                 ctx.fill();
    131                 ctx.closePath()
    132             }
    133         
    134         }
    135         
    136 
    137         //实例化
    138         function draw(){        
    139            ctx.clearRect(0,0,ele.width,ele.height);
    140             // ctx.globalCompositeOperation = 'destination-over'
    141             for (var i = 0; i < arrTorch.length; i++) {
    142                 var p = arrTorch[i];   
    143                 p.rect(ctx);              
    144                 p.width-=p.remaining_life;
    145                 // 每次移动 有关颜色的参数的变化
    146                 p.g+=random(50,65);
    147                 // 位置变化
    148                 p.location.y-=p.speed.y;
    149                 p.location.x= p.location.x-p.speed.x;
    150                 // 若菱形长度为0 或者生存时间为0 
    151                 if(p.width<0||p.remaining_life<0){
    152                     // 当前的菱形重新实例化一次
    153                     arrTorch[i]=new torch();
    154                 }
    155             }
    156            requestAnimationFrame(draw);
    157         }
    158        draw();  
    159       
    160     </script>
    161 </body>
    162 </html>
    View Code
  • 相关阅读:
    stl变易算法(三)
    JAVA模拟登录实例
    python 使用scapy编写DNS Fuzzer
    SQL 用户定义表类型,在存储过程里使用数据类型作參数
    POJ2584_T-Shirt Gumbo(二分图多重最大匹配/最大流)
    HDU 2830 Matrix Swapping II
    【SSH之旅】一步步学习Hibernate框架(一):关于持久化
    java.text.ParseException: Unparseable date: &quot;2015-06-09 hh:56:19&quot;
    socket pro
    OpenWrt opkg 在线源默认配置
  • 原文地址:https://www.cnblogs.com/Jeanchjy/p/12822535.html
Copyright © 2011-2022 走看看