过年了,你有多久没有放鞭炮了呢?

简介: 过年了,你有多久没有放鞭炮了呢?

过年了,一起来放鞭炮吗?

提前祝大家新年快乐呀,不知道大家有没有这样的感觉,为什么越长大,越觉得过年没有了年味?回想小时候和小伙伴们一起拿着鞭炮到田里看到什么炸什么的日子,还真是遥远,现在是无法在像一起那样了,那么就在网上来一起放鞭炮吧!

预览

实现

一、vue实现

template
<template>
  <div id="app">
    <div class="firecrackers">
      <div class="Stick"></div>
      <div class="line">
        <div v-for="n in crackerNum" :key="n" class="cracker"></div>
        <div class="fire" v-for="n in 10" :key="n"></div>
        <audio
          src="./assets/鞭炮声.mp3"
          controls="controls"
          preload
          id="music"
          hidden
        ></audio>
      </div>
    </div>
    <div class="play" @click="play()">点炮竹</div>
  </div>
</template>
script
初始化鞭炮的样式

初始化鞭炮的样式,让鞭炮左右倾斜排布。

//初始化炮竹
initCrackers() {
    let crackers = document.getElementsByClassName("cracker");
    let num = 0;
    let j = 0;
    while (crackers.length > j) {
        for (let i = 0; i < 2; ++i) {
            let cracker = crackers[j];
            j++;
            cracker.style.top = num * this.crackerHeight + "px";
            if (j % 2 == 0) {
                cracker.style.transform = "rotate(30deg)";
                cracker.style.left = "-5px";
            } else {
                cracker.style.transform = "rotate(-30deg)";
            }
        }
        num++;
    }
},
初始化火花

初始化火花,生成一定范围内随机排布的火花

//初始化火花
initFires() {
    let fires = document.getElementsByClassName("fire");
    for (let i = 0; i < fires.length; i++) {
        fires[i].style.top =
            this.crackerHeight * (this.crackerNum / 2) +
            parseFloat(this.getRandom(2)) +
            "px";
        fires[i].style.left = parseFloat(this.getRandom(10)) + "px";
    }
},
    getRandom(n) {
        let r = Math.random() * n;
        let flag = Math.random();
        if (flag > 0.5) return -r;
        return r;
    },
},
点燃鞭炮

点击燃烧鞭炮,添加飘落效果和鞭炮声

//点炮竹
play(len = "") {
    let crackers = document.getElementsByClassName("cracker");
    let fires = document.getElementsByClassName("fire");
    let audio = document.getElementById("music");
    if (audio.paused) {
        audio.play(); // 播放
    }
    if (len == "") len = crackers.length - 1;
    crackers[len].classList.add("to-smoke");
    crackers[len - 1].classList.add("to-smoke");
    setTimeout(() => {
        crackers[len].remove();
        crackers[len - 1].remove();
    }, 5000);
    for (let i = 0; i < fires.length; i++) {
        fires[i].style.display = "block";
        fires[i].style.top =
            parseInt(fires[i].style.top) - this.crackerHeight + "px";
    }
    setTimeout(() => {
        if (len - 2 >= 0) {
            this.play(len - 2);
        } else {
            for (let i = fires.length - 1; i >= 0; i--) {
                fires[i].remove();
                audio.pause();
            }
        }
    }, this.speed);
},
css
粒子闪烁动画简单模拟火花
@keyframes fireAni {
    0% {
        opacity: 0;
    }
    50% {
        opacity: 1;
    }
    100% {
        opacity: 0;
    }
}
鞭炮燃烧后飘落效果
@keyframes smoky {
    to {
        background-color: whitesmoke;
        transform: translate3d(200px, 80px, 0) rotate(-40deg) skewX(70deg)
            scale(1.5);
        text-shadow: 0 0 20px whitesmoke;
        opacity: 0;
    }
}
• 1
• 2
• 3
• 4
• 5
• 6
• 7
• 8
• 9
完整代码
<template>
  <div id="app">
    <div class="firecrackers">
      <div class="Stick"></div>
      <div class="line">
        <div v-for="n in crackerNum" :key="n" class="cracker"></div>
        <div class="fire" v-for="n in 10" :key="n"></div>
        <audio
          src="./assets/鞭炮声.mp3"
          controls="controls"
          preload
          id="music"
          hidden
        ></audio>
      </div>
    </div>
    <div class="play" @click="play()">点炮竹</div>
  </div>
</template>
<script>
export default {
  name: "app",
  components: {},
  data() {
    return {
      crackerHeight: 12, //炮竹高度
      speed: 200, //燃烧速度ms
      crackerNum: 80, //炮竹数量
    };
  },
  methods: {
    init() {
      this.initCrackers();
      this.initFires();
      this.initLine();
    },
    //点炮竹
    play(len = "") {
      let crackers = document.getElementsByClassName("cracker");
      let fires = document.getElementsByClassName("fire");
      let audio = document.getElementById("music");
      if (audio.paused) {
        audio.play(); // 播放
      }
      if (len == "") len = crackers.length - 1;
      crackers[len].classList.add("to-smoke");
      crackers[len - 1].classList.add("to-smoke");
      setTimeout(() => {
        crackers[len].remove();
        crackers[len - 1].remove();
      }, 5000);
      for (let i = 0; i < fires.length; i++) {
        fires[i].style.display = "block";
        fires[i].style.top =
          parseInt(fires[i].style.top) - this.crackerHeight + "px";
      }
      setTimeout(() => {
        if (len - 2 >= 0) {
          this.play(len - 2);
        } else {
          for (let i = fires.length - 1; i >= 0; i--) {
            fires[i].remove();
            audio.pause();
          }
        }
      }, this.speed);
    },
    //初始化炮竹
    initCrackers() {
      let crackers = document.getElementsByClassName("cracker");
      let num = 0;
      let j = 0;
      while (crackers.length > j) {
        for (let i = 0; i < 2; ++i) {
          let cracker = crackers[j];
          j++;
          cracker.style.top = num * this.crackerHeight + "px";
          if (j % 2 == 0) {
            cracker.style.transform = "rotate(30deg)";
            cracker.style.left = "-5px";
          } else {
            cracker.style.transform = "rotate(-30deg)";
          }
        }
        num++;
      }
    },
    //初始化炮竹线
    initLine() {
      let line = document.getElementsByClassName("line")[0];
      line.style.height = this.crackerHeight * (this.crackerNum / 2) + "px";
    },
    //初始化火花
    initFires() {
      let fires = document.getElementsByClassName("fire");
      for (let i = 0; i < fires.length; i++) {
        fires[i].style.top =
          this.crackerHeight * (this.crackerNum / 2) +
          parseFloat(this.getRandom(2)) +
          "px";
        fires[i].style.left = parseFloat(this.getRandom(10)) + "px";
      }
    },
    getRandom(n) {
      let r = Math.random() * n;
      let flag = Math.random();
      if (flag > 0.5) return -r;
      return r;
    },
  },
  mounted() {
    this.init();
  },
};
</script>
<style lang="scss" scoped>
#app {
  font-family: "Avenir", Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
  .firecrackers {
    position: relative;
    width: 60%;
    height: 60%;
    left: 20%;
    .Stick {
      background-color: grey;
      height: 300px;
      width: 5px;
      position: absolute;
      transform: rotate(45deg);
    }
    .line {
      background-color: grey;
      height: 300px;
      width: 2px;
      position: absolute;
      top: 43px;
      left: 106px;
      .cracker {
        width: 5px;
        height: 12px;
        background-color: red;
        position: absolute;
      }
      .fire {
        background-color: orange;
        width: 5px;
        height: 5px;
        border-radius: 50%;
        top: 300px;
        position: absolute;
        animation: fireAni 1s infinite;
        display: none;
      }
    }
  }
  .play {
    cursor: pointer;
  }
  .to-smoke {
    text-shadow: 0 0 0 whitesmoke;
    animation: smoky 5s;
  }
  @keyframes fireAni {
    0% {
      opacity: 0;
    }
    50% {
      opacity: 1;
    }
    100% {
      opacity: 0;
    }
  }
  @keyframes smoky {
    to {
      background-color: whitesmoke;
      transform: translate3d(200px, 80px, 0) rotate(-40deg) skewX(70deg)
        scale(1.5);
      text-shadow: 0 0 20px whitesmoke;
      opacity: 0;
    }
  }
}
</style>

二、原生js实现

html
<body>
    <div id="app">
        <div class="firecrackers">
            <div class="Stick"></div>
            <div class="line"></div>
        </div>
        <div class="play" onclick="play()">点炮竹</div>
        <audio
               src="./assets/鞭炮声.mp3"
               controls="controls"
               preload
               id="music"
               hidden
               ></audio>
    </div>
</body>
script
初始化炮竹元素

初始化鞭炮的样式,让鞭炮左右倾斜排布。

//初始化炮竹
function initCrackers() {
    let crackers = document.getElementsByClassName("cracker");
    let num = 0;
    let j = 0;
    while (crackers.length > j) {
        for (let i = 0; i < 2; ++i) {
            let cracker = crackers[j];
            j++;
            cracker.style.top = num * crackerHeight + "px";
            if (j % 2 == 0) {
                cracker.style.transform = "rotate(30deg)";
                cracker.style.left = "-5px";
            } else {
                cracker.style.transform = "rotate(-30deg)";
            }
        }
        num++;
    }
}
初始化火花

在一定范围内随机生成闪烁的元素来模拟火花。

//初始化火花
function initFires() {
    let fires = document.getElementsByClassName("fire");
    for (let i = 0; i < fires.length; i++) {
        fires[i].style.top =
            crackerHeight * (crackerNum / 2) + parseFloat(getRandom(2)) + "px";
        fires[i].style.left = parseFloat(getRandom(10)) + "px";
    }
}
function getRandom(n) {
    let r = Math.random() * n;
    let flag = Math.random();
    if (flag > 0.5) return -r;
    return r;
}
初始化页面

使用js动态生成dom元素

function initPage() {
    let line = document.getElementsByClassName("line")[0];
    let temp = ``;
    for (let i = 0; i < crackerNum; i++) {
        temp += `<div key="${i}" class="cracker"></div>`;
    }
    for (let i = 0; i < 10; i++) {
        temp += `<div key="${i}" class="fire"></div>`;
    }
    line.innerHTML = temp;
    initLine();
    initCrackers();
    initFires();
}
点燃鞭炮

点击燃烧鞭炮,添加飘落效果和鞭炮声

//点炮竹
function play(len = "") {
    let crackers = document.getElementsByClassName("cracker");
    let fires = document.getElementsByClassName("fire");
    let audio = document.getElementById("music");
    if (audio.paused) {
        audio.play(); // 播放
    }
    if (len == "") len = crackers.length - 1;
    crackers[len].classList.add("to-smoke");
    crackers[len - 1].classList.add("to-smoke");
    setTimeout(() => {
        crackers[len].remove();
        crackers[len - 1].remove();
    }, 5000);
    for (let i = 0; i < fires.length; i++) {
        fires[i].style.display = "block";
        fires[i].style.top =
            parseInt(fires[i].style.top) - crackerHeight + "px";
    }
    setTimeout(() => {
        if (len - 2 >= 0) {
            play(len - 2);
        } else {
            for (let i = fires.length - 1; i >= 0; i--) {
                fires[i].remove();
                audio.pause();
            }
        }
    }, speed);
}
css
粒子闪烁动画简单模拟火花
@keyframes fireAni {
    0% {
        opacity: 0;
    }
    50% {
        opacity: 1;
    }
    100% {
        opacity: 0;
    }
}
鞭炮燃烧后飘落效果
@keyframes smoky {
    to {
        background-color: whitesmoke;
        transform: translate3d(200px, 80px, 0) rotate(-40deg) skewX(70deg)
            scale(1.5);
        text-shadow: 0 0 20px whitesmoke;
        opacity: 0;
    }
}
完整代码
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title></title>
    </head>
    <body>
        <div id="app">
            <div class="firecrackers">
                <div class="Stick"></div>
                <div class="line"></div>
            </div>
            <div class="play" onclick="play()">点炮竹</div>
            <audio
                   src="./assets/鞭炮声.mp3"
                   controls="controls"
                   preload
                   id="music"
                   hidden
                   ></audio>
        </div>
    </body>
    <script type="text/javascript">
        const crackerHeight = 12; //炮竹高度
        const speed = 200; //燃烧速度ms
        const crackerNum = 80; //炮竹数量
        function initPage() {
            let line = document.getElementsByClassName("line")[0];
            let temp = ``;
            for (let i = 0; i < crackerNum; i++) {
                temp += `<div key="${i}" class="cracker"></div>`;
            }
            for (let i = 0; i < 10; i++) {
                temp += `<div key="${i}" class="fire"></div>`;
            }
            line.innerHTML = temp;
            initLine();
            initCrackers();
            initFires();
        }
        //点炮竹
        function play(len = "") {
            let crackers = document.getElementsByClassName("cracker");
            let fires = document.getElementsByClassName("fire");
            let audio = document.getElementById("music");
            if (audio.paused) {
                audio.play(); // 播放
            }
            if (len == "") len = crackers.length - 1;
            crackers[len].classList.add("to-smoke");
            crackers[len - 1].classList.add("to-smoke");
            setTimeout(() => {
                crackers[len].remove();
                crackers[len - 1].remove();
            }, 5000);
            for (let i = 0; i < fires.length; i++) {
                fires[i].style.display = "block";
                fires[i].style.top =
                    parseInt(fires[i].style.top) - crackerHeight + "px";
            }
            setTimeout(() => {
                if (len - 2 >= 0) {
                    play(len - 2);
                } else {
                    for (let i = fires.length - 1; i >= 0; i--) {
                        fires[i].remove();
                        audio.pause();
                    }
                }
            }, speed);
        }
        //初始化炮竹
        function initCrackers() {
            let crackers = document.getElementsByClassName("cracker");
            let num = 0;
            let j = 0;
            while (crackers.length > j) {
                for (let i = 0; i < 2; ++i) {
                    let cracker = crackers[j];
                    j++;
                    cracker.style.top = num * crackerHeight + "px";
                    if (j % 2 == 0) {
                        cracker.style.transform = "rotate(30deg)";
                        cracker.style.left = "-5px";
                    } else {
                        cracker.style.transform = "rotate(-30deg)";
                    }
                }
                num++;
            }
        }
        //初始化炮竹线
        function initLine() {
            let line = document.getElementsByClassName("line")[0];
            line.style.height = crackerHeight * (crackerNum / 2) + "px";
        }
        //初始化火花
        function initFires() {
            let fires = document.getElementsByClassName("fire");
            for (let i = 0; i < fires.length; i++) {
                fires[i].style.top =
                    crackerHeight * (crackerNum / 2) + parseFloat(getRandom(2)) + "px";
                fires[i].style.left = parseFloat(getRandom(10)) + "px";
            }
        }
        function getRandom(n) {
            let r = Math.random() * n;
            let flag = Math.random();
            if (flag > 0.5) return -r;
            return r;
        }
        initPage();
    </script>
    <style>
        body {
            height: 100%;
            width: 100%;
            background-color: rgb(19, 12, 12);
        }
        #app {
            font-family: "Avenir", Helvetica, Arial, sans-serif;
            -webkit-font-smoothing: antialiased;
            -moz-osx-font-smoothing: grayscale;
            text-align: center;
            color: #2c3e50;
            margin-top: 60px;
        }
        .firecrackers {
            position: relative;
            width: 60%;
            height: 60%;
            left: 20%;
        }
        .Stick {
            background-color: grey;
            height: 300px;
            width: 5px;
            position: absolute;
            transform: rotate(45deg);
        }
        .line {
            background-color: grey;
            height: 300px;
            width: 2px;
            position: absolute;
            top: 43px;
            left: 106px;
        }
        .cracker {
            width: 5px;
            height: 12px;
            background-color: red;
            position: absolute;
        }
        .fire {
            background-color: orange;
            width: 5px;
            height: 5px;
            border-radius: 50%;
            top: 300px;
            position: absolute;
            animation: fireAni 1s infinite;
            display: none;
        }
        .play {
            cursor: pointer;
            color: whitesmoke;
        }
        .to-smoke {
            text-shadow: 0 0 0 whitesmoke;
            animation: smoky 5s;
        }
        @keyframes fireAni {
            0% {
                opacity: 0;
            }
            50% {
                opacity: 1;
            }
            100% {
                opacity: 0;
            }
        }
        @keyframes smoky {
            to {
                background-color: whitesmoke;
                transform: translate3d(200px, 80px, 0) rotate(-40deg) skewX(70deg)
                    scale(0.5);
                text-shadow: 0 0 20px whitesmoke;
                opacity: 0;
            }
        }
    </style>
</html>

说在后面

代码写得有点丑,实现效果也没有很炫酷,只是有感而发,做了这样一个页面来给自己增加一点年味,在这里提前祝大家新年快乐,虎年虎虎生威,如虎添翼。

目录
相关文章
|
7月前
|
存储 C++
【寒假打卡】Day01
【寒假打卡】Day01
46 0
|
7月前
|
消息中间件 前端开发 NoSQL
目前实习,要不要辞职回家过年?
目前实习,要不要辞职回家过年?
81 3
目前实习,要不要辞职回家过年?
|
7月前
【寒假打卡】Day02
【寒假打卡】Day02
51 0
|
Python
Pythyon|当中秋遇上国庆
Pythyon|当中秋遇上国庆
203 0
A计划救公主
可怜的公主在一次次被魔王掳走一次次被骑士们救回来之后,而今,不幸的她再一次面临生命的考验。魔王已经发出消息说将在T时刻吃掉公主,因为他听信谣言说吃公主的肉也能长生不老。年迈的国王正是心急如焚,告招天下勇士来拯救公主。不过公主早已习以为常,她深信智勇的骑士LJ肯定能将她救出。
191 0
|
程序员 网络架构
过年回家,程序猿最怕的5件事
时间过得真快啊,一月接一月,一年又一年。程序猿工作繁忙,每天游离于代码之间,似乎已经忘记了时间的流淌。
过年回家,程序猿最怕的5件事
|
消息中间件 分布式计算 Hadoop
除了吃月饼,中秋节还能干啥? | 9月12号栖夜读
今天的首篇文章,讲述了:明天八月十五,团圆夜花好月圆之际!除了吃月饼,还能干啥?
2964 0
一个项目告一段落,终于可以回家过年了。
一个项目告一段落,终于可以回家过年了。      这个项目已经有了一年多的时间了,一开始还是几个人一起来做,到最后就只有我一个人了,没办法又不能放弃,只能自己一个人来抗了。      终于是告一段落了。
804 0
2018-过年记
    眨眼间2018的春节在欢声炮竹中过完了,相逢是一件愉快的事情,只可惜美好的时光永远是短暂的,不知道这是不是人的一种本性,时间在和谐的状态下总是过得飞快。
842 0