CSS firework special effects (less) (template vue3, understand the life cycle and change it at will)

Effect:

 

code:

<script setup>
import { onMounted, onUnmounted, ref } from "vue";
let num = 0;
const show = ref(true)

let arr1 = new Array(120);
arr1.fill("12");

function getMousePosition(event) {
    var x = 0;
    var y = 0;
    var doc = document.documentElement;
    var body = document.body;
    if(!event) event=window.event;
    if (window.pageYoffset) {//pageYoffset是Netscape特有
        x = window.pageXOffset;
        y = window.pageYOffset;
    }else{
        x = (doc && doc.scrollLeft || body && body.scrollLeft || 0)
          - (doc && doc.clientLeft || body && body.clientLeft || 0);
        y = (doc && doc.scrollTop  || body && body.scrollTop  || 0)
          - (doc && doc.clientTop  || body && body.clientTop  || 0);
    }
    x += event.clientX;
    y += event.clientY;
    return {'x' : x, 'y' : y};
};
const createFire = ({x,y})=>{
  var firePage = document.getElementById('firePage');
  let newFire = document.createElement('div');
  newFire.className = "fireOrigin";
  newFire.id = `fireOrigin_${num}`;
  newFire.style.left = `${x}px`;
  newFire.style.top = `${y}px`;
  newFire.style.transform = 'translate(-50% , -50%)';
  newFire.style.position = "absolute";
  newFire.style.margin = "0";
  let html = ''
  for (let i = 0; i < arr1.length; i++) {
    html = html + `<div class="fireItem fireItem_${i%6}">
        <div class="fireItem1 fireItemTail"></div>
        <div class="fireItem2 fireItemTail"></div>
      </div>`
  }
  newFire.innerHTML = html
  firePage.appendChild(newFire);
  const numberStr = num
  setTimeout(()=>{
    console.log(`fireOrigin_${numberStr}`);
    let removeChild = document.getElementById(`fireOrigin_${numberStr}`);
    firePage.removeChild(removeChild)
  },3500)
  num++
  console.log(num,x,y);
};
onMounted(() => {
  document.addEventListener('click',(e)=>{
    const obj = getMousePosition(e)
    createFire(obj)
  })
});
onUnmounted(()=>{
  document.removeEventListener('click',(e)=>{
    const obj = getMousePosition(e)
    createFire(obj)
  })
})
</script>

<template>
  <div class="firePage" id="firePage">
    <div class="fireOrigin" id="fireOrigin">
      <div
        v-for="(item, index) in arr1"
        :class="'fireItem_' + (index % 6)"
        :key="index"
        class="fireItem"
      >
        <div class="fireItem1 fireItemTail"></div>
        <div class="fireItem2 fireItemTail"></div>
      </div>
    </div>
  </div>
</template>
<style lang="less">
.firePage {
  width: 100%;
  height: 100vh;
  min-height: 400px;
  min-width: 400px;
  background: #000;
  border: 1px solid transparent;
  position: relative;
  .fireOrigin {
    width: 400px;
    height: 400px;
    margin: 50px auto;
    position: relative;
    @fireBack: rgba(255, 0, 0, 1);
    @fireBack1: rgba(255, 0, 0, 0.5);
    @fireBack2: rgba(255, 0, 0, 0.3);
    @fireBack3: rgba(255, 0, 0, 0);

    @time: 3s;
    .fireItem {
      position: absolute;
      width: 200px;
      height: 1px;
      background: transparent;
      top: 50%;
      left: 50%;
      transform-origin: left;
      z-index: 1;
      .fireItem1 {
        width: 0px;
        // width: 10px;
        // height: 10px;
        height: 1px;
        border-radius: 50% 0 50% 0;
        background: @fireBack;
        position: absolute;
        z-index: 2;
        left: 0px;
        top: 50%;
        transform: rotate(45deg) translateY(-50%);
        animation: fireX1 @time
          linear(0 0%, 0.9 64.68%, 0.95 70.53%, 0.98 79.68%, 1 88.97%, 1 100%);
      }
      .fireItem2 {
        // width: 1px;
        width: 0px;
        height: 1px;
        border-radius: 50% 0 50% 0;
        background: @fireBack;
        position: absolute;
        z-index: 2;
        left: 0px;
        top: 50%;
        transform: rotate(45deg) translateY(-50%);
        animation: fireX2 @time
          linear(0 0%, 0.9 64.68%, 0.95 70.53%, 0.98 79.68%, 1 88.97%, 1 100%);
      }
      .fireItemTail {
        &::after {
          content: "";
          position: absolute;
          left: 0;
          top: 0;
          transform: translate(-90%, 0%) rotate(-45deg);
          clip-path: polygon(
            0 60%,
            0 40%,
            30% 10%,
            50% 0%,
            100% 10%,
            100% 90%,
            50% 100%,
            30% 90%
          );
          // width: 50px;
          width: 0px;
          height: 10px;
          transform-origin: right center;
          background: linear-gradient(
            to left,
            @fireBack1 0%,
            @fireBack2 50%,
            @fireBack3 100%
          );
          animation: tail @time linear;
        }
        @keyframes tail {
          0% {
            width: 0px;
            height: 1px;
          }
          100% {
            width: 50px;
            height: 10px;
          }
        }
      }
      @keyframes fireX1 {
        0% {
          left: 0px;
          width: 1px;
          height: 1px;
          opacity: 0.7;
          box-shadow: 0px 0px 0px @fireBack;
        }
        30% {
          opacity: 0.9;
        }
        50% {
          opacity: 1;
          box-shadow: 0px 0px 30px @fireBack;
        }
        70% {
          opacity: 1;
        }
        80% {
          opacity: 0.7;
        }
        90% {
          opacity: 0.9;
        }
        100% {
          left: 100%;
          width: 10px;
          height: 10px;
          opacity: 0;
          box-shadow: 0px 0px 40px @fireBack;
        }
      }
      @keyframes fireX2 {
        0% {
          left: 0px;
          width: 1px;
          height: 1px;
          opacity: 0.7;
          box-shadow: 0px 0px 0px @fireBack;
        }
        30% {
          opacity: 0.9;
        }
        50% {
          opacity: 1;
          box-shadow: 0px 0px 30px @fireBack;
        }
        70% {
          opacity: 1;
        }
        80% {
          opacity: 0.7;
        }
        90% {
          opacity: 0.9;
        }
        100% {
          left: 90%;
          width: 10px;
          height: 10px;
          opacity: 0;
          box-shadow: 0px 0px 40px @fireBack;
        }
      }
      // transform: translate(-50%,-50%);
    }
    .fireItem_0 {
      .fireItem1 {
        animation-delay: 0s;
      }
      .fireItem2 {
        animation-delay: @time / 4; // 0.75
      }
    }
    .fireItem_1 {
      .fireItem1 {
        animation-delay: @time / 12; // 0.25
      }
      .fireItem2 {
        animation-delay: @time / 3; // 1
      }
    }
    .fireItem_2 {
      .fireItem1 {
        animation-delay: @time / 6; // 0.5
      }
      .fireItem2 {
        animation-delay: @time / 2.4; // 1.25
      }
    }
    .fireItem_3 {
      .fireItem1 {
        animation-delay: @time / 12;
      }
      .fireItem2 {
        animation-delay: @time / 3;
      }
    }
    .fireItem_4 {
      .fireItem1 {
        animation-delay: 0s;
      }
      .fireItem2 {
        animation-delay: @time / 4;
      }
    }
    .fireItem_5 {
      .fireItem1 {
        animation-delay: @time / 6;
      }
      .fireItem2 {
        animation-delay: @time / 2.4;
      }
    }
    .generate-z-index(@n, @i: 1) when (@i =< @n) {
      @deg: 360deg / @n;
      .fireItem:nth-child(@{i}) {
        z-index: (200-@i);
        transform: rotate(@deg * (@i));
        -ms-transform: rotate(@deg * (@i)); /* Internet Explorer */
        -moz-transform: rotate(@deg * (@i)); /* Firefox */
        -webkit-transform: rotate(@deg * (@i)); /* Safari 和 Chrome */
        -o-transform: rotate(@deg * (@i)); /* Opera */
        .fireItem1 {
        }
      }
      .generate-z-index(@n, (@i + 1));
    }
    .generate-z-index(120);
  }
}
</style>

 

Guess you like

Origin blog.csdn.net/qq_48959246/article/details/130723965