canvas完成好看的下雨实际效果的示例

日期:2021-01-19 类型:科技新闻 

关键词:建站平台有哪些,如何建设网站,免费自助建站,如何建立一个网站,网站建站的

表明

这篇文章内容说怎样用canvas画出好看的下雨实际效果,先看看最终完成的实际效果吧。

实际效果图

解释

看图来剖析下,大家必须完成哪些实际效果。
1、雨滴着落实际效果,挪动电脑鼠标操纵着落方位
2、雨滴着落散成小水珠,小水珠的挪动方位和电脑鼠标挪动方位同样
3、雨滴着落到电脑鼠标座标1定范畴内,散成小水珠,一样的,小水珠的挪动方位也和电脑鼠标挪动方位同样

好的,大家把全部实际效果大概拆分为3个实际效果,完成这3个实际效果,就进行了。

大家1步1步来完成。

1、雨滴着落实际效果,挪动电脑鼠标操纵着落方位

完成全部实际效果的思路便是,

原始时

用1个数字能量数组储存雨滴目标。

1个雨滴目标里边有各个特性用来表明,雨滴的x座标,y座标,长度,着落速率,色调,分辨是不是删掉的标示位

升级动漫时

往数字能量数组中加上1定数量的雨滴目标,随后遍历数字能量数组,改动每一个雨滴目标的x座标和y座标,用canvas依据雨滴目标的座标,画出两个点,连起来便是1个雨滴了。

因此完成实际效果的关键就在座标上

原始化1个雨滴的情况下

雨滴x座标:1个任意数

雨滴y座标:⑴00,这样是以便让雨滴从可视性地区外进来

升级动漫时

雨滴x座标:原x座标的值 + speed * speedx

speed 是1个固定不动的值,表明雨滴着落速率,

speedx 是1个和电脑鼠标挪动方位相关系的自变量,speedx = speedx + (maxspeedx - speedx) / 50

而maxspeedx 是依据电脑鼠标挪动方位获得的1个值

maxspeedx = (e.clientX - canvasEl.clientWidth / 2) / (canvasEl.clientWidth / 2)

e.clientX:电脑鼠标间距可视性地区左侧的值

canvasEl.clientWidth:全部可视性地区的宽度

也便是说 speedx 是1个慢慢贴近maxspeedx 的值

maxspeedx 的赋值范畴是 ⑴ 到 1,他的值越贴近 ⑴,表明方位越向左,值越贴近1,表明方位越向右。

为何不立即用maxspeedx ?

这是以便让雨滴转变方位的速率不必那末快,不必追随电脑鼠标转变方位马上更改,要有点点的延迟时间,看上去更好些。

假如用maxspeedx ,是这样的实际效果

假如用speedx ,是这样的实际效果

雨滴y座标:原y座标的值 + speed

speed 和上面x座标中提到的1样,是1个固定不动值,表明雨滴着落速率,

好的,最终便是用canvas依据雨滴目标的座标,画两个点了,随后连起来,雨滴就画出来了

第1个点座标较为简易,立即获得雨滴目标的x座标和y座标,便是这个点的座标

第2个点的座标:
x座标 = 雨滴x座标的值 + 雨滴长度 * speedx
y座标 = 雨滴y座标的值 + 雨滴长度

最终把这两个点连起来,就有1条线了,便是1个雨滴了

当设定x座标时,又用到了自变量 speedx,这是以便让 雨滴方位 和 雨滴着落方位同样,

当无需 speedx时,是这样

当用上speedx时,是这样

2、雨滴着落散成小水珠,小水珠的挪动方位和电脑鼠标挪动方位同样

这里的思路实际上,和上面的实际效果一些类似

原始时

用1个数字能量数组储存小水珠目标。

1个小水珠,实际上便是画1个圆弧。

1个小水珠目标里边有各个特性用来表明,小水珠的座标,x轴挪动速率,y轴挪动速率,圆的半径,分辨是不是删掉的标示位。

升级动漫时

往数字能量数组中加上1定数量的小水珠目标,随后遍历数字能量数组,改动每一个小水珠目标的x座标和y座标,用canvas依据小水珠目标的座标特性 和 半径特性,画1个圆弧。

因此完成实际效果的关键还在座标上

原始化1个小水珠的情况下

小水珠是雨滴消退的情况下出現的,因此小水珠的座标也是依据雨滴的座标来的,删掉1个雨滴,就出現1些小水珠,并且小水珠的挪动方位也是和雨滴着落方位,电脑鼠标挪动方位1样,因此還是会必须上面提到的自变量 speedx,

小水珠x座标: 删掉的雨滴x座标 + 删掉的雨滴长度 * speedx
小水珠y座标:删掉的雨滴y座标 + 删掉的雨滴长度

升级动漫时

这里要用到小水珠目标的两个特性 vx(x轴的值 的转变速率) 和vy(y轴的值 的转变速率),

小水珠的x座标
vx = vx + speedx / 2
小水珠的x座标 =原x座标 + vx

speedx:上面提到的和电脑鼠标挪动方位有关的1个自变量,这里的功效便是用来操纵小水珠的挪动方位和别的方位同样
speedx / 2,除2是以便使 让小水珠 在x轴的挪动间距短1点,看上去更真正点

小水珠的y座标
vy = vy + gravity
小水珠的y座标 = 原y座标 + vy;
vy:1个负数
gravity:重力,1个正数,详细编码里设定的是0.5
由于 原y座标 是1个正数,这样小水珠y座标的值,就会先减小后增大,这是以便完成小水珠会先升高后降低的实际效果,看图

最终便是用canvas依据小水珠的座标特性和半径特性画圆弧便可以了,弧度是任意的

3、雨滴着落到电脑鼠标座标1定范畴内,散成小水珠,一样的,小水珠的挪动方位也和电脑鼠标挪动方位同样

明确图中圆的尺寸非常容易,假定圆的半径是35,大家能获得到电脑鼠标的座标,以电脑鼠标的座标为圆心,35为半径,就明确了圆的尺寸。

关键在于怎样分辨,雨滴是否进到了这个范畴,这就要用勾股定理了,看图。

由于雨滴是两个点连起来的1条线,要看雨滴是否进到了这个范畴内, 便是看雨滴靠下边的点的座标,到电脑鼠标的平行线间距是是多少,便是图中AB直线的长度。

勾股定理:直角3角形的两条直角边的平方和等于斜边的平方。

AB = Math.sqrt(BCBC + AC AC)

BC = 雨滴x座标 - 电脑鼠标x座标
AC = 雨滴y座标 - 电脑鼠标y座标
Math.sqrt()方式用来测算1个数的平方根

大家了解雨滴到电脑鼠标的平行线间距后,和圆的半径较为下,超过半径就不在范畴内,不然便是在了。
假如在范畴内,就删掉雨滴,画1些小水珠。

总结

要完成这个实际效果,不便的地区在于方位,雨滴方位,雨滴着落方位,小水珠挪动方位,而这些都和电脑鼠标挪动方位有关,明确各种各样方位后,依据间距,用canvas持续的画线,画圆弧就可以了。

详细编码

<!doctype html>
<html lang="en">
<head>
  <meta charset="UTF⑻">
  <style>
    * {
      margin: 0;
      padding: 0;
    }
  </style>
</head>
<body>
  <canvas id="canvas" style="position: absolute; height: 100%; width:100%;"></canvas>
  <script>
    window.onload = main;
    function main() {
      // 获得canvas元素
      var canvasEl = document.getElementById('canvas');
      var ctx = canvasEl.getContext('2d');
      // canvas画布的 情况色调
      var backgroundColor = '#000';

      // canvas画布的宽 等于 可视性地区的宽
      canvasEl.width = canvasEl.clientWidth;
      // canvas画布的高 等于 可视性地区的高
      canvasEl.height = canvasEl.clientHeight;

      // 储存小水珠的数字能量数组
      // 雨滴着落后散成小水珠,小水珠便是1些圆弧
      var dropList = [];

      // 重力
      // 雨滴着落后散成小水珠,小水珠会先升高后降低,关键是由于 gravity 这个自变量的原因
      var gravity = 0.5;

      // 储存雨滴的数字能量数组
      // 每一个雨滴 全是 画的1条线 
      var linelist = [];

      // 储存电脑鼠标的座标 
      // mousePos[0] 意味着x轴的值,mousePos[1] 意味着y轴的值 
      var mousePos = [0, 0];

      // 追随电脑鼠标, mouseDis 尺寸地区内的雨滴会消退,产生散落实际效果
      // 以mousePos为圆心,mouseDis为半径,这个范畴内的雨滴 都会散开,产生很多小水珠
      var mouseDis = 35;

      // 升级1次动漫,画lineNum 条雨滴,lineNum 值越大,下雨就越聚集
      var lineNum = 3;

      // 追随电脑鼠标方位 转变下雨方位的 速率
      // 电脑鼠标挪动后,下雨的方位 会渐渐地更改,关键靠speedx 这个自变量
      var speedx = 0;

      // maxspeedx 为 speedx 能够取的最大值
      // 当 speedx = maxspeedx时,下雨方位 会 随电脑鼠标挪动方位马上更改
      var maxspeedx = 0;

      // 网页页面尺寸产生转变时,重设canvas画布尺寸
      window.onresize = function () {
        canvasEl.width = canvasEl.clientWidth;
        canvasEl.height = canvasEl.clientHeight;
      }

      //挪动电脑鼠标开启恶性事件
      window.onmousemove = function (e) {
        //  设定mousePos 等于 电脑鼠标座标
        //  e.clientX 为间距 访问器对话框可视性地区 左侧的间距
        //  e.clientY 为间距 访问器对话框可视性地区 上边的间距
        mousePos[0] = e.clientX;
        mousePos[1] = e.clientY;

        // 根据电脑鼠标部位,设定 maxspeedx的值,赋值范畴是 ⑴ 到 1
        // maxspeedx的值,关联到 
        // 1、雨滴的方位
        // 2、雨滴着落的方位
        // 3、雨滴着落方位 追随 电脑鼠标挪动方位转变的速率
        // 4、小水珠的挪动方位
        // 值越贴近1,表明方位越向右
        // 值越贴近⑴,表明方位越向左
        maxspeedx = (e.clientX - canvasEl.clientWidth / 2) / (canvasEl.clientWidth / 2);
      }

      // 依据主要参数,回到1个rgb色调,用于给雨滴设定色调
      function getRgb(r, g, b) {
        return "rgb(" + r + "," + g + "," + b + ")";
      }

      // 画 1滴雨(1条线)
      function createLine(e) {
        // 任意转化成 雨滴的长度
        var temp = 0.25 * (50 + Math.random() * 100);
        // 1个 line 目标,意味着1个雨滴
        var line = {
          // 雨滴着落速率  
          speed: 5.5 * (Math.random() * 6 + 3),
          // 分辨是不是删掉,值为true就删掉
          die: false,
          // 雨滴x座标 
          posx: e,
          // 雨滴y座标 
          posy: ⑸0,
          // 雨滴的长度
          h: temp,
          // 雨滴的色调
          color: getRgb(Math.floor(temp * 255 / 75), Math.floor(temp * 255 / 75), Math.floor(temp * 255 / 75))
        };
        // 把建立好的line(雨滴)目标,加上到储存雨滴的数字能量数组
        linelist.push(line);
      }

      // 画1个小水珠(雨滴散开后的小水珠便是1个个的圆弧)
      function createDrop(x, y) {
        // 1个 drop 目标,意味着1个圆弧
        var drop = {
          // 分辨是不是删掉,值为true就删掉
          die: false,
          // 圆弧圆心的x座标 
          posx: x,
          // 圆弧圆心的y座标 
          posy: y,
          // vx 表明 x轴的值 转变的速率
          vx: (Math.random() - 0.5) * 8,
          // vy 表明 y轴的值 转变的速率 赋值范畴:⑶ 到 ⑼
          vy: Math.random() * (⑹) - 3,
          // 圆弧的半径
          radius: Math.random() * 1.5 + 1
        };
        return drop;
      }

      // 画1定数量的小水珠
      function madedrops(x, y) {
        // 任意转化成1个数 maxi
        // maxi 意味着要画小水珠的数量
        var maxi = Math.floor(Math.random() * 5 + 5);
        for (var i = 0; i < maxi; i++) {
          dropList.push(createDrop(x, y));
        }
      }

      // 刚开始启用update涵数,升级动漫
      window.requestAnimationFrame(update);
      // 升级动漫
      function update() {
        // 假如储存小水珠的数字能量数组有內容
        if (dropList.length > 0) {
          // 遍历储存小水珠的数字能量数组
          dropList.forEach(function (e) {
            //设定e.vx,vx表明x座标转变的速率
            // (speedx)/2 是以便,让小水珠 在x轴的挪动间距短1点,看上去更真正点
            // 也使 小水珠的挪动方位 和 雨滴方位,雨滴着落方位,电脑鼠标挪动方位同样
            e.vx = e.vx + (speedx / 2);
            e.posx = e.posx + e.vx;
            
            //设定e.vy,vy表明y座标转变的速率
            // e.vy的范畴是⑶ 到 ⑼,而这时候e.posy(y座标)1定是恰逢,因此 e.posy的值会先减小后增大
            // 也便是完成 雨滴散成小水珠,小水珠会先升高后降低的实际效果
            e.vy = e.vy + gravity;
            e.posy = e.posy + e.vy;

            // 假如 小水珠y座标 超过 可视性地区的高宽比,设定die特性为true
            // 小水珠假如超过可视性地区就删掉掉
            if (e.posy > canvasEl.clientHeight) {
              e.die = true;
            }
          });
        }

        // 删掉 die特性为ture 的数字能量数组组员
        // 可视性地区外的小水珠删掉掉
        for (var i = dropList.length - 1; i >= 0; i--) {
          if (dropList[i].die) {
            dropList.splice(i, 1);
          }
        }

        // 设定下雨方位转换的速率,赋值范畴: ⑴ 到 1
        // 当 speedx = maxspeedx时,下雨方位 会 随电脑鼠标挪动方位马上更改
        speedx = speedx + (maxspeedx - speedx) / 50;

        // 依据lineNum的值,画1定数量雨滴
        for (var i = 0; i < lineNum; i++) {
          // 启用createLine 涵数,主要参数是雨滴x座标
          createLine(Math.random() * 2 * canvasEl.width - (0.5 * canvasEl.width));
        }

        // 设定完毕线,也便是雨滴散开 产生很多小水珠的部位
        var endLine = canvasEl.clientHeight - Math.random() * canvasEl.clientHeight / 5;

        // 遍历储存雨滴的数字能量数组
        linelist.forEach(function (e) {

          // 运用勾股定理 明确1个范畴,在这个范畴内雨滴会散开产生小水珠
          // e.posx + speedx * e.h 是雨滴x座标
          // e.posy + e.h 是雨滴y座标
          var dis = Math.sqrt(((e.posx + speedx * e.h) - mousePos[0]) * ((e.posx + speedx * e.h) - mousePos[0]) + (e.posy + e.h - mousePos[1]) * (e.posy + e.h - mousePos[1]));

          // 假如在mouseDis地区内,就删掉雨滴,画1些小水珠(圆弧)
          // 完成电脑鼠标碰到雨滴,雨滴散成小水珠的实际效果
          if (dis < mouseDis) {
            // 删掉 雨滴
            e.die = true;
            // 画1些小水珠(圆弧)
            madedrops(e.posx + speedx * e.h, e.posy + e.h);
          }

          // 假如雨滴超出 完毕线,删掉雨滴,画1些小水珠(圆弧)
          if ((e.posy + e.h) > endLine) {
            e.die = true;
            madedrops(e.posx + speedx * e.h, e.posy + e.h);
          }

          // 假如 雨滴 y座标 超过 可视性地区的高宽比,设定die特性为true
          // 假如 雨滴 超过可视性地区就删掉掉
          if (e.posy >= canvasEl.clientHeight) {
            e.die = true;
          } else {
            // 慢慢提升 雨滴 y座标的值
            e.posy = e.posy + e.speed;

            // 转变雨滴 x座标
            // * speedx 用来操纵雨滴 着落 方位
            // 使 雨滴着落方位 和 电脑鼠标挪动方位同样
            e.posx = e.posx + e.speed * speedx;
          }
        });

        // 删掉 die特性为ture 的数字能量数组组员
        // 电脑鼠标地区内的,超出完毕线的,可视性地区外的雨滴删掉掉
        for (var i = linelist.length - 1; i >= 0; i--) {
          if (linelist[i].die) {
            linelist.splice(i, 1);
          }
        }

        // 3D渲染
        render();
        // 递归启用 update,完成动漫实际效果
        window.requestAnimationFrame(update);
      }

      // 3D渲染
      function render() {
        // 画1个和可视性地区1样大的矩形框
        ctx.fillStyle = backgroundColor;
        ctx.fillRect(0, 0, canvasEl.width, canvasEl.height);

        // 画雨滴实际效果
        ctx.lineWidth = 5;
        linelist.forEach(function (line) {
          ctx.strokeStyle = line.color;
          ctx.beginPath();
          ctx.moveTo(line.posx, line.posy);

          // * speedx 用来操纵雨滴方位
          // 使 雨滴方位 和 电脑鼠标挪动方位同样
          ctx.lineTo(line.posx + line.h * speedx, line.posy + line.h);
          ctx.stroke();
        });

        // 画雨滴散开产生小水珠实际效果
        ctx.lineWidth = 1;
        ctx.strokeStyle = "#fff";
        dropList.forEach(function (e) {
          ctx.beginPath();
          ctx.arc(e.posx, e.posy, e.radius, Math.random() * Math.PI * 2, 1 * Math.PI);
          ctx.stroke();
        });

        // 解开注解,可看见电脑鼠标范畴
        /*
          ctx.beginPath();
          ctx.arc(mousePos[0], mousePos[1], mouseDis, 0, 2 * Math.PI);
          ctx.stroke();
        */
      }
    }
  </script>
</body>

</html>

以上便是本文的所有內容,期待对大伙儿的学习培训有一定的协助,也期待大伙儿多多适用脚本制作之家。

上一篇:Html5之title吸顶作用 返回下一篇:没有了