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

news2024/12/23 16:00:46

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

圣诞节的起源

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

在这里插入图片描述

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

在这里插入图片描述

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

用 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>

卡片圣诞树

在这里插入图片描述

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


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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/59209.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

DenseNet的基本思想

之前的文章介绍过残差网络的基本思想&#xff1a;残差网络的思想就是将网络学习的映射从X到Y转为学习从X到Y-X的差&#xff0c;然后把学习到的残差信息加到原来的输出上即可。即便在某些极端情况下&#xff0c;这个残差为0&#xff0c;那么网络就是一个X到Y的恒等映射。其示意图…

Java基础类型和运算符

文章目录变量与常量变量的命名规则常量final 关键字修饰的常量字面常量基本类型整型基本整型变量 int长整型 long短整型 short比特型 byte浮点数 float和double关于3*0.10.3三种特殊的double字符型 char布尔类型 boolean类型转换隐式类型提升强制类型转换运算符算数运算符基本四…

vue中打印插件vue-print-nb(二)-实例之两种方法——安包之设置一个id和绑定一个对象 下载print.js之ref设置锚点

vue中打印插件vue-print-nb(二)-实例之两种方法——安包之设置一个id和绑定一个对象 & 下载print.js之ref设置锚点 第一种方法 方式1、设置一个id ① 给要打印的部分设置一个 id ② 在打印按钮中添加 v-print"#id名" 1、安装vue-print-nb插件 npm install v…

Firefly RK3399 PC pro Android 10下载验证

一.Android 源码以及image 1.Android 10代码链接&#xff1a; 百度网盘 请输入提取码 密码&#xff1a;1234 下载后检查md5值&#xff0c;检查下载是否正确&#xff1a; fb41fcdc48b1cf90ecac4a5bb8fafc7a Firefly-RK3399_Android10.0_git_20211222.7z.001 82d665fb54fb412…

Flutter ー Authentication 认证

Flutter ー Authentication 认证 原文 https://medium.com/simbu/flutter-authentication-adb8df7cf673 前言 如果我相信我知道你是谁那我就能让你查看你的个人 应用 application 资料。 身份验证可能是应用程序必须处理的最大的交叉问题。 将它作为一个特性添加到 DigestableP…

HashMap JDK1.7与1.8的区别

结构 首先HashMap在1.7中是以数组链表的形式存在的, 而HashMap在1.8中则是以数组链表红黑树构成的, 当一个节点的链表长度超过8并且数组长度超过64时会将链表转换为红黑树, 初始化 初始容量大小介绍 说到数组就不得不提HashMap里面的成员变量DEFAULT_INITIAL_CAPACITY也就是…

Mysql进阶学习(八)DDL语言+数据类型和DTL语言

Mysql进阶学习&#xff08;八&#xff09;DDL语言与DTL语言DDL语言1、简介&#xff1a;1.1、库的管理1.1.1、库的创建1.1.2、库的修改1.1.3、库的删除1.2、表的管理1.2.1.表的创建 ★1.2.2.表的修改1.2.3.表的删除1.2.4.表的复制测试案例1. 创建表dept12. 将表departments中的数…

SpringBoot_整合Thymeleaff模板引擎

Thymeleaf模板引擎的主要目标是将优雅的自然模板带到开发工作流程中&#xff0c;并将HTML在浏览器中正确显示&#xff0c;并且可以作为静态原型&#xff0c;让开发团队能更容易地协作。Thymeleaf能够处理HTML&#xff0c;XML&#xff0c;JavaScript&#xff0c;CSS甚至纯文本。…

Qt扫盲-Qt Designer 设计师使用总结

Designer 设计师使用总结一、顶部菜单栏1. 常用的菜单内容2. 快捷工具栏说明二、左侧控件栏1. 组件分类2. 筛选三、中间绘图区1. 左侧控件区拖放控件到中间2. 中间区域布局3. 属性修改四、右侧属性栏1. 对象查看器2. 属性编辑器3.组织结构2. 属性设置五、美化专栏1.单个设置层叠…

微服务框架 SpringCloud微服务架构 12 DockerCompose 12.2 部署微服务集群

微服务框架 【SpringCloudRabbitMQDockerRedis搜索分布式&#xff0c;系统详解springcloud微服务技术栈课程|黑马程序员Java微服务】 SpringCloud微服务架构 文章目录微服务框架SpringCloud微服务架构12 DockerCompose12.2 部署微服务集群12.2.1 直接开干12 DockerCompose 1…

大数据:Hive简介及核心概念

一、简介 Hive 是一个构建在 Hadoop 之上的数据仓库&#xff0c;它可以将结构化的数据文件映射成表&#xff0c;并提供类 SQL 查询功能&#xff0c;用于查询的 SQL 语句会被转化为 MapReduce 作业&#xff0c;然后提交到 Hadoop 上运行。 特点&#xff1a; 简单、容易上手 (…

做短视频不知道靠什么变现,分享三个自我商业定位的方法,适用普通人

如果说你还停留在我也不知道我可以靠什么赚钱这样的一个状态当中。那我给你三个自我商业定位的方法。篇幅较长&#xff0c;点赞收藏慢慢看哦 首先第一个方法&#xff0c;从工作上或者专业的事情上找变现的方法。 那么你们需要了解一个概念叫做知识的诅咒。什么意思呢&#xf…

【论文整理1】On the Continuity of Rotation Representations in Neural Networks

1.前置知识 1.1 Gram-Schmidt正交化 【参考阅读】Gram-Schmidt过程 看完这篇应该基本能理解&#xff0c;但是他对于公式的讲解有一个地方讲解得不是很清楚! 即为什么分母是平方形式呢&#xff1f; 1.2 差集 定义&#xff1a;差集是一种集合运算&#xff0c;记A&#xff0…

Java并发编程—CompletableFuture的介绍和使用

在博主上一篇博客介绍中&#xff0c;Java并发编程—java异步Future的迭代过程_小魏快起床的博客-CSDN博客&#xff0c;这里面给大家分析了Future的使用过程和一些存在的问题&#xff0c;那么针对里面出现的阻塞问题&#xff0c;博主将在这一篇文章给大家介绍清楚 &#x1f34f…

MyBatis框架简介

MyBatis是一个开源的数据持久层框架&#xff0c;内部封装了通过JDBC访问数据库的操作&#xff0c;支持普通的SQL查询、存储过程和高级映射。作为持久层框架&#xff0c;主要思想是将程序中的大量的SQL语句分离出来&#xff0c;配置在相应的配置文件中&#xff0c;这样可以在不修…

Java—数据类型

文章目录数据类型八大基本数据类型Java中有了基本数据类型&#xff0c;为什么还要包装类型String字符串类型函数字符串类的length()方式是否能够得到字符串内有多少个字符&#xff1f;不可变字符串String为什么要设计成不可变的&#xff1f;boolean类型占多少位&#xff1f;为什…

【springboot进阶】使用aop + 注解方式,简单实现spring cache功能

目录 一、实现思路 二、定义缓存注解 三、aop 切面处理 四、使用方式 五、灵活的运用 六、总结 前几天有同学看了 SpringBoot整合RedisTemplate配置多个redis库 这篇文章&#xff0c;提问spring cache 能不能也动态配置多个redis库。介于笔者没怎么接触过&#xff0c;所以…

【Java开发】 Spring 08 :访问 Web 资源( 借助 RestTemplate or WebClient )

web 资源就是运行在服务器上的资源&#xff0c;比如放到 web 下的页面 js 文件、图片、css等&#xff0c;web资源分为静态web资源和动态web资源两类&#xff0c;接下来访问的就是动态资源&#xff08;页面返回的数据是动态的&#xff0c;由后端程序产生&#xff09;&#xff0…

Android 使用元数据

Android 使用元数据 前提介绍Metadata 有时候为安全起见&#xff0c;某个参数要给某个活动专用&#xff0c;并不希望其他活动也能获取该参数&#xff0c;也就是要使用第三方SDK时。Activity提供了元数据&#xff08;Metadata&#xff09;的概念&#xff0c;元数据是一种描述其…

C++类和对象(二)构造函数、析构函数、拷贝构造函数

目录 1.类的6个默认成员函数 2. 构造函数 2.1 概念 2.2 特性 3.析构函数 3.1 概念 3.2 特性 4. 拷贝构造函数 4.1 概念 4.2 特征 1.类的6个默认成员函数 如果一个类中什么成员都没有&#xff0c;简称为空类。 空类中真的什么都没有吗&#xff1f;并不是&#xff0c;…