炎炎夏日,快用代码下场雨ヽ`☂ヽ`canvas

Posted 北极光之夜。

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了炎炎夏日,快用代码下场雨ヽ`☂ヽ`canvas相关的知识,希望对你有一定的参考价值。

一.先看效果(源码在最后):

哗啦啦啦


我的B站地址~效果演示更清晰

图片展示,因为图片限制5m大小,所以演示不太多:
在这里插入图片描述

二.实现过程(可一步一步实现):

因为雨是重点,所以中间 logo 部分就不详细写了,可直接看源码~

1.定义canvas标签与设置css基本样式:

 <canvas id="canvas"></canvas>
      *{
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
     
        #canvas{
           position: fixed;
           background-color: rgb(0, 0, 0);
           z-index: -10;
        }

position: fixed; 固定定位。

2. 开始js部分,获取画布与定义基本变量:

 // 获取画布
        var canvas = document.querySelector("#canvas");
        var rain = canvas.getContext('2d');
        // drop数组,存每个散开的小水滴信息
        var drop = [];
        // water数组,存每丝雨的信息
        var water = [];
        // 雨的数量,可自行更改
        var waterNum = 100;
        // 小水(雨)滴的重力
        var gravity = 1;
        // 鼠标在页面的初始位置
        var mouseX=-36,mouseY=-36;
        // 关于雨的角度值,值为-1到1,后面讲
        var direction = 0;
        // 这也是关于鼠标在页面位置的角度值,值为-1到1
        var mouseDelay = 0;
        // 这是画布自适应窗口大小的函数,复制即可
        window.onresize = resizeCanvas;
            function resizeCanvas() {
                canvas.width = window.innerWidth;
                canvas.height = window.innerHeight;
            }
            resizeCanvas();

2.初始化雨:

  // 一丝雨的初始化,封装,后面好几处要调用
        function creatWater(){         
                water.push({
                    //值为0或1,判断是否要散开水滴
                    add:1,
                    //随机初始水平位置
                    x:Math.random()*3*canvas.width-canvas.width,
                    // 随机初始垂直位置,在上面一点,这样雨能从上面下落
                    y: Math.random()*500-500,
                    // 随机雨的长度
                    len: Math.random()*20+50,
                    // 随机雨的速度
                    speed: Math.random()*10+35,
                    // 随机雨的随机颜色
                    color: `rgb(255,255,255,${Math.random()*0.5})`,
                    // 随机散开水滴数量
                    dropNum:Math.random()*6+6
                })                   
        }
        // 雨数组初始化,每丝雨都来
        function chushi(){
            for (let i = 0; i < waterNum; i++) {
               creatWater();
            } 
        }

3.初始化雨滴:

 // 散开水滴数组初始化,x为水平位置,y为垂直位置,dropNum为数量
        function creatDrop (x,y,dropNum){
            //给drop数组添加元素
            for (let j = 0; j < dropNum; j++) {
                drop.push({
                    // x轴位置
                    pagex:x,
                    // y轴位置
                    pagey:y,
                    // x轴移动距离
                    dx:Math.random()*12-6,
                    // y轴移动距离
                    dy:Math.random()*10-20,
                    // 半径
                    r:Math.random()+2,
                    //颜色
                    color: `rgb(255,255,255,${Math.random()*0.5+0.5})`,
                })
            }
        }

4.绘画每一丝雨:

 // 绘画,画雨
        function drawWater(){
            //遍历数组
            for (let i = 0; i < water.length; i++){
                let temp = water[i];
                // 颜色
                rain.strokeStyle = temp.color;
                // 开始路径
                rain.beginPath();
                // 开始点
                rain.moveTo(temp.x,temp.y);
                // 结束点,连线,如: 当前x位置+长度*角度值  
                rain.lineTo(temp.x+temp.len*direction,temp.y+temp.len);
                // 线宽度
                rain.lineWidth = 3;
                // 绘制
                rain.stroke();                            
            }
        }

5.绘画每一个雨滴:

 // 绘画雨滴
       function drawDrop(){
           //遍历
        for (let i = 0; i < drop.length; i++){  
            let temp = drop[i];
            // 线宽度
            rain.lineWidth = 2;
            //颜色
            rain.strokeStyle = temp.color;
            //开始路径
            rain.beginPath();
            // 画一个随机的弧度
            rain.arc(temp.pagex,temp.pagey,temp.r, Math.PI , Math.random() * 2 * Math.PI);
            // 绘制
            rain.stroke();
            //结束路径
            rain.closePath();                            
       }
    }

5. 雨信息更新,同时判断各种事件:

 //雨信息的更新
       function updateWater(){
         for (let i = 0; i < water.length; i++){
            // 判断雨的底部是否碰到鼠标,碰到就散开成水滴,x轴y轴与鼠标的位置绝对值在35之内则散开。
            if(Math.abs(mouseX-water[i].x)<35&&Math.abs(mouseY-water[i].y-water[i].len)<35){
                // 创建雨滴,传入x轴y轴大小与数量
                creatDrop(water[i].x,water[i].y+water[i].len,water[i].dropNum);
                // 既然水滴散开了,就清除掉这丝雨
                water.splice(i,1);
                // 重新来一丝随机的雨
                creatWater();
            }
             // 判断雨的底部是否超过画布底部,且add值为1
            if(((water[i].y+water[i].len)>=canvas.height) && water[i].add==1){
               // add值为0 
               water[i].add = 0;
              // 创建雨滴,传入x轴y轴大小与数量,y轴位置就为画布高即可
               creatDrop(water[i].x,canvas.height,water[i].dropNum);
           }
            // 判断整丝雨是否超过画布
            if(water[i].y>canvas.height){
                // 清除它
               water.splice(i,1);
               // 来个新的
              creatWater();
           }
           // 缓动动画原理,雨角度慢慢接近鼠标的角度
           direction += (mouseDelay - direction)*0.0002;           
           // 雨x轴位置改变
           water[i].x += water[i].speed*direction;
           //雨y轴位置改变
           water[i].y += water[i].speed;        
          }
       }

6. 雨滴信息更新:

 // 雨滴信息更新
       function updateDrop(){
           for(let i=0;i<drop.length;i++){
            // y轴移动距离加上重力。因为dy一开是负数,所以雨滴先升后降
            drop[i].dy +=  gravity;    
            // x轴位置改变,同时它也受雨角度影响
                 drop[i].pagex += drop[i].dx + direction*10;
                 // y轴位置改变
                 drop[i].pagey += drop[i].dy;
                 //判断雨滴是否超过画布
                 if(drop[i].pagey>canvas.height){
                     //清除水滴
                     drop.splice(i,1);
                 }
           }
       }

7.绑定鼠标事件:

 // 绑定鼠标移动事件
       window.addEventListener('mousemove',e=>{
           // 得到x轴位置
              mouseX = e.clientX;
              //得到y轴位置
              mouseY = e.clientY;
              // 雨角度值,在-1到1之间
              mouseDelay = (e.clientX-canvas.offsetWidth/2)/(canvas.offsetWidth/2);
              
       })
       // 判断鼠标离开事件
       window.addEventListener('mouseout',()=>{
           // 给个值,不会产生雨滴的值就行
           mouseY=canvas.height+40;
       })

8.设置定时器,开始下雨动画:

// 先初始化雨数组
       chushi();
       //设置定时器,开始动画
       setInterval(function(){
           // 清除画布
          rain.clearRect(0,0,canvas.width,canvas.height);
          // 更新雨和雨滴信息
          updateWater();   
          updateDrop();
          // 绘画雨和雨滴
          drawWater();
          drawDrop();
       },20)

三.完整代码:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>北极光之夜。</title>
    <style>
        *{
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
     
        #canvas{
           position: fixed;
           background-color: rgb(0, 0, 0);
           z-index: -10;
        }
        svg{
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%,-50%);
        }
        .txt{   
            font-family: 'fangsong';
            font-weight: 900;
            font-size: 80px;
            letter-spacing: 3px;
            fill: transparent;
            stroke: rgb(30, 134, 252); 
            stroke-width: 1.5px;
            stroke-dasharray: 625;
            stroke-dashoffset: 625;
            animation: draw 2s linear infinite;
            text-shadow: 0 0 10px rgb(30, 134, 252),
            0 0 20px rgb(30, 134, 252),
            0 0 40px rgb(30, 134, 252),
            0 0 60px rgb(30, 134, 252);
        }
        @keyframes draw{
            0%,100%{
                stroke-dasharray: 625;
                stroke-dashoffset: 625;
            }
            45%,55%{
                stroke-dasharray: 652;
                stroke-dashoffset: 0;
            }
        }
    </style>
</head>
<body>
    <svg width="500" height="200">
        <text x="30" y="120" class="txt">北极光之夜。</text>
  </svg>
   
    <canvas id="canvas"></canvas>
    <script>
        // 获取画布
        var canvas = document.querySelector("#canvas");
        var rain = canvas.getContext('2d');
        // drop数组,存每个散开的小水滴信息
        var drop = [];
        // water数组,存每丝雨的信息
        var water = [];
        // 雨的数量,可自行更改
        var waterNum = 100;
        // 小水(雨)滴的重力
        var gravity = 1;
        // 鼠标在页面的初始位置
        var mouseX=-36,mouseY=-36;
        // 关于雨的角度值,值为-1到1,后面讲
        var direction = 0;
        // 这也是关于鼠标在页面位置的角度值,值为-1到1
        var mouseDelay = 0;
        // 这是画布自适应窗口大小的函数,复制即可
        window.onresize = resizeCanvas;
            function resizeCanvas() {
                canvas.width = window.innerWidth;
                canvas.height = window.innerHeight;
            }
            resizeCanvas();
        
       // 一丝雨的初始化,封装,后面好几处要调用
        function creatWater(){         
                water.push({
                    //值为0或1,判断是否要散开水滴
                    add:1,
                    //随机初始水平位置
                    x:Math.random()*3*canvas.width-canvas.width,
                    // 随机初始垂直位置,在上面一点,这样雨能从上面下落
                    y: Math.random()*500-500,
                    // 随机雨的长度
                    len: Math.random()*20+50,
                    // 随机雨的速度
                    speed: Math.random()*10+35,
                    // 随机雨的随机颜色
                    color: `rgb(255,255,255,${Math.random()*0.5})`,
                    // 随机散开水滴数量
                    dropNum:Math.random()*6+6
                })                   
        }
        // 雨数组初始化,每丝雨都来
        function chushi(){
            for (let i = 0; i < waterNum; i++) {
               creatWater();
            } 
        }
       // 散开水滴数组初始化,x为水平位置,y为垂直位置,dropNum为数量
        function creatDrop (x,y,dropNum){
            //给drop数组添加元素
            for (let j = 0; j < dropNum; j++) {
                drop.push({
                    // x轴位置
                    pagex:x,
                    // y轴位置
                    pagey:y,
                    // x轴移动距离
                    dx:Math.random()*12-6,
                    // y轴移动距离
                    dy:Math.random()*10-20,
                    // 半径
                    r:Math.random()+2,
                    //颜色
                    color: `rgb(255,255,255,${Math.以上是关于炎炎夏日,快用代码下场雨ヽ`☂ヽ`canvas的主要内容,如果未能解决你的问题,请参考以下文章

2019.09.13中秋快乐!来点福大猫咪色图ヽ(=^?ω?^=)丿

#夏日挑战赛#FFH这个盛夏,来一场“清凉”的代码雨!

字符画

打印一只皮卡丘!

夏日炎炎有你超甜-Microsoft 365

6岁男孩向他们敬礼2分钟,夏日炎炎,你们都辛苦了!