30行代码实现红包雨🧧

1,064 阅读1分钟

我正在参加「兔了个兔」创意投稿大赛,详情请看:「兔了个兔」创意投稿大赛

本文技术栈:React + Vue3 + svelte

React 是一个用于构建用户界面的 JavaScript 库

Vue 是渐进式 JavaScript 框架

Svelte 是一种全新的构建用户界面的方法

通过 img 的 left 来控制红包的距离右边的位置,animation-duration 来控制图片降落的时间。

为了方便大家使用框架的不同,我这边把我会的三种框架都整上了,大家想用的话,直接复制粘贴就好了。

React

import React, { useState, useEffect } from "react"
import './index.css'

const RedEnvelope = () => {
  const redEnvelopeList = Array.from(new Array(20))
  const [maxLeft, setMaxLeft] = useState(0)

  useEffect(() => {
    setMaxLeft(document.body.offsetWidth)
  }, [])

  return (
    <>
      {
        redEnvelopeList.map((v) => {
          return (
            <img
              src="https://cdn.pixabay.com/photo/2022/04/12/07/05/red-envelope-7127397_1280.png"
              class="img"
              style={{
                left: `${Math.random() * maxLeft}px`,
                animationDuration: `${Math.random() * 2 + 1}s`
              }}
              key={v}
            />
          )
        })
      }
    </>
  )
}

export default RedEnvelope

Vue3

<template>
  <img
    v-for="v in redEnvelopeList"
    src="https://cdn.pixabay.com/photo/2022/04/12/07/05/red-envelope-7127397_1280.png"
    alt=""
    class="img"
    :key="v"
    :style="{
      left: `${Math.random() * maxLeft}px`,
      animationDuration: `${Math.random() * 2 + 1}s`,
    }"
  />
</template>

<script>
import { defineComponent, ref, onMounted } from "vue";

export default defineComponent({
  setup() {
    const redEnvelopeList = ref(Array.from(new Array(20)));
    const maxLeft = ref(0);

    onMounted(() => {
      maxLeft.value = document.body.offsetWidth;
    });

    return {
      redEnvelopeList,
      maxLeft,
    };
  },
});
</script>

<style lang="css">
// .....
</style>

Svelte

<style> 块中的 CSS,其作用域受限于该组件。这是通过向元素添加一个类来实现的,该类基于组件样式的哈希值而生成的(例如 svelte-123xyz)。

<script>
  import { onMount } from "svelte";

  export const redEnvelopeList = Array.from(new Array(20)).fill(0);
  export let maxLeft = 0;

  onMount(() => {
    maxLeft = document.body.offsetWidth;
  });
</script>

<main>
  {#each redEnvelopeList as v}
    <img
      src="https://cdn.pixabay.com/photo/2022/04/12/07/05/red-envelope-7127397_1280.png"
      alt=""
      class="img"
      style="left: {Math.random() *
        maxLeft}px; animation-duration: {Math.random() * 2 + 1}s;"
    />
  {/each}
</main>

<style>
  :global(body) {
  /* 这个样式就是全局的 */
    padding: 0;
    margin: 0;
    background-image: url("https://cdn.pixabay.com/photo/2017/01/04/21/00/fireworks-1953253_1280.jpg");
    background-size: cover;
  }

  // ...
</style>

index.css

body {
  background-image: url('https://cdn.pixabay.com/photo/2017/01/04/21/00/fireworks-1953253_1280.jpg');
  background-size: cover;
}

.img {
  position: fixed;
  top: -100px;
  width: 40px;
  animation: run infinite linear;
}

@keyframes run {
  0% {
    transform: translateY(0);
  }

  100% {
    transform: translateY(150vh);
  }
}