使用js和canvas实现下雪效果

需求:

实现较为逼真的下雪效果

实现:

<!-- snow 样式 -->

<style>

body {

display: flex;

justify-content: center;

align-items: center;

gap: 1em;

min-height: 100vh;

background-image: radial-gradient(circle at 50% 100%, #1b1b35, #121225);

font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,

"Helvetica Neue", "Open Sans", system-ui, sans-serif,

"Apple Color Emoji", "Segoe UI Emoji";

}

.canvas {

position: absolute;

inset: 0;

pointer-events: none;

}

.rotate-container {

display: inline-block;

position: absolute;

z-index: 17;

width: 10rem;

height: 10rem;

left: 50%;

top: 5.8rem;

animation: rotate-container 17s linear infinite;

transform: translateX(-50%);

}

.ball-img {

width: 100%;

height: 100%;

}

.title-img{

display: inline-block;

position: absolute;

z-index: 17;

width: 6rem;

/* height: 2rem; */

left: 50%;

top: 10rem;

transform: translateX(-50%);

}

/* @keyframes rotate-container {

0% {

transform: translateX(-50%) rotate(0deg) scale(1);

}

25% {

transform: translateX(-50%) rotate(90deg) scale(0.8);

}

50% {

transform: translateX(-50%) rotate(180deg) scale(1);

}

75% {

transform: translateX(-50%) rotate(270deg) scale(0.8);

}

100% {

transform: translateX(-50%) rotate(360deg) scale(1);

}

} */



 

@keyframes rotate-container {

0% {

transform: translateX(-50%) rotate(0deg) scale(1);

}

25% {

transform: translateX(-50%) rotate(90deg) scale(1);

}

50% {

transform: translateX(-50%) rotate(180deg) scale(1);

}

75% {

transform: translateX(-50%) rotate(270deg) scale(1);

}

100% {

transform: translateX(-50%) rotate(360deg) scale(1);

}

}

.T9TB07{

z-index: 17;

}

.zlfwHK{

z-index: 17;

}

<body style="background: #fff;">

<div id="app" id="app" style="background-color: #333;

overflow: hidden;">

<!-- canvas 雪花 -->

<canvas class="canvas" style="display: flex;

z-index: 18;

position: fixed;

"></canvas>

</div>

<!-- 雪花 代码 -->

<script>

const canvas = document.querySelector(".canvas");

const ctx = canvas.getContext("2d");

const pixelRatio = window.devicePixelRatio || 1;

const snowflakes = [];

class Snowflake {

constructor() {

this.x = Math.random() * canvas.width;

this.y = Math.random() * canvas.height;

const maxSize = 3;

this.size = Math.random() * (maxSize - 1) + 1;

this.velocity = this.size * 0.35;

const opacity = this.size / maxSize;

this.fill = `rgb(255 255 255 / ${opacity})`;

this.windSpeed = (Math.random() - 0.5) * 0.1;

this.windAngle = Math.random() * Math.PI * 2;

}

isOutsideCanvas() {

return this.y > canvas.height + this.size;

}

reset() {

this.x = Math.random() * canvas.width;

this.y = -this.size;

}

update() {

this.windAngle += this.windSpeed;

this.wind = Math.cos(this.windAngle) * 0.5;

this.x += this.wind;

this.y += this.velocity;

if (this.isOutsideCanvas()) {

this.reset();

}

}

draw() {

ctx.beginPath();

ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);

ctx.fillStyle = this.fill;

ctx.fill();

ctx.closePath();

}

}

const createSnowflakes = () => {

// snowflakeCount = Math.floor(

// (window.innerWidth * window.innerHeight) / 1400

// );

snowflakeCount = Math.floor(

(1920*2000) / 1400

);

console.log(snowflakeCount,'snowflakeCount')

for (let i = 0; i < snowflakeCount; i++) {

snowflakes.push(new Snowflake());

}

};

console.log(window.innerWidth,'window.innerWidth-')

console.log(window.innerHeight,'window.innerHeight-')

// 调整canvas大小

const resizeCanvas = () => {

const width = window.innerWidth;

console.log(width,'window.innerWidth')

const height = window.innerHeight;

console.log(pixelRatio,'pixelRatio')

canvas.width = width * pixelRatio;

console.log(canvas.width,'canvas.width')

canvas.height = height * pixelRatio;


 

canvas.style.width = `${width}px`;

canvas.style.height = `${height}px`;

// 修改

// canvas.style.width = `100%`;

// canvas.style.height = `100%`;

ctx.scale(pixelRatio, pixelRatio);

snowflakes.length = 0;

createSnowflakes();

};

window.addEventListener("resize", resizeCanvas);

resizeCanvas();

const render = () => {

requestAnimationFrame(render);

ctx.clearRect(0, 0, canvas.width, canvas.height);

snowflakes.forEach((snowflake) => {

snowflake.update();

snowflake.draw();

});

};

render();

</script>

</body>

<!DOCTYPE html>
<html lang="en">
  <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, maximum-scale=1.0, user-scalable=0" />
    
    <!-- snow 样式 -->
    <style>
      body {
        display: flex;
        justify-content: center;
        align-items: center;
        gap: 1em;
        min-height: 100vh;
        background-image: radial-gradient(circle at 50% 100%, #1b1b35, #121225);
        font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
          "Helvetica Neue", "Open Sans", system-ui, sans-serif,
          "Apple Color Emoji", "Segoe UI Emoji";
      }

      .canvas {
        position: absolute;
        inset: 0;
        pointer-events: none;
      }
      .rotate-container {
        display: inline-block;
        position: absolute;
        z-index: 17;
        width: 10rem;
        height: 10rem;
        left: 50%;
        top: 5.8rem;
        animation: rotate-container 17s linear infinite;
        transform: translateX(-50%);
      }

      .ball-img {
          width: 100%;
          height: 100%;
      }

      .title-img{
        display: inline-block;
    position: absolute;
    z-index: 17;
    width: 6rem;
    /* height: 2rem; */
    left: 50%;
    top: 10rem;
    transform: translateX(-50%);
      }
      @keyframes rotate-container {
          0% {
              transform: translateX(-50%) rotate(0deg) scale(1);
          }
          25% {
              transform: translateX(-50%) rotate(90deg) scale(1);
          }
          50% {
              transform: translateX(-50%) rotate(180deg) scale(1);
          }
          75% {
              transform: translateX(-50%) rotate(270deg) scale(1);
          }
          100% {
              transform: translateX(-50%) rotate(360deg) scale(1);
          }
      }
      .T9TB07{
        z-index: 17;
      }
      .zlfwHK{
        z-index: 17;
      }
    </style>
  </head>

  <body style="background: #fff;">
    <div id="app" id="app" style="background-color: #333;
    overflow: hidden;">
      <!-- canvas 雪花 -->
      <canvas class="canvas" style="display: flex;
        z-index: 18;
        position: fixed;
        "></canvas>
        
    </div>


    <!-- 雪花 代码 -->
    <script>
      const canvas = document.querySelector(".canvas");
      const ctx = canvas.getContext("2d");

      const pixelRatio = window.devicePixelRatio || 1;

      const snowflakes = [];

      class Snowflake {
        constructor() {
          this.x = Math.random() * canvas.width;
          this.y = Math.random() * canvas.height;

          const maxSize = 3;
          this.size = Math.random() * (maxSize - 1) + 1;
          this.velocity = this.size * 0.35;
          const opacity = this.size / maxSize;
          this.fill = `rgb(255 255 255 / ${opacity})`;

          this.windSpeed = (Math.random() - 0.5) * 0.1;
          this.windAngle = Math.random() * Math.PI * 2;
        }
        isOutsideCanvas() {
          return this.y > canvas.height + this.size;
        }
        reset() {
          this.x = Math.random() * canvas.width;
          this.y = -this.size;
        }
        update() {
          this.windAngle += this.windSpeed;
          this.wind = Math.cos(this.windAngle) * 0.5;

          this.x += this.wind;
          this.y += this.velocity;

          if (this.isOutsideCanvas()) {
            this.reset();
          }
        }
        draw() {
          ctx.beginPath();
          ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
          ctx.fillStyle = this.fill;
          ctx.fill();
          ctx.closePath();
        }
      }

      const createSnowflakes = () => {
        // snowflakeCount = Math.floor(
        //   (window.innerWidth * window.innerHeight) / 1400
        // );
        snowflakeCount = Math.floor(
          (1920*2000) / 1400
        );
        console.log(snowflakeCount,'snowflakeCount')
        for (let i = 0; i < snowflakeCount; i++) {
          snowflakes.push(new Snowflake());
        }
      };
      
      console.log(window.innerWidth,'window.innerWidth-')
      console.log(window.innerHeight,'window.innerHeight-')
      // 调整canvas大小
      const resizeCanvas = () => {
        const width = window.innerWidth;
        console.log(width,'window.innerWidth')
        const height = window.innerHeight;
        console.log(pixelRatio,'pixelRatio')
        canvas.width = width * pixelRatio;
        console.log(canvas.width,'canvas.width')
        canvas.height = height * pixelRatio;


        canvas.style.width = `${width}px`;
        canvas.style.height = `${height}px`;

        // 修改
        // canvas.style.width = `100%`;
        // canvas.style.height = `100%`;

        ctx.scale(pixelRatio, pixelRatio);
        snowflakes.length = 0;
        createSnowflakes();
      };

      window.addEventListener("resize", resizeCanvas);

      resizeCanvas();

      const render = () => {
        requestAnimationFrame(render);
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        snowflakes.forEach((snowflake) => {
          snowflake.update();
          snowflake.draw();
        });
      };

      render();
    </script>
  </body>

  
</html>

实现效果:

录屏2023-12-21 11.26.28

  • 22
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值