首页 前端知识 用coding向你最爱的人说圣诞快乐

用coding向你最爱的人说圣诞快乐

2024-01-29 14:01:31 前端知识 前端哥 907 644 我要收藏

文章目录

    • 圣诞节的起源
    • 圣诞祝福语
    • 用 coding 说圣诞快乐
      • Canvas 渲染 圣诞树特效
      • 唯美圣诞树
      • CSS实现圣诞树
      • 简易的圣诞树
      • 线性树
      • 卡片圣诞树

🎄🎄🎄圣诞节即将到来,今天让我们用编码的方式向你最爱的人表达圣诞节快乐

圣诞节的起源

 圣诞节源自古罗马人迎接新年的农神节,与基督教本无关系。在基督教盛行罗马帝国后,教廷将这种民俗节日纳入基督教体系,同时以庆祝耶稣的降生。但在圣诞节这天不是耶稣的生辰,因为《圣经》未记载耶稣具体出生时间,同样没提到过有此种节日,是基督教吸收了古罗马神话的结果。

在这里插入图片描述

 圣诞节是西方传统节日,也是许多西方国家一年中最重要的节日。每年这一天,欢快的圣诞歌在大街小巷飘扬,商场里流光溢彩,琳琅满目,到处弥漫着温馨欢乐的气息。孩子们在甜美的梦乡中,盼望着圣诞老人从天而降,带来梦寐以求的礼物。

在这里插入图片描述

 平安夜和圣诞节现在很多人都在过,对于很多人而言,并不是在做一个所谓的洋节,而是在这一天让自己爱的人和爱我们的人开心,正如网络上流行的一句话:“ 世界上本没有圣诞老人,所有的惊喜和礼物都来自于爱你的人。

圣诞祝福语

🎄 Merry Christmas

🎄今年圣诞老人🎅🏻也很忙喔

所以轮到我把圣诞惊喜给你咯!

🎄今天扎了个蝴蝶结,像不像你的圣诞礼物。

圣诞节没有领到礼物的到我这里领个37°的拥抱吧🎅🏻

🎄蟹蟹圣诞老公公,送礼全世界最棒的礼物给我,就是把你放进我心里。

麋鹿不会迷路,圣诞之礼,终将准时送达。🎅🏻

多少人,一夜之间,没穿圣诞装,却成了圣诞老人。🎅🏻

把我的小心思,偷偷塞进礼物盒,在圣诞节那一天,通通送给你

圣诞有我,要开心哦(• . •)

我想和你一起看夜景 一起吃热热的烤火鸡 一起许愿 看着那会发光的圣诞树 一起倒数

你快跳进圣诞老人的背包里 一觉醒来你就是我的礼物

想给每个善良的人一顶圣诞帽 愿这顶帽子成为他们的睡帽 从此每个安睡的日子都叫平安夜

希望圣诞树 和你一起到来🎄

圣诞快乐,喜乐长安。🎄

用 coding 说圣诞快乐

Canvas 渲染 圣诞树特效

在这里插入图片描述

index.html

<!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">
    <title>ChristmasTree</title>
    <style>
        html,
        body {
            margin: 0;
            width: 100%;
            height: 100%
        }
        body {
            height: 100%;
            display: flex;
            justify-content: center;
            align-items: center;
            background-color: black;
            position: relative;
            overflow-x: hidden;
            overflow-y: hidden;
        }
        .snow-container {
            position: absolute;
            width: 400px;
            height: 550px;
            color: white;
        }
        @media screen and (max-width: 450px) {
            .snow-container {
                width: 100%;
            }
        }
        .snow-box {
            position: relative;
            width: 100%;
            height: 100%;
        }
        .snow {
            position: absolute;
            animation: 5s snow linear infinite;
        }
        @keyframes snow {
            0% {
                left: 0;
                top: 0
            }
            80% {
                top: 90%
            }
            100% {
                top: 90%
            }
        }
        .snow2 {
            left: 5%;
            top: 2%;
            position: absolute;
            animation: 10s snow2 ease-in infinite;
        }
        @keyframes snow2 {
            0% {
                left: 5%;
                top: 2%;
            }
            80% {
                top: 90%
            }
            100% {
                top: 90%
            }
        }
        .snow3 {
            left: 10%;
            top: 8%;
            position: absolute;
            animation: 8s snow3 ease-out infinite;
        }
        @keyframes snow3 {
            0% {
                left: 5%;
                top: 2%;
            }
            80% {
                top: 90%
            }
            100% {
                top: 90%
            }
        }
        .snow4 {
            left: 18%;
            top: 18%;
            position: absolute;
            animation: 7s snow4 ease-out infinite;
        }
        @keyframes snow4 {
            0% {
                left: 18%;
                top: 18%;
            }
            80% {
                top: 90%
            }
            100% {
                top: 90%
            }
        }
        .snow5 {
            left: 59%;
            top: 1%;
            position: absolute;
            animation: 6s snow4 ease infinite;
        }
        @keyframes snow5 {
            0% {
                left: 75%;
                top: 18%;
            }
            80% {
                top: 90%
            }
            100% {
                top: 90%
            }
        }
        .snow6 {
            left: 65%;
            top: 5%;
            position: absolute;
            animation: 6s snow6 ease-in infinite;
        }
        @keyframes snow6 {
            0% {
                left: 75%;
                top: 18%;
            }
            80% {
                top: 90%
            }
            100% {
                top: 90%
            }
        }
        .snow7 {
            left: 75%;
            top: 18%;
            position: absolute;
            animation: 11s snow5 ease infinite;
        }
        @keyframes snow7 {
            0% {
                left: 75%;
                top: 18%;
            }
            80% {
                top: 90%
            }
            100% {
                top: 90%
            }
        }
        .snow8 {
            left: 90%;
            top: 40%;
            position: absolute;
            animation: 5s snow8 ease-out infinite;
        }
        @keyframes snow8 {
            0% {
                left: 90%;
                top: 20%;
            }
            80% {
                top: 90%
            }
            100% {
                top: 90%
            }
        }
        .snow9 {
            left: 50%;
            top: 10%;
            position: absolute;
            animation: 5s snow9 ease-out infinite;
        }
        @keyframes snow9 {
            0% {
                left: 85%;
                top: 20%;
            }
            80% {
                left: 50%;
                top: 90%
            }
            100% {
                top: 90%
            }
        }
        .snow10 {
            left: 100%;
            top: 10%;
            position: absolute;
            animation: 7s snow10 ease infinite;
        }
        @keyframes snow10 {
            0% {
                left: 100%;
                top: 10%;
            }
            80% {
                left: 50%;
                top: 90%
            }
            100% {
                left: 50%;
                top: 90%
            }
        }
        .text {
            font-size: 40px;
            color: #f1ebe5;
            text-shadow: 0 8px 9px #c4b59d, 0px -2px 1px #fff;
            font-weight: bold;
            letter-spacing: 2px;
            text-align: center;
            position: absolute;
            white-space: nowrap;
            left: 50%;
            transform: translate(-50%, -50%);
        }
    </style>
</head>

<body>
    <div class="snow-container">
        <div class="snow-box">
            <span class="snow">*</span>
            <span class="snow2">*</span>
            <span class="snow3">*</span>
            <span class="snow4">*</span>
            <span class="snow5">*</span>
            <span class="snow6">*</span>
            <span class="snow7">*</span>
            <span class="snow8">*</span>
            <span class="snow9">*</span>
            <span class="snow10">*</span>
        </div>

        <div class="text">鱼找水的🎄</div>
    </div>
    <canvas id="canvas" width="375" height="500"></canvas>
    <script src="./assets/index.js">
    </script>
    <script>
        new ChristmasTree().renderTree()
    </script>
</body>

</html>

index.js

class ChristmasTree {
    constructor() {
        this.side = 20
        this.gap = 6 + this.side
        this.init()
        this.treeData = []
    }

    init() {
        this.canvas = document.querySelector('#canvas')
        this.ctx = this.canvas.getContext('2d')
        const { width, height } = this.canvas
        this.width = width
        this.height = height
        this.ctx.fillStyle = 'rgb(0, 0, 0)'
        this.ctx.fillRect(0, 0, width, height)
    }

    createArc(x, y, color) {
        this.ctx.beginPath()
        this.ctx.fillStyle = color
        this.ctx.arc(x, y, this.side / 2, 0, Math.PI * 2, false)
        this.ctx.fill()
    }

    createRect(x, y, color) {
        this.ctx.fillStyle = color
        this.ctx.fillRect(x, y, this.side, this.side)
    }

    createPentastar(x, y, color) {
        this.ctx.beginPath()
        const R = this.gap / 2,
            r = this.gap / 5

        for (var i = 0; i < 5; i++) {
            this.ctx.lineTo(
                Math.cos(((18 + i * 72) / 180) * Math.PI) * R + x, -Math.sin(((18 + i * 72) / 180) * Math.PI) * R + y
            )
            this.ctx.lineTo(
                Math.cos(((54 + i * 72) / 180) * Math.PI) * r + x, -Math.sin(((54 + i * 72) / 180) * Math.PI) * r + y
            )
        }
        this.ctx.closePath()
        this.ctx.lineWidth = '3'
        this.ctx.fillStyle = color
        this.ctx.fill()
    }

    buildTreeCrown(startNodeNum, rowsNum, startHeight) {
        const arr = []
        const midRect = this.width / 2 - this.side / 2
        const midArc = this.width / 2
        for (let i = 0; i < rowsNum; i++) {
            for (let j = 0; j < startNodeNum; j++) {
                if (rowsNum - i === 2 && startNodeNum - j <= 2) {
                    arr.push({
                        type: 'start',
                        x: midArc + (j % 2 === 0 ? (-this.gap * j) / 2 : (+(j + 1) / 2) * this.gap),
                        y: startHeight + this.gap * i + this.side / 2,
                        color: rowsNum - i === 1 ? 'red' : 'yellow'
                    })
                } else if (rowsNum - i === 1 && startNodeNum - j <= 2) {
                    arr.push({
                        type: 'arc',
                        x: midArc + (j % 2 === 0 ? (-this.gap * j) / 2 : (+(j + 1) / 2) * this.gap),
                        y: startHeight + this.gap * i + this.side / 2,
                        color: 'red'
                    })
                } else {
                    arr.push({
                        type: 'rect',
                        x: midRect + (j % 2 === 0 ? (-this.gap * j) / 2 : (+(j + 1) / 2) * this.gap),
                        y: startHeight + this.gap * i,
                        color: i === rowsNum - 1 && startNodeNum - j >= 7 ? 'red' : 'green'
                    })
                }
            }
            if (i === rowsNum - 3) {
                startNodeNum += 4
            } else {
                startNodeNum += 2
            }
        }
        return arr
    }

    buildTreeStump(row, col, gapRow) {
        const arr = []
        const midRect = this.width / 2 - this.side / 2
        for (let i = 0; i < row; i++) {
            for (let j = 0; j < col; j++) {
                arr.push({
                    type: 'rect',
                    x: midRect + (j % 2 === 0 ? (-this.gap * j) / 2 : (+(j + 1) / 2) * this.gap),
                    y: (gapRow + i) * this.gap,
                    color: 'rgb(67, 11, 0)'
                })
            }
        }
        return arr
    }

    setTreeData() {
        const _this = this
        let gapRow = 1

        this.treeData = [{
                type: 'start',
                x: this.width / 2,
                y: this.side / 2 + 2,
                color: 'yellow'
            },
            ...setTreeCrownData(3),
            ...this.buildTreeStump(5, 3, gapRow)
        ]

        function setTreeCrownData(crownNum) {
            const arr = []
            let indexNode = 1
            let rowsNum = 4

            for (let i = 0; i < crownNum; i++) {
                arr.push(..._this.buildTreeCrown(indexNode, rowsNum, _this.gap * gapRow))
                indexNode += 2
                gapRow += rowsNum
            }
            return arr
        }
    }

    renderTree() {
        this.setTreeData()
        for (const item of this.treeData) {
            if (item.type === 'arc') {
                const { x, y, color } = item
                this.createArc(x, y, color)
            } else if (item.type === 'rect') {
                const { x, y, color } = item
                this.createRect(x, y, color)
            } else if (item.type === 'start') {
                const { x, y, color } = item
                this.createPentastar(x, y, color)
            }
        }
    }
}

唯美圣诞树

在线演示,加载比较慢

在这里插入图片描述

里边用到的音乐自己下载,修改变量const files为对应mp3的路径

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">

  <title>Musical Christmas Lights</title>

  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/5.0.0/normalize.min.css">

  <style>
    * {
      box-sizing: border-box;
    }

    body {
      margin: 0;
      height: 100vh;
      overflow: hidden;
      display: flex;
      align-items: center;
      justify-content: center;
      background: #161616;
      color: #c5a880;
      font-family: sans-serif;
    }

    label {
      display: inline-block;
      background-color: #161616;
      padding: 16px;
      border-radius: 0.3rem;
      cursor: pointer;
      margin-top: 1rem;
      width: 300px;
      border-radius: 10px;
      border: 1px solid #c5a880;
      text-align: center;
    }

    ul {
      list-style-type: none;
      padding: 0;
      margin: 0;
    }

    .btn {
      background-color: #161616;
      border-radius: 10px;
      color: #c5a880;
      border: 1px solid #c5a880;
      padding: 16px;
      width: 300px;
      margin-bottom: 16px;
      line-height: 1.5;
      cursor: pointer;
    }

    .separator {
      font-weight: bold;
      text-align: center;
      width: 300px;
      margin: 16px 0px;
      color: #a07676;
    }

    .title {
      color: #a07676;
      font-weight: bold;
      font-size: 1.25rem;
      margin-bottom: 16px;
    }

    .text-loading {
      font-size: 2rem;
    }

    #tree-text {
      position: absolute;
      top: 18vh;

      width: 100vw;
      line-height: 5vh;

      text-align: center;
      color: #fab1a0;
      font-size: x-large;
      font-family: "Lucida Console", "Courier New", monospace;
      opacity: 1;
      font-weight: bold;

      color: transparent;
      background: linear-gradient(45deg, #fab1a0 35%, #ff7675, #e17055 60%);
      background-size: cover;
      -webkit-background-clip: text;
      -ms-background-clip: text;
      -moz-background-clip: text;
      -o-background-clip: text;
    }

    @keyframes gradually-appear {
      from {
        opacity: 0;
      }

      to {
        opacity: 1;
      }
    }

    .show {
      display: block;
      animation-name: gradually-appear;
      animation-duration: 8s;
    }

    .hide {
      display: none;
    }
  </style>

  <script>
    window.console = window.console || function (t) { };
  </script>



  <script>
    if (document.location.search.match(/type=embed/gi)) {
      window.parent.postMessage("resize", "*");
    }
  </script>


</head>

<body translate="no">
  <script src="https://cdn.jsdelivr.net/npm/three@0.115.0/build/three.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/three@0.115.0/examples/js/postprocessing/EffectComposer.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/three@0.115.0/examples/js/postprocessing/RenderPass.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/three@0.115.0/examples/js/postprocessing/ShaderPass.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/three@0.115.0/examples/js/shaders/CopyShader.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/three@0.115.0/examples/js/shaders/LuminosityHighPassShader.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/three@0.115.0/examples/js/postprocessing/UnrealBloomPass.js"></script>

  <div id="overlay">
    <ul>
      <li class="title">宝贝,选一首喜欢的歌吧</li>
      <li>
        <button class="btn" id="btnA" type="button">
          Snowflakes Falling Down by Simon Panrucker
        </button>
      </li>
      <li><button class="btn" id="btnB" type="button">This Christmas by Dott</button></li>
      <li><button class="btn" id="btnC" type="button">No room at the inn by TRG Banks</button></li>
      <li><button class="btn" id="btnD" type="button">Jingle Bell Swing by Mark Smeby</button></li>
      <li  style="display: none;" class="separator">或者</li>
      <li style="display: none;">
        <input type="file" id="upload" hidden />
        <label for="upload">Upload File</label>
      </li>
    </ul>
  </div>

  <div id="tree-text" class="hide">
    祝我最爱的girl圣诞节快乐
    <br />
    希望能与你度过以后的每一个圣诞节,I ❤️ you~
  </div>

  <script id="rendered-js">
    const { PI, sin, cos } = Math;
    const TAU = 2 * PI;

    const map = (value, sMin, sMax, dMin, dMax) => {
      return dMin + (value - sMin) / (sMax - sMin) * (dMax - dMin);
    };

    const range = (n, m = 0) =>
      Array(n).
        fill(m).
        map((i, j) => i + j);

    const rand = (max, min = 0) => min + Math.random() * (max - min);
    const randInt = (max, min = 0) => Math.floor(min + Math.random() * (max - min));
    const randChoise = arr => arr[randInt(arr.length)];
    const polar = (ang, r = 1) => [r * cos(ang), r * sin(ang)];

    let scene, camera, renderer, analyser;
    let step = 0;
    const uniforms = {
      time: { type: "f", value: 0.0 },
      step: { type: "f", value: 0.0 }
    };

    const params = {
      exposure: 1,
      bloomStrength: 0.9,
      bloomThreshold: 0,
      bloomRadius: 0.5
    };

    let composer;

    const fftSize = 2048;
    const totalPoints = 4000;

    const listener = new THREE.AudioListener();

    const audio = new THREE.Audio(listener);

    document.querySelector("input").addEventListener("change", uploadAudio, false);

    const buttons = document.querySelectorAll(".btn");
    buttons.forEach((button, index) =>
      button.addEventListener("click", () => loadAudio(index)));


    function init() {
      const overlay = document.getElementById("overlay");
      overlay.remove();
      document.getElementById("tree-text").className = "show";

      scene = new THREE.Scene();
      renderer = new THREE.WebGLRenderer({ antialias: true });
      renderer.setPixelRatio(window.devicePixelRatio);
      renderer.setSize(window.innerWidth, window.innerHeight);
      document.body.appendChild(renderer.domElement);

      camera = new THREE.PerspectiveCamera(
        60,
        window.innerWidth / window.innerHeight,
        1,
        1000);

      camera.position.set(-0.09397456774197047, -2.5597086635726947, 24.420789670889008);
      camera.rotation.set(0.10443543723052419, -0.003827152981119352, 0.0004011488708739715);

      const format = renderer.capabilities.isWebGL2 ?
        THREE.RedFormat :
        THREE.LuminanceFormat;

      uniforms.tAudioData = {
        value: new THREE.DataTexture(analyser.data, fftSize / 2, 1, format)
      };


      addPlane(scene, uniforms, 3000);
      addSnow(scene, uniforms);

      range(10).map(i => {
        addTree(scene, uniforms, totalPoints, [20, 0, -20 * i]);
        addTree(scene, uniforms, totalPoints, [-20, 0, -20 * i]);
      });

      const renderScene = new THREE.RenderPass(scene, camera);

      const bloomPass = new THREE.UnrealBloomPass(
        new THREE.Vector2(window.innerWidth, window.innerHeight),
        1.5,
        0.4,
        0.85);

      bloomPass.threshold = params.bloomThreshold;
      bloomPass.strength = params.bloomStrength;
      bloomPass.radius = params.bloomRadius;

      composer = new THREE.EffectComposer(renderer);
      composer.addPass(renderScene);
      composer.addPass(bloomPass);

      addListners(camera, renderer, composer);
      animate();
    }

    function animate(time) {
      analyser.getFrequencyData();
      uniforms.tAudioData.value.needsUpdate = true;
      step = (step + 1) % 1000;
      uniforms.time.value = time;
      uniforms.step.value = step;
      composer.render();
      requestAnimationFrame(animate);
    }

    function loadAudio(i) {
      document.getElementById("overlay").innerHTML =
        '<div class="text-loading">正在下载音乐,请稍等...</div>';
      // const files = [
      //   "https://files.freemusicarchive.org/storage-freemusicarchive-org/music/no_curator/Simon_Panrucker/Happy_Christmas_You_Guys/Simon_Panrucker_-_01_-_Snowflakes_Falling_Down.mp3",
      //   "https://files.freemusicarchive.org/storage-freemusicarchive-org/music/no_curator/Dott/This_Christmas/Dott_-_01_-_This_Christmas.mp3",
      //   "https://files.freemusicarchive.org/storage-freemusicarchive-org/music/ccCommunity/TRG_Banks/TRG_Banks_Christmas_Album/TRG_Banks_-_12_-_No_room_at_the_inn.mp3",
      //   "https://files.freemusicarchive.org/storage-freemusicarchive-org/music/ccCommunity/Mark_Smeby/En_attendant_Nol/Mark_Smeby_-_07_-_Jingle_Bell_Swing.mp3"];
      const files = ["./music/Simon_Panrucker_-_01_-_Snowflakes_Falling_Down.mp3",
        "./music/Dott_-_01_-_This_Christmas.mp3",
        "./music/TRG_Banks_-_12_-_No_room_at_the_inn.mp3",
        "./music/Mark_Smeby_-_07_-_Jingle_Bell_Swing.mp3"];
      const file = files[i];

      const loader = new THREE.AudioLoader();
      loader.load(file, function (buffer) {
        audio.setBuffer(buffer);
        audio.play();
        analyser = new THREE.AudioAnalyser(audio, fftSize);
        init();
      });




    }


    function uploadAudio(event) {
      document.getElementById("overlay").innerHTML =
        '<div class="text-loading">请稍等...</div>';
      const files = event.target.files;
      const reader = new FileReader();

      reader.onload = function (file) {
        var arrayBuffer = file.target.result;

        listener.context.decodeAudioData(arrayBuffer, function (audioBuffer) {
          audio.setBuffer(audioBuffer);
          audio.play();
          analyser = new THREE.AudioAnalyser(audio, fftSize);
          init();
        });
      };

      reader.readAsArrayBuffer(files[0]);
    }

    function addTree(scene, uniforms, totalPoints, treePosition) {
      const vertexShader = `
      attribute float mIndex;
      varying vec3 vColor;
      varying float opacity;
      uniform sampler2D tAudioData;

      float norm(float value, float min, float max ){
       return (value - min) / (max - min);
      }
      float lerp(float norm, float min, float max){
       return (max - min) * norm + min;
      }

      float map(float value, float sourceMin, float sourceMax, float destMin, float destMax){
       return lerp(norm(value, sourceMin, sourceMax), destMin, destMax);
      }


      void main() {
       vColor = color;
       vec3 p = position;
       vec4 mvPosition = modelViewMatrix * vec4( p, 1.0 );
       float amplitude = texture2D( tAudioData, vec2( mIndex, 0.1 ) ).r;
       float amplitudeClamped = clamp(amplitude-0.4,0.0, 0.6 );
       float sizeMapped = map(amplitudeClamped, 0.0, 0.6, 1.0, 20.0);
       opacity = map(mvPosition.z , -200.0, 15.0, 0.0, 1.0);
       gl_PointSize = sizeMapped * ( 100.0 / -mvPosition.z );
       gl_Position = projectionMatrix * mvPosition;
      }
      `;
      const fragmentShader = `
      varying vec3 vColor;
      varying float opacity;
      uniform sampler2D pointTexture;
      void main() {
       gl_FragColor = vec4( vColor, opacity );
       gl_FragColor = gl_FragColor * texture2D( pointTexture, gl_PointCoord ); 
      }
      `;
      const shaderMaterial = new THREE.ShaderMaterial({
        uniforms: {
          ...uniforms,
          pointTexture: {
            value: new THREE.TextureLoader().load(`https://assets.codepen.io/3685267/spark1.png`)
          }
        },


        vertexShader,
        fragmentShader,
        blending: THREE.AdditiveBlending,
        depthTest: false,
        transparent: true,
        vertexColors: true
      });


      const geometry = new THREE.BufferGeometry();
      const positions = [];
      const colors = [];
      const sizes = [];
      const phases = [];
      const mIndexs = [];

      const color = new THREE.Color();

      for (let i = 0; i < totalPoints; i++) {
        const t = Math.random();
        const y = map(t, 0, 1, -8, 10);
        const ang = map(t, 0, 1, 0, 6 * TAU) + TAU / 2 * (i % 2);
        const [z, x] = polar(ang, map(t, 0, 1, 5, 0));

        const modifier = map(t, 0, 1, 1, 0);
        positions.push(x + rand(-0.3 * modifier, 0.3 * modifier));
        positions.push(y + rand(-0.3 * modifier, 0.3 * modifier));
        positions.push(z + rand(-0.3 * modifier, 0.3 * modifier));

        color.setHSL(map(i, 0, totalPoints, 1.0, 0.0), 1.0, 0.5);

        colors.push(color.r, color.g, color.b);
        phases.push(rand(1000));
        sizes.push(1);
        const mIndex = map(i, 0, totalPoints, 1.0, 0.0);
        mIndexs.push(mIndex);
      }

      geometry.setAttribute(
        "position",
        new THREE.Float32BufferAttribute(positions, 3).setUsage(
          THREE.DynamicDrawUsage));


      geometry.setAttribute("color", new THREE.Float32BufferAttribute(colors, 3));
      geometry.setAttribute("size", new THREE.Float32BufferAttribute(sizes, 1));
      geometry.setAttribute("phase", new THREE.Float32BufferAttribute(phases, 1));
      geometry.setAttribute("mIndex", new THREE.Float32BufferAttribute(mIndexs, 1));

      const tree = new THREE.Points(geometry, shaderMaterial);

      const [px, py, pz] = treePosition;

      tree.position.x = px;
      tree.position.y = py;
      tree.position.z = pz;

      scene.add(tree);
    }

    function addSnow(scene, uniforms) {
      const vertexShader = `
      attribute float size;
      attribute float phase;
      attribute float phaseSecondary;

      varying vec3 vColor;
      varying float opacity;


      uniform float time;
      uniform float step;

      float norm(float value, float min, float max ){
       return (value - min) / (max - min);
      }
      float lerp(float norm, float min, float max){
       return (max - min) * norm + min;
      }

      float map(float value, float sourceMin, float sourceMax, float destMin, float destMax){
       return lerp(norm(value, sourceMin, sourceMax), destMin, destMax);
      }
      void main() {
       float t = time* 0.0006;

       vColor = color;

       vec3 p = position;

       p.y = map(mod(phase+step, 1000.0), 0.0, 1000.0, 25.0, -8.0);

       p.x += sin(t+phase);
       p.z += sin(t+phaseSecondary);

       opacity = map(p.z, -150.0, 15.0, 0.0, 1.0);

       vec4 mvPosition = modelViewMatrix * vec4( p, 1.0 );

       gl_PointSize = size * ( 100.0 / -mvPosition.z );

       gl_Position = projectionMatrix * mvPosition;

      }
      `;

      const fragmentShader = `
      uniform sampler2D pointTexture;
      varying vec3 vColor;
      varying float opacity;

      void main() {
       gl_FragColor = vec4( vColor, opacity );
       gl_FragColor = gl_FragColor * texture2D( pointTexture, gl_PointCoord ); 
      }
      `;
      function createSnowSet(sprite) {
        const totalPoints = 300;
        const shaderMaterial = new THREE.ShaderMaterial({
          uniforms: {
            ...uniforms,
            pointTexture: {
              value: new THREE.TextureLoader().load(sprite)
            }
          },


          vertexShader,
          fragmentShader,
          blending: THREE.AdditiveBlending,
          depthTest: false,
          transparent: true,
          vertexColors: true
        });


        const geometry = new THREE.BufferGeometry();
        const positions = [];
        const colors = [];
        const sizes = [];
        const phases = [];
        const phaseSecondaries = [];

        const color = new THREE.Color();

        for (let i = 0; i < totalPoints; i++) {
          const [x, y, z] = [rand(25, -25), 0, rand(15, -150)];
          positions.push(x);
          positions.push(y);
          positions.push(z);

          color.set(randChoise(["#f1d4d4", "#f1f6f9", "#eeeeee", "#f1f1e8"]));

          colors.push(color.r, color.g, color.b);
          phases.push(rand(1000));
          phaseSecondaries.push(rand(1000));
          sizes.push(rand(4, 2));
        }

        geometry.setAttribute(
          "position",
          new THREE.Float32BufferAttribute(positions, 3));

        geometry.setAttribute("color", new THREE.Float32BufferAttribute(colors, 3));
        geometry.setAttribute("size", new THREE.Float32BufferAttribute(sizes, 1));
        geometry.setAttribute("phase", new THREE.Float32BufferAttribute(phases, 1));
        geometry.setAttribute(
          "phaseSecondary",
          new THREE.Float32BufferAttribute(phaseSecondaries, 1));


        const mesh = new THREE.Points(geometry, shaderMaterial);

        scene.add(mesh);
      }
      const sprites = [
        "https://assets.codepen.io/3685267/snowflake1.png",
        "https://assets.codepen.io/3685267/snowflake2.png",
        "https://assets.codepen.io/3685267/snowflake3.png",
        "https://assets.codepen.io/3685267/snowflake4.png",
        "https://assets.codepen.io/3685267/snowflake5.png"];

      sprites.forEach(sprite => {
        createSnowSet(sprite);
      });
    }

    function addPlane(scene, uniforms, totalPoints) {
      const vertexShader = `
      attribute float size;
      attribute vec3 customColor;
      varying vec3 vColor;

      void main() {
       vColor = customColor;
       vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
       gl_PointSize = size * ( 300.0 / -mvPosition.z );
       gl_Position = projectionMatrix * mvPosition;

      }
      `;
      const fragmentShader = `
      uniform vec3 color;
      uniform sampler2D pointTexture;
      varying vec3 vColor;

      void main() {
       gl_FragColor = vec4( vColor, 1.0 );
       gl_FragColor = gl_FragColor * texture2D( pointTexture, gl_PointCoord );

      }
      `;
      const shaderMaterial = new THREE.ShaderMaterial({
        uniforms: {
          ...uniforms,
          pointTexture: {
            value: new THREE.TextureLoader().load(`https://assets.codepen.io/3685267/spark1.png`)
          }
        },


        vertexShader,
        fragmentShader,
        blending: THREE.AdditiveBlending,
        depthTest: false,
        transparent: true,
        vertexColors: true
      });


      const geometry = new THREE.BufferGeometry();
      const positions = [];
      const colors = [];
      const sizes = [];

      const color = new THREE.Color();

      for (let i = 0; i < totalPoints; i++) {
        const [x, y, z] = [rand(-25, 25), 0, rand(-150, 15)];
        positions.push(x);
        positions.push(y);
        positions.push(z);

        color.set(randChoise(["#93abd3", "#f2f4c0", "#9ddfd3"]));

        colors.push(color.r, color.g, color.b);
        sizes.push(1);
      }

      geometry.setAttribute(
        "position",
        new THREE.Float32BufferAttribute(positions, 3).setUsage(
          THREE.DynamicDrawUsage));


      geometry.setAttribute(
        "customColor",
        new THREE.Float32BufferAttribute(colors, 3));

      geometry.setAttribute("size", new THREE.Float32BufferAttribute(sizes, 1));

      const plane = new THREE.Points(geometry, shaderMaterial);

      plane.position.y = -8;
      scene.add(plane);
    }

    function addListners(camera, renderer, composer) {
      document.addEventListener("keydown", e => {
        const { x, y, z } = camera.position;
        console.log(`camera.position.set(${x},${y},${z})`);
        const { x: a, y: b, z: c } = camera.rotation;
        console.log(`camera.rotation.set(${a},${b},${c})`);
      });

      window.addEventListener(
        "resize",
        () => {
          const width = window.innerWidth;
          const height = window.innerHeight;

          camera.aspect = width / height;
          camera.updateProjectionMatrix();

          renderer.setSize(width, height);
          composer.setSize(width, height);
        },
        false);

    }
  </script>

</body>

</html>

CSS实现圣诞树

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width= , initial-scale=1.0">
    <title>圣诞树</title>
    <!-- <link rel="stylesheet" href="index.css"> -->
    <style>
        html,
        body {
            width: 100%;
            height: 100%;
        }
        * {
            margin: 0;
            padding: 0;
        }
        body {
            background-color: #020024;
        }
        .word {
            font-size: 22px;
            text-align: center;
            color: gold;
            padding-top: 50px;
            letter-spacing: 5px;
            text-shadow: 2px 4px 9px rgba(255, 255, 255, 0.7);
        }
        /* 圣诞树外层div */
        .tree {
            width: 200px;
            height: 300px;
            margin: 80px auto 0 auto;
            position: relative;
            /*相对定位*/
            /* border: 1px solid #fff; */
        }
        .star {
            width: 50px;
            height: 50px;
            position: absolute;
            background-color: #fff;
            border-radius: 50%;
            -webkit-border-radius: 50%;
            -moz-border-radius: 50%;
            -ms-border-radius: 50%;
            -o-border-radius: 50%;
            top: -25px;
            z-index: 1000;
            left: 50%;
            transform: translate(-50%);
            -webkit-transform: translate(-50%);
            -moz-transform: translate(-50%);
            -ms-transform: translate(-50%);
            -o-transform: translate(-50%);
            animation: starLight 1.5s ease infinite alternate;
            -webkit-animation: starLight 1.5s ease infinite alternate;
        }
        .star-in {
            position: absolute;
            left: 50%;
            top: 50%;
            border-right: 100px solid transparent;
            border-bottom: 70px solid gold;
            border-left: 100px solid transparent;
            transform: translateX(-50%) translateY(-50%) rotate(35deg) scale(0.14);
            -webkit-transform: translateX(-50%) translateY(-50%) rotate(35deg) scale(0.14);
            -moz-transform: translateX(-50%) translateY(-50%) rotate(35deg) scale(0.14);
            -ms-transform: translateX(-50%) translateY(-50%) rotate(35deg) scale(0.14);
            -o-transform: translateX(-50%) translateY(-50%) rotate(35deg) scale(0.14);
        }
        .star-in::before {
            border-right: 30px solid transparent;
            border-bottom: 80px solid gold;
            border-left: 30px solid transparent;
            position: absolute;
            top: -45px;
            left: -65px;
            content: '';
            transform: rotate(-35deg);
            -webkit-transform: rotate(-35deg);
            -moz-transform: rotate(-35deg);
            -ms-transform: rotate(-35deg);
            -o-transform: rotate(-35deg);
        }
        .star-in::after {
            border-right: 100px solid transparent;
            border-bottom: 70px solid gold;
            border-left: 100px solid transparent;
            position: absolute;
            top: 3px;
            left: -105px;
            content: '';
            transform: rotate(-70deg);
            -webkit-transform: rotate(-70deg);
            -moz-transform: rotate(-70deg);
            -ms-transform: rotate(-70deg);
            -o-transform: rotate(-70deg);
        }
        @keyframes starLight {
            0% {
                background: radial-gradient(ellipse at center,
                        gold 0%,
                        rgba(255, 240, 158, 0.5)42%,
                        rgba(255, 242, 173, 0.2)58%,
                        rgba(255, 255, 255, 0.1)100%);
            }

            25% {
                background: radial-gradient(ellipse at center,
                        gold 0%,
                        rgba(255, 240, 158, 0.5)40%,
                        rgba(255, 242, 173, 0.2)60%,
                        rgba(255, 255, 255, 0.1)100%);
            }

            50% {
                background: radial-gradient(ellipse at center,
                        gold 0%,
                        rgba(255, 240, 158, 0.5)38%,
                        rgba(255, 242, 173, 0.2)62%,
                        rgba(255, 255, 255, 0.1)100%);
            }

            75% {
                background: radial-gradient(ellipse at center,
                        gold 0%,
                        rgba(255, 240, 158, 0.5)36%,
                        rgba(255, 242, 173, 0.2)64%,
                        rgba(255, 255, 255, 0.1)100%);
            }

            100% {
                background: radial-gradient(ellipse at center,
                        gold 0%,
                        rgba(255, 240, 158, 0.5)34%,
                        rgba(255, 242, 173, 0.2)66%,
                        rgba(255, 255, 255, 0.1)100%);
            }

        }
        .leaf {
            position: absolute;
            left: 50%;
            top: 3%;
            margin-left: -30px;
            background-color: rgba(14, 110, 14);
            width: 60px;
            height: 60px;
            border-radius: 0 10px 35px 10px;
            -webkit-border-radius: 0 10px 35px 10px;
            -moz-border-radius: 0 10px 35px 10px;
            -ms-border-radius: 0 10px 35px 10px;
            -o-border-radius: 0 10px 35px 10px;
            transform: rotate(45deg);
            -webkit-transform: rotate(45deg);
            -moz-transform: rotate(45deg);
            -ms-transform: rotate(45deg);
            -o-transform: rotate(45deg);
            box-shadow: 2px 7px 2px rgba(43, 43, 43, 0.2);
        }
        .edge {
            position: absolute;
            left: 0;
            bottom: 0;
            background: rgba(14, 110, 14);
            width: 25px;
            height: 30px;
            border-radius: 0 10px 35px 10px;
            -webkit-border-radius: 0 10px 35px 10px;
            -moz-border-radius: 0 10px 35px 10px;
            -ms-border-radius: 0 10px 35px 10px;
            -o-border-radius: 0 10px 35px 10px;
            transform: translateY(50%) translateX(0);
            -webkit-transform: translateY(50%) translateX(0);
            -moz-transform: translateY(50%) translateX(0);
            -ms-transform: translateY(50%) translateX(0);
            -o-transform: translateY(50%) translateX(0);
        }
        .edge.right {
            position: absolute;
            left: unset;
            bottom: unset;
            top: 0;
            right: 0;
            background: rgba(14, 110, 14);
            width: 25px;
            height: 30px;
            border-radius: 0 10px 35px 10px;
            -webkit-border-radius: 0 10px 35px 10px;
            -moz-border-radius: 0 10px 35px 10px;
            -ms-border-radius: 0 10px 35px 10px;
            -o-border-radius: 0 10px 35px 10px;
            transform: translateY(0) translateX(50%);
            -webkit-transform: translateY(0) translateX(50%);
            -moz-transform: translateY(0) translateX(50%);
            -ms-transform: translateY(0) translateX(50%);
            -o-transform: translateY(0) translateX(50%);
        }
        /* 双数修改背景颜色 */
        .leaf:nth-child(even) {
            background-color: #0f880f;
        }
        .leaf:nth-child(even) .edge {
            background-color: #0f880f;
        }
        /* 最上面 */
        .leaf:nth-child(1) {
            z-index: 100;
            transform: rotate(45deg) scale(0.8);
            -webkit-transform: rotate(45deg) scale(0.8);
            -moz-transform: rotate(45deg) scale(0.8);
            -ms-transform: rotate(45deg) scale(0.8);
            -o-transform: rotate(45deg) scale(0.8);
        }
        /* 第二 */
        .leaf:nth-child(2) {
            z-index: 99;
            top: 15%;
            transform: rotate(45deg) scale(1.3);
            -webkit-transform: rotate(45deg) scale(1.3);
            -moz-transform: rotate(45deg) scale(1.3);
            -ms-transform: rotate(45deg) scale(1.3);
            -o-transform: rotate(45deg) scale(1.3);
        }
        .leaf:nth-child(3) {
            z-index: 98;
            top: 28%;
            transform: rotate(45deg) scale(1.6);
            -webkit-transform: rotate(45deg) scale(1.6);
            -moz-transform: rotate(45deg) scale(1.6);
            -ms-transform: rotate(45deg) scale(1.6);
            -o-transform: rotate(45deg) scale(1.6);
        }
        .leaf:nth-child(4) {
            z-index: 97;
            top: 41%;
            transform: rotate(45deg) scale(1.9);
            -webkit-transform: rotate(45deg) scale(1.9);
            -moz-transform: rotate(45deg) scale(1.9);
            -ms-transform: rotate(45deg) scale(1.9);
            -o-transform: rotate(45deg) scale(1.9);
        }
        .leaf:nth-child(5) {
            z-index: 96;
            top: 54%;
            transform: rotate(45deg) scale(2.2);
            -webkit-transform: rotate(45deg) scale(2.2);
            -moz-transform: rotate(45deg) scale(2.2);
            -ms-transform: rotate(45deg) scale(2.2);
            -o-transform: rotate(45deg) scale(2.2);
        }
        .trunk {
            width: 25px;
            height: 45px;
            border-radius: 0 0 3px 3px;
            -webkit-border-radius: 0 0 3px 3px;
            -moz-border-radius: 0 0 3px 3px;
            -ms-border-radius: 0 0 3px 3px;
            -o-border-radius: 0 0 3px 3px;
            position: absolute;
            left: 50%;
            transform: translateX(-50%);
            -webkit-transform: translateX(-50%);
            -moz-transform: translateX(-50%);
            -ms-transform: translateX(-50%);
            -o-transform: translateX(-50%);
            bottom: 20px;
            z-index: 1;
            box-shadow: 0 0 10px 5px rgb(19, 19, 19);
            background: linear-gradient(0deg, #6d411b 0%, #5a341d 64%);
        }
        .ball {
            width: 20px;
            height: 20px;
            background: #f00;
            box-shadow: -1px -1px 6px inset #600, 1px 1px 8px inset #ffc9c9;
            border-radius: 50%;
            -webkit-border-radius: 50%;
            -moz-border-radius: 50%;
            -ms-border-radius: 50%;
            -o-border-radius: 50%;
            z-index: 101;
            position: absolute;
        }
        .b1 {
            left: 25%;
            top: 30%;
        }
        .b2 {
            left: 35%;
            top: 50%;
        }
        .b3 {
            left: 65%;
            top: 20%;
        }
        .b4 {
            left: 45%;
            top: 22%;
        }
        .b5 {
            left: 40%;
            top: 72%;
        }
        .b6 {
            left: 60%;
            top: 52%;
        }
        .b7 {
            left: 50%;
            top: 62%;
        }
        .b8 {
            left: 80%;
            top: 42%;
        }
        .b9 {
            left: 10%;
            top: 62%;
        }
        .b4,
        .b5,
        .b6 {
            background: #ececec;
            box-shadow: -1px -1px 6px inset #615f5f, 1px 1px 8px inset #fff;
        }
        .b7,
        .b8,
        .b9 {
            background: gold;
            box-shadow: -1px -1px 6px inset #3a3101, 1px 1px 8px inset #fff;
        }
        .sparkle span {
            display: block;
            position: absolute;
            font-size: 20px;
            z-index: 101;
            color: #fff;
            animation: lights 1.5s ease infinite alternate;
            -webkit-animation: lights 1.5s ease infinite alternate;
        }
        /* 闪烁动画 */
        @keyframes lights {

            0%,
            100% {
                transform: scale(1);
                -webkit-transform: scale(1);
                -moz-transform: scale(1);
                -ms-transform: scale(1);
                -o-transform: scale(1);
            }

            50% {
                transform: scale(1.5);
                -webkit-transform: scale(1.5);
                -moz-transform: scale(1.5);
                -ms-transform: scale(1.5);
                -o-transform: scale(1.5);
            }
        }
        .sparkle span:nth-child(1) {
            left: 30%;
            top: 40%;
        }
        .sparkle span:nth-child(2) {
            left: 40%;
            top: 27%;
            font-size: 15px;
        }
        .sparkle span:nth-child(3) {
            left: 50%;
            top: 57%;
            font-size: 12px;
        }
        .sparkle span:nth-child(4) {
            left: 70%;
            top: 67%;
            font-size: 14px;
        }
        .sparkle span:nth-child(5) {
            left: 74%;
            top: 13%;
            font-size: 16px;
        }
        .blink div {
            width: 3px;
            height: 3px;
            background: #fff;
            z-index: 101;
            position: absolute;
            border-radius: 50%;
            -webkit-border-radius: 50%;
            -moz-border-radius: 50%;
            -ms-border-radius: 50%;
            -o-border-radius: 50%;
            animation: blink 1.5s ease infinite alternate;
            -webkit-animation: blink 1.5s ease infinite alternate;
        }
        .blink div:nth-child(2) {
            left: 34%;
            top: 13%;
            transform: scale(1.2);
            -webkit-transform: scale(1.2);
            -moz-transform: scale(1.2);
            -ms-transform: scale(1.2);
            -o-transform: scale(1.2);
        }
        .blink div:nth-child(3) {
            left: 54%;
            top: 43%;
            transform: scale(0.6);
            -webkit-transform: scale(0.6);
            -moz-transform: scale(0.6);
            -ms-transform: scale(0.6);
            -o-transform: scale(0.6);
        }
        .blink div:nth-child(4) {
            left: 64%;
            top: 33%;
            transform: scale(1.4);
            -webkit-transform: scale(1.4);
            -moz-transform: scale(1.4);
            -ms-transform: scale(1.4);
            -o-transform: scale(1.4);
        }
        .blink div:nth-child(5) {
            left: 34%;
            top: 63%;
            transform: scale(1.8);
            -webkit-transform: scale(1.8);
            -moz-transform: scale(1.8);
            -ms-transform: scale(1.8);
            -o-transform: scale(1.8);
        }
        .blink div:nth-child(6) {
            left: 14%;
            top: 76%;
            transform: scale(1.5);
            -webkit-transform: scale(1.5);
            -moz-transform: scale(1.5);
            -ms-transform: scale(1.5);
            -o-transform: scale(1.5);
        }
        @keyframes blink {
            0% {
                box-shadow: 0 0 0 0 #fff;
            }

            25% {
                box-shadow: 0 0 1px 1px #fff;
            }

            50% {
                box-shadow: 0 0 2px 2px #fff;
            }

            75% {
                box-shadow: 0 0 3px 3px #fff;
            }

            100% {
                box-shadow: 0 0 4px 4px #fff;
            }
        }

        .yy {
            position: absolute;
            top: 80%;
            right: 0%;
        }
    </style>

</head>

<body>
    <p class="word">
        圣诞树
    </p>
    <div class="tree">
        <div class="star">
            <div class="star-in"></div>
        </div>
        <!-- 树叶 -->
        <div class="leaf-box">
            <div class="leaf">
                <div class="edge"></div>
                <div class="edge right"></div>
            </div>
            <div class="leaf">
                <div class="edge"></div>
                <div class="edge right"></div>
            </div>
            <div class="leaf">
                <div class="edge"></div>
                <div class="edge right"></div>
            </div>
            <div class="leaf">
                <div class="edge"></div>
                <div class="edge right"></div>
            </div>
            <div class="leaf">
                <div class="edge"></div>
                <div class="edge right"></div>
            </div>
        </div>
        <!-- 树干 -->
        <div class="trunk"></div>
        <!-- 彩色的球 -->
        <div class="ball-box">
            <div class="ball b1"></div>
            <div class="ball b2"></div>
            <div class="ball b3"></div>
            <div class="ball b4"></div>
            <div class="ball b5"></div>
            <div class="ball b6"></div>
            <div class="ball b7"></div>
            <div class="ball b8"></div>
            <div class="ball b9"></div>
        </div>
        <!-- 闪烁 -->
        <div class="sparkle">
            <span></span>
            <span></span>
            <span></span>
            <span></span>
            <span></span>
            <span></span>
        </div>
        <div class="blink">
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
        </div>
    </div>

    <div class="yy">
        <iframe frameborder="no" border="0" marginwidth="0" marginheight="0" width=330 height=86
            src="https://music.163.com/outchain/player?type=2&id=359109&auto=1&height=66"></iframe>
    </div>
</body>
</html>

简易的圣诞树

在这里插入图片描述

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-status-bar-style" content="black">
    <title>鱼找水的圣诞树</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.0"></script>
    <style type="text/css">
        body{
            background-color: #020024;
        }
        #app{
            display:flex;
            justify-content:center;
            height: 100vh;
        }
        .shendanshu {
            display: flex;
            justify-content: center;
            width: 1000px;
            max-width: 100vw;
            flex-direction: column;
            align-items: center;
        }

        .shuceng {
            display: flex;
            flex-direction: row;
            overflow: hidden;
            justify-content: center;
        }

        .shuye {
            position: relative;
            height: 46px;
        }

        .ye {
            width: 0;
            height: 0;
            border: 30px solid;
            border-color: transparent transparent green;
            border-top-width: 6px;
        }

        .caideng {
            position: absolute;
            bottom: 0px;
            left: 22px;
            width: 16px;
            height: 16px;
            background: red;
            border-radius: 40px;
            animation: dengguangxiaoguo 1s linear infinite alternate;
        }
        .caideng1{
            animation-delay:-0.25s;
        }
        .caideng2{
            animation-delay:-0.5s;
        }
        .caideng3{
            animation-delay:-0.75s;
        }

        .shugan {
            background-color: #795548;
            height: 60px;
            width: 100px;
        }

        .tudi {
            background: #FFC107;
            height: 20px;
            width: 500px;
            max-width: 80vw;
            border-radius: 20px 20px 0px 0px;
        }

        @keyframes dengguangxiaoguo {
            0% {
                background-color: #fff;
            }

            25% {
                background-color: blue;
            }

            50% {
                background-color: red;
            }

            75% {
                background-color: yellow;
            }

            100% {
                background-color: #fff;
            }
        }
    </style>
</head>
<body>
    <div id="app">
        <!-- 圣诞树 -->
        <div class="shendanshu">
            <!-- 树叶区域 -->
            <div class="shuceng" v-for="arr_shuye in arr_shengdanshu">
                <div class="shuye" v-for="shuye in arr_shuye">
                    <div class="ye"></div>
                    <div class="caideng" v-bind:class="shuye.caideng"></div>
                </div>
            </div>
            <!-- 树干 -->
            <div class="shugan"></div>
            <!-- 土地 -->
            <div class="tudi">
                <a style="width:100%;text-align:center;display: inline-block;" href="https://github.com/mengmeng1009/shengdanshu"></a>
            </div>
        </div>
    </div>
    <script>
        var app = new Vue({
            el: '#app',
            data: {
                arr_shengdanshu: []
            },
            created: function () {
                for (let i = 0; i < 9; i++) {
                    let arr_shuye = [];
                    for (let j = 0; j < i + 1; j++) {
                        let shuye = { js: j, caideng: "caideng" + Math.ceil(Math.random() * 4) }
                        arr_shuye.push(shuye)
                    }
                    this.arr_shengdanshu.push(arr_shuye)
                }
            }
        })
    </script>
</body>
</html>

线性树

在这里插入图片描述

<!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">
    <title>🎄</title>
    <script type='text/javascript'>
      onload = function() {
        var click_cnt = 0;
        var $html = document.getElementsByTagName("html")[0];
        var $body = document.getElementsByTagName("body")[0];
        $html.onclick = function(e) {
          var $elem = document.createElement("b");
          $elem.style.color = "#E94F06";
          $elem.style.zIndex = 9999;
          $elem.style.position = "absolute";
          $elem.style.select = "none";
          var x = e.pageX;
          var y = e.pageY;
          $elem.style.left = (x - 10) + "px";
          $elem.style.top = (y - 20) + "px";
          clearInterval(anim);
          switch (++click_cnt) {
            case 10:
              $elem.innerText = "OωO";
              break;
            case 20:
              $elem.innerText = "(๑•́ ∀ •̀๑)";
              break;
            case 30:
              $elem.innerText = "(๑•́ ₃ •̀๑)";
              break;
            case 40:
              $elem.innerText = "(๑•̀_•́๑)";
              break;
            case 50:
              $elem.innerText = "( ̄へ ̄)";
              break;
            case 60:
              $elem.innerText = "(╯°口°)╯(┴—┴";
              break;
            case 70:
              $elem.innerText = "૮( ᵒ̌皿ᵒ̌ )ა";
              break;
            case 80:
              $elem.innerText = "╮(。>口<。)╭";
              break;
            case 90:
              $elem.innerText = "( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃";
              break;
            case 100:
            case 101:
            case 102:
            case 103:
            case 104:
            case 105:
              $elem.innerText = "(ꐦ°᷄д°᷅)";
              break;
            default:
              $elem.innerText = "❤";
              break;
          }
          $elem.style.fontSize = Math.random() * 10 + 8 + "px";
          var increase = 0;
          var anim;
          setTimeout(function() {
            anim = setInterval(function() {
              if (++increase == 150) {
                clearInterval(anim);
                $body.removeChild($elem);
              }
              $elem.style.top = y - 20 - increase + "px";
              $elem.style.opacity = (150 - increase) / 120;
            }, 8);
          }, 70);
          $body.appendChild($elem);
        };
      };

    </script>
    <style>
        * {
            padding: 0;
            margin: 0;
            list-style: none;
        }

        body {
            display: flex;
            height: 100vh;
            justify-content: center;
            align-items: center;
            background-color: rgb(54, 66, 70);
        }

        .tree {
            position: relative;
            width: 500px;
            height: 700px;
            display: flex;
            justify-content: center;
        }
        /*绘制星星*/
        .star {
            width: 50px;
            height: 50px;
            position: absolute;
            background-color: rgb(236, 234, 167);
            z-index: 999;
            clip-path: polygon(50% 0, 65% 40%, 100% 40%, 72% 60%,
                    85% 100%, 50% 75%, 15% 100%, 28% 60%, 0 40%, 35% 40%);
        }
        .tree li{
            position: absolute;
            top: 25px;
            width: 2px;
            /*颜色渐变*/
            background: linear-gradient(rgba(46,204,113,0),rgba(46,204,113,.25));
            transform-origin: 0 0;
            /*按照规定的动画 4秒内播放完毕 低速开始和结束 无限次播放*/
            animation: swing 10s ease-in-out infinite;
            height: calc(var(--i)*4px);
            /*动画开始前的等待时间*/
            animation-delay:calc(var(--i)*-0.23s);
        }

        @keyframes swing{
            0%,
            100%{
                transform: rotate(-30deg);
            }
            0%{
                opacity: 1;
            }
            5%,45%{
                opacity: 0.25;
            }
            50%,100%{
                opacity: 1;
            }
            50%{
                transform: rotate(30deg);
            }
        }
        .tree li::before{
            content: '';
            font-size: 1px;
            position: absolute;
            left: -1px;
            bottom: 1px;
            width: 3px;
            height: 3px;
        }
        .tree li:nth-child(4n)::before{
            background-color: #D8334A;
            color: #D8334A;
        }
        .tree li:nth-child(4n+1)::before{
            background-color: #FFCE54;
            color: #FFCE54
        }
        .tree li:nth-child(4n+2)::before{
            background-color: #2ECC71;
            color: #2ECC71
        }
        .tree li:nth-child(4n+3)::before{
            background-color: #5D9CEC;
            color: #5D9CEC
        }


    </style>
</head>

<body>
    <ul class="tree">
        <div class="star"></div>
    </ul>
</body>
<script>
    let tree = document.querySelector('.tree')
    for (let i = 0; i < 128; i++) {
        let li = document.createElement('li')
        li.style = "--i:" + i
        tree.appendChild(li)
    }
</script>
</html>

卡片圣诞树

在这里插入图片描述

这个代码文件比较多,就不贴了。有需要的可以评论私聊,以后会上传到资源


到此,本章内容就介绍完啦,如果有帮助到你 欢迎点个赞👍👍吧!!您的鼓励是博主的最大动力! 有问题评论区交流。

转载请注明出处或者链接地址:https://www.qianduange.cn//article/774.html
标签
评论
会员中心 联系我 留言建议 回顶部
复制成功!