iT邦幫忙

2024 iThome 鐵人賽

DAY 29
0
Modern Web

創意前端設計:用 Vue.js 打造 30 個互動實用功能系列 第 29

Day29 Vue.js 動效分類實戰 (20) 蛋糕特輯 - 來過生日!吹氣 + 驚喜動畫,慶祝儀式感拉滿

  • 分享至 

  • xImage
  •  

https://ithelp.ithome.com.tw/upload/images/20241013/20124462k1c2rotSGG.jpg

🎂 生日蛋糕互動秀:吹氣熄蠟燭,還有彩帶灑滿天!🎉

嘿嘿嘿,今天要來和大家分享一個超可愛又好玩的生日蛋糕互動網站
這個專案不但有超酷的動畫效果,還能用聲音把蠟燭吹熄哦~!
不僅如此,當你吹熄蠟燭之後,還會有繽紛的五彩紙屑隨之而來,真的是超級有趣,讓人忍不住想一直玩下去!

今天這篇文章,我們將一步步深入介紹如何實作這個生日蛋糕互動網站,讓你也能輕鬆打造一個屬於自己的有趣網頁!🎂✨


🌟 設計理念:一場趣味十足的視覺和聽覺盛宴

img

這個文章的設計重點在於互動性並且結合之前學到過的各種動效。
使用者不僅可以看到可愛的生日蛋糕動畫,還能通過對裝置吹氣來熄滅蠟燭。
加上動態祝福語和繽紛的五彩紙屑效果,讓整個慶祝場景瞬間充滿歡樂,達到最驚喜的效果。

核心理念:結合視覺、聽覺和互動的元素,創造一個沉浸式的生日慶祝體驗。
使用者能夠參與到其中,真正成為這場生日派對的主角。


🎂 技術細節:如何實作這個超可愛的互動網站?

https://ithelp.ithome.com.tw/upload/images/20241013/20124462Lj5tVH0zep.png

1. 動畫蛋糕與蠟燭燃燒效果 🎂🔥

首先,讓我們來看看如何使用 Vue 和 SVG 組件來實現一個動態的蛋糕與蠟燭效果。
蛋糕的設計是通過 Cake 子元件來實現的,並通過 showCandles 屬性控制蠟燭的顯示與否。

Cake.vue 中,我們使用了 CSS keyframes 來創造蠟燭火焰的擺動效果:

@keyframes fuego {
  0%, 100% {
    background: rgba(254, 248, 97, 0.5);
    box-shadow: 0 0 40px 10px rgba(248, 233, 209, 0.2);
    transform: translateY(0) scale(1);
  }
  50% {
    background: rgba(255, 50, 0, 0.1);
    box-shadow: 0 0 40px 20px rgba(248, 233, 209, 0.2);
    transform: translateY(-20px) scale(0);
  }
}

這段 CSS 創造了火焰在蠟燭頂端輕輕擺動的效果,讓整個蛋糕更具生命力!
showCandlestrue 時,蠟燭會顯示在蛋糕上,閃爍的小火焰看起來就像真的在燃燒一樣。

Cake.vue子元件完整程式碼放在文章最下處)


2. 聲音偵測:對著螢幕吹氣,蠟燭就熄滅了! 🗣️💨

img

這是這個互動網站的亮點之一!
我們使用了瀏覽器的麥克風來捕捉使用者的吹氣聲音,並將這個聲音轉換成行為——熄滅蠟燭!

我們使用了 navigator.mediaDevices.getUserMedia 來抓取音訊,並且通過 AnalyserNode 來分析音頻的強度,當音量超過某個閾值時,我們認為使用者正在吹氣,這時蠟燭會被吹熄。

navigator.mediaDevices.getUserMedia({ audio: true })
  .then((stream) => {
    const audioContext = new AudioContext();
    const analyser = audioContext.createAnalyser();
    const source = audioContext.createMediaStreamSource(stream);
    analyser.fftSize = 256;

    const dataArray = new Uint8Array(analyser.frequencyBinCount);

    function detectBreath() {
      analyser.getByteTimeDomainData(dataArray);
      let sum = 0;

      dataArray.forEach(value => sum += Math.abs(value - 128));
      const volume = sum / dataArray.length;

      if (volume > 40) {
        showCandles.value = false;  // 蠟燭熄滅
        triggerConfetti(); // 繽紛紙屑效果
        stream.getTracks().forEach(track => track.stop()); // 停止麥克風
      }
      if (showCandles.value) requestAnimationFrame(detectBreath);  // 繼續偵測
    }

    detectBreath();
  });

這段程式碼確保了當使用者吹氣時,系統會偵測到音量變化,然後觸發相應的動畫效果,讓蠟燭熄滅的過程變得趣味十足。


  • CakePage.vue 父元件完整程式碼
<script lang="ts" setup>
import { shallowRef } from "vue";
import Cake from "../components/Cake.vue";
import confetti from "canvas-confetti";

const triggerConfetti = function () {
  confetti({
    particleCount: 500, // 粒子數量
    spread: 180, // 噴射角度
    origin: { x: 0.5, y: 0.5 }, // 起始位置(畫面中央)
  });
};
// 控制蠟燭顯示的狀態
const showCandles = shallowRef(true);
const showMessage = shallowRef(false); // 控制文案顯示的狀態

const startAudio = function () {
  const AudioContext = window.AudioContext || (window as any).webkitAudioContext;
  const audioContext = new AudioContext();
  const analyser = audioContext.createAnalyser();

  navigator.mediaDevices
    .getUserMedia({ audio: true })
    .then((stream: MediaStream) => {
      const source = audioContext.createMediaStreamSource(stream);
      source.connect(analyser);
      analyser.fftSize = 256;

      const dataArray = new Uint8Array(analyser.frequencyBinCount);

      function detectBreath() {
        analyser.getByteTimeDomainData(dataArray);
        let sum = 0;

        // 計算音量值
        for (let i = 0; i < dataArray.length; i++) {
          sum += Math.abs(dataArray[i] - 128);
        }
        const volume = sum / dataArray.length;

        // 偵測音量閾值,音量大於 40 認為是吹氣
        if (volume > 40) {
          showCandles.value = false; // 吹熄蠟燭
          triggerConfetti(); // 觸發 confetti 效果
          console.log("Detected breath, candles are blown out!");
          stream.getTracks().forEach((track: MediaStreamTrack) => track.stop()); // 停止麥克風
        }
   
        // 繼續偵測
        if (showCandles.value) {
          requestAnimationFrame(detectBreath);
        }
      }

      // 開始偵測呼氣
      detectBreath();
    })
    .catch((err: Error) => {
      console.error("Error accessing the microphone: ", err);
    });
};


const showAfterDelay = () => {
  setTimeout(() => {
    showMessage.value = true; // 7 秒後顯示祝福文案
  }, 7000); // 7000 毫秒 = 7 秒
};

showAfterDelay();
</script>

<template>
  <div class="h-screen bg-pink-3 w-full overflow-hidden">
    <Cake :showCandles="showCandles"/>
    <Transition name="fade" mode="out-in">

    <div v-if="showMessage" class="flex flex-col justify-center items-center font-mono space-y-4 tracking-widest">
      <div class="text-6xl text-center py-10 text-[#8b6a60]">Happy Birthday</div>

      <div v-if="showCandles" 
        class="text-2xl text-center leading-relaxed text-white">
        對著螢幕許下你的願望,然後準備吹熄蠟燭!
        <br />
        <a href="#" @click="startAudio" class="text-white underline"
          >點擊這裡,開啟祝福音效</a
        >
      </div>

      <div v-else 
        @click="triggerConfetti"
        class="text-2xl text-center leading-relaxed text-white cursor-pointer">
        🎊你的願望一定都會實現!🎊
    </div>
    </div>

    </Transition>
  </div>
</template>

<style scoped>

/* 定義淡入效果的 CSS */
.fade-enter-active, .fade-leave-active {
  transition: opacity 1s;
}
.fade-enter-from, .fade-leave-to {
  opacity: 0;
}
</style>


3. 慶祝特效:五彩紙屑滿天飛! 🎉🎊

https://ithelp.ithome.com.tw/upload/images/20241013/20124462vs1OxiWOX4.png
當蠟燭熄滅後,我們會觸發五彩紙屑,讓生日派對達到最高潮!這裡我們使用了 canvas-confetti 來實現紙屑效果:

const triggerConfetti = function () {
  confetti({
    particleCount: 500,
    spread: 180,
    origin: { x: 0.5, y: 0.5 },
  });
};

這段程式碼讓五彩紙屑從畫面的中央噴射而出,隨著蠟燭熄滅,整個畫面變得繽紛又充滿喜悅,讓使用者的成就感瞬間爆棚!


4. 祝福文案淡入效果 🎈🎁

img

當蠟燭熄滅後,系統還會顯示一段動人的祝福文案,這段文字會通過 Vue Transition 和 CSS 動畫進行淡入顯示,增添了儀式感和驚喜。

<Transition name="fade" mode="out-in">
  <div v-if="showMessage" class="text-6xl text-center py-10 text-[#8b6a60]">
    Happy Birthday!
  </div>
</Transition>

這裡使用了 CSS 的 fade 淡入效果,讓文案從透明逐漸變得清晰,給使用者帶來滿滿的祝福:

.fade-enter-active, .fade-leave-active {
  transition: opacity 1s;
}
.fade-enter-from, .fade-leave-to {
  opacity: 0;
}

這個設計讓祝福語句像魔法一樣出現在螢幕上,為整個互動增加了神秘感和樂趣。


🎉 小結:你也來做一個吧!

這次的生日蛋糕互動專案真的充滿了驚喜和趣味!
不僅有漂亮的動畫、可愛的蠟燭火焰效果,還能偵測到使用者的吹氣行為,帶來充滿互動性的慶祝體驗。
結合五彩紙屑和祝福文案的淡入效果,這個網站絕對會讓每個參與的人都充滿驚喜和快樂!

這次讓你學會如何在 Vue.js 中運用動畫和音訊偵測,還展示了如何設計一個充滿互動性的網站。
快動手做一個屬於你的生日派對網站吧!
讓每一次的慶祝都變得難忘又有趣!🎂🎉

img


備註

  • Cake.vue 子元件完整程式碼
<script lang="ts" setup>
import { defineProps } from 'vue';

defineProps({
  showCandles: {
    type: Boolean,
    default: false, // 可選:如果你想要一個預設值
  }
});
</script>
<template>
  <div>
    <div class="velas">
      <div
        class="fuego"
        v-for="(_f, i) in 5"
        :key="i"
        :style="{ animationDuration: `${2 - i * 0.5}s` }"
        v-if="showCandles"
      ></div>
    </div>
    <svg
      id="cake"
      version="1.1"
      x="0px"
      y="0px"
      width="200px"
      height="500px"
      viewBox="0 0 200 500"
      enable-background="new 0 0 200 500"
      xml:space="preserve"
    >
      <path
        fill="#a88679"
        d="M173.667-13.94c-49.298,0-102.782,0-147.334,0c-3.999,0-4-16.002,0-16.002
		c44.697,0,96.586,0,147.334,0C177.667-29.942,177.668-13.94,173.667-13.94z"
      >
        <animate
          id="bizcocho_3"
          attributeName="d"
          calcMode="spline"
          keySplines="0 0 1 1; 0 0 1 1"
          begin="relleno_2.end"
          dur="0.3s"
          fill="freeze"
          values="
                          M173.667-13.94c-49.298,0-102.782,0-147.334,0c-3.999,0-4-16.002,0-16.002
		c44.697,0,96.586,0,147.334,0C177.667-29.942,177.668-13.94,173.667-13.94z
                          ;
                          M173.667,411.567c-47.995,12.408-102.955,12.561-147.334,0
		c-3.848-1.089-0.189-16.089,3.661-15.002c44.836,12.66,90.519,12.753,139.427,0.07
		C173.293,395.631,177.541,410.566,173.667,411.567z
                          ;
                          M173.667,427.569c-49.795,0-101.101,0-147.334,0c-3.999,0-4-16.002,0-16.002
		c46.385,0,97.539,0,147.334,0C177.668,411.567,177.667,427.569,173.667,427.569z
                          "
        />
      </path>
      <path
        fill="#8b6a60"
        d="M100-178.521c1.858,0,3.364,1.506,3.364,3.363c0,0,0,33.17,0,44.227
		c0,19.144,0,57.431,0,76.574c0,10.152,0,40.607,0,40.607c0,1.858-1.506,3.364-3.364,3.364l0,0c-1.858,0-3.364-1.506-3.364-3.364c0,0,0-30.455,0-40.607c0-19.144,0-57.432,0-76.575c0-11.057,0-44.226,0-44.226C96.636-177.015,98.142-178.521,100-178.521
		L100-178.521z"
      >
        <animate
          id="relleno_2"
          attributeName="d"
          calcMode="spline"
          keySplines="0 0 1 1; 0 0 1 1; 0 0 0.58 1"
          begin="bizcocho_2.end"
          dur="0.5s"
          fill="freeze"
          values="
                          M100-178.521c1.858,0,3.364,1.506,3.364,3.363c0,0,0,33.17,0,44.227
		c0,19.144,0,57.431,0,76.574c0,10.152,0,40.607,0,40.607c0,1.858-1.506,3.364-3.364,3.364l0,0c-1.858,0-3.364-1.506-3.364-3.364c0,0,0-30.455,0-40.607c0-19.144,0-57.432,0-76.575c0-11.057,0-44.226,0-44.226C96.636-177.015,98.142-178.521,100-178.521
		L100-178.521z
                          ;
                          M100,267.257c1.858,0,3.364,1.506,3.364,3.363c0,0,0,33.17,0,44.227
		c0,19.143,0,57.43,0,76.574c0,10.151,0,40.606,0,40.606c0,1.858-1.506,3.364-3.364,3.364l0,0c-1.858,0-3.364-1.506-3.364-3.364
		c0,0,0-30.455,0-40.606c0-19.145,0-57.432,0-76.576c0-11.057,0-44.225,0-44.225C96.636,268.763,98.142,267.257,100,267.257
		L100,267.257z
                          ;
                          M93.928,405.433c-0.655,6.444-0.102,9.067,2.957,11.798c0,0,8.083,5.571,16.828,3.503
		c18.629-4.406,43.813,6.194,50.792,7.791c14.75,3.375,9.162,6.867,9.162,6.867c-2.412,2.258-58.328,0-73.667,0l0,0
		c-1.858,0-69.995,2.133-73.667,0c0,0-3.337-2.439,6.172-5.992c11.375-4.25,52.875,8.822,47.139-9.442
		c-6.333-20.167,5.226-21.514,5.226-21.514c3.435-0.915,12.78-6.663,10.923-0.546L93.928,405.433z
                          ;
                          M102.242,427.569c5.348,0,14.079,0,17.462,0c0,0,17.026,0,27.504,0
		c19.143,0,20.39-3.797,26.459,0c3,1.877,0,7.823,0,7.823c-2.412,2.258-58.328,0-73.667,0l0,0c-1.858,0-67.187,0-73.667,0
		c0,0-4.125-4.983,0-7.823c5.201-3.58,16.085,0,23.725,0c8.841,0,20.762,0,20.762,0c3.686,0,8.597,0,19.511,0H102.242z
                          "
        />
      </path>
      <path
        fill="#a88679"
        d="M173.667-15.929c-46.512,0-105.486,0-147.334,0c-3.999,0-4-16.002,0-16.002
		c43.566,0,97.96,0,147.334,0C177.667-31.931,177.666-15.929,173.667-15.929z"
      >
        <animate
          id="bizcocho_2"
          attributeName="d"
          calcMode="spline"
          keySplines="0 0 1 1; 0 0 1 1; 0.25 0 0.58 1"
          begin="relleno_1.end"
          dur="0.5s"
          fill="freeze"
          values="
                          M173.667-15.929c-46.512,0-105.486,0-147.334,0c-3.999,0-4-16.002,0-16.002
		c43.566,0,97.96,0,147.334,0C177.667-31.931,177.666-15.929,173.667-15.929z
                          ;
                          M173.434,445.393c-47.269,8.001-105.245,8.001-147.334,0c-3.929-0.747-0.692-16.543,3.243-15.824
		c43.828,8.001,92.165,8.001,140.739,0C174.029,428.918,177.377,444.726,173.434,445.393z
                          ;
                          M173.667,449.514c-47.576-5.454-102.799-5.744-147.333,0c-3.966,0.512-3.938-15.297,0-16.002
		c43.683-7.823,97.646-8.026,147.333,0C177.616,434.15,177.642,449.969,173.667,449.514z
                          ;
                          M173.667,451.394c-49.298,0-102.782,0-147.334,0c-3.999,0-4-16.002,0-16.002
		c44.697,0,96.586,0,147.334,0C177.667,435.392,177.668,451.394,173.667,451.394z
                          "
        />
      </path>
      <path
        fill="#8b6a60"
        d="M101.368-73.685c0,12.164,0,15.18,0,28.519c0,22.702,0-13.661,0,8.304c0,14.48,0,18.233,0,30.512
		c0,1.753-2.958,1.847-2.958,0c0-12.68,0-16.277,0-30.401c0-21.983,0,11.66,0-8.305c0-13.027,0-15.992,0-28.628
		C98.411-75.883,101.368-75.592,101.368-73.685z"
      >
        <animate
          id="relleno_1"
          attributeName="d"
          calcMode="spline"
          keySplines="0 0 1 1; 0 0 1 1; 0 0 0.6 1"
          begin="bizcocho_1.end"
          dur="0.5s"
          fill="freeze"
          values="
                          M101.368-73.685c0,12.164,0,15.18,0,28.519c0,22.702,0-13.661,0,8.304c0,14.48,0,18.233,0,30.512
		c0,1.753-2.958,1.847-2.958,0c0-12.68,0-16.277,0-30.401c0-21.983,0,11.66,0-8.305c0-13.027,0-15.992,0-28.628
		C98.411-75.883,101.368-75.592,101.368-73.685z
                          ;
                          M101.368,350.885c0,12.164,0,65.18,0,78.518c0,22.703,0-33.66,0-11.695c0,14.48,0,28.232,0,40.512
		c0,1.753-2.958,1.847-2.958,0c0-12.68,0-26.277,0-40.402c0-21.982,0,31.66,0,11.695c0-13.027,0-65.992,0-78.627
		C98.411,348.686,101.368,348.977,101.368,350.885z
                          ;
                          M128.38,447.567c37.626,6.312,39.303,13.658,26.833,12.833c-22.653-1.499-13.636-0.831-23.302-0.831
		c-14.48,0-17.884,0-30.163,0c-2.087,0-2.068,0-3.915,0c-13.333,0-8.963,0-23.088,0c-11.668,0-14.062,5.995-27.532,1.164
		c-12.629-4.529,38.667-3.167,46.833-17.333C100.077,432.94,105.546,443.736,128.38,447.567z
                          ;
                          M173.667,451.394c2.875,0,2.997,9.257,0,9.131c-22.662-0.956-32.09-0.956-41.756-0.956
		c-14.48,0-17.884,0-30.163,0c-2.087,0-2.068,0-3.915,0c-13.333,0-8.963,0-23.088,0c-11.668,0-34.99-0.294-48.412,1.831
		c-4.109,0.65-3.01-10.006,0-10.006C37.129,451.394,149.379,451.394,173.667,451.394z
                          "
        />
      </path>
      <path
        fill="#a88679"
        d="M173.667,21.571c-33.174,0-111.467,0-147.334,0c-4,0-4-16.002,0-16.002c39.836,0,105.982,0,147.334,0
		C177.668,5.569,177.667,21.571,173.667,21.571z"
      >
        <animate
          id="bizcocho_1"
          attributeName="d"
          calcMode="spline"
          keySplines="0 0 1 1; 0 0 1 1; 0 0 1 1; 0.25 0 1 1; 0 0 1 1; 0.25 0 0.6 1"
          begin="2s"
          dur="0.8s"
          fill="freeze"
          values="
                          M173.667,21.571c-33.174,0-111.467,0-147.334,0c-4,0-4-16.002,0-16.002c39.836,0,105.982,0,147.334,0
		C177.668,5.569,177.667,21.571,173.667,21.571z
                          ;
                          M173.667,459.569c-33.197,16.002-110.782,16.002-147.334,0c-3.664-1.604,1.614-15.617,5.337-14.153
		c40.702,16.002,94.289,16.104,136.505,0.103C171.917,444.1,177.271,457.832,173.667,459.569z
                          ;
                          M171.817,475.571c-39.361-3.001-105.438-2.571-143.556,0c-3.991,0.27-7.377-14.736-3.387-15.014
		c41.553-2.888,104.421-3.121,150.51-0.233C179.378,460.574,175.806,475.875,171.817,475.571z
                          ;
                          M171.817,459.564c-38.8-12.188-104.504-13.762-143.556,0c-3.772,1.329-7.961-12.604-4.178-13.905
		c40.864-14.064,105.114-15.52,151.918-0.973C179.822,445.874,175.634,460.762,171.817,459.564z
                          ;
                          M173.667,475.571c-46.376-5.005-105.924-4.003-147.334,0c-3.981,0.385-3.479-15.421,0.479-16.002
		c43.087-6.327,97.705-7.083,146.855,0.438C177.621,460.613,177.644,476,173.667,475.571z
                          ;
                          M173.667,474.117c-46.376,1.866-105.638,2.01-147.334,0c-3.995-0.192-3.52-16.144,0.479-16.002
		c43.794,1.55,96.341,1.541,145.723,0C176.532,457.99,177.663,473.956,173.667,474.117z
                          ;
                          M173.667,475.571c-46.512,0-105.486,0-147.334,0c-3.999,0-4-16.002,0-16.002c43.566,0,97.96,0,147.334,0
		C177.667,459.569,177.666,475.571,173.667,475.571z
                          "
        />
      </path>
      <path
        fill="#fefae9"
        d="M104.812,113.216c0,3.119-2.164,5.67-4.812,5.67c-2.646,0-4.812-2.551-4.812-5.67c0-5.594,0-16.782,0-22.375
	c0-5.143,0-15.427,0-20.568c0-7.333,0-21.998,0-29.33c0-5.523,0-16.569,0-22.092c0-3.295,0-9.885,0-13.181
	C95.188,2.551,97.353,0,100,0c2.648,0,4.812,2.551,4.812,5.669c0,3.248,0,9.743,0,12.991c0,5.428,0,16.284,0,21.711
	c0,7.618,0,22.854,0,30.472c0,4.952,0,14.854,0,19.807C104.812,96.292,104.812,107.576,104.812,113.216z"
      >
        <animate
          id="crema"
          attributeName="d"
          calcMode="spline"
          keySplines="0 0 1 1; 0 0 1 1; 0 0 1 1; 0.25 0 1 1; 0 0 1 1; 0 0 0.58 1"
          begin="bizcocho_3.end"
          dur="2s"
          fill="freeze"
          values="
                          M104.812,113.216c0,3.119-2.164,5.67-4.812,5.67c-2.646,0-4.812-2.551-4.812-5.67c0-5.594,0-16.782,0-22.375
	c0-5.143,0-15.427,0-20.568c0-7.333,0-21.998,0-29.33c0-5.523,0-16.569,0-22.092c0-3.295,0-9.885,0-13.181
	C95.188,2.551,97.353,0,100,0c2.648,0,4.812,2.551,4.812,5.669c0,3.248,0,9.743,0,12.991c0,5.428,0,16.284,0,21.711
	c0,7.618,0,22.854,0,30.472c0,4.952,0,14.854,0,19.807C104.812,96.292,104.812,107.576,104.812,113.216z
                          ;
                          M104.812,405.897c0,3.119-2.164,5.67-4.812,5.67c-2.646,0-4.812-2.551-4.812-5.67c0-5.594,0-16.782,0-22.376
	c0-5.143,0-15.426,0-20.568c0-7.332,0-21.997,0-29.33c0-5.522,0-16.568,0-22.092c0-3.295,0-9.885,0-13.181
	c0-3.118,2.165-5.669,4.812-5.669c2.648,0,4.812,2.551,4.812,5.669c0,3.247,0,9.743,0,12.991c0,5.428,0,16.283,0,21.711
	c0,7.618,0,22.854,0,30.473c0,4.951,0,14.854,0,19.807C104.812,388.972,104.812,400.256,104.812,405.897z
                          ;
                          M111.873,411.567c-3.119,0-9.226,0-11.874,0c-2.646,0-7.748,0-10.867,0c-7.086,0-12.698,0-18.292,0
	c-6.592,0-12.871,7.371-19.166,3.008c-10.043-6.961-7.776-10.169,2.991-17.745c12.61-8.873,27.713,1.994,25.919-7.531
	c-2.589-13.742,11.008-14.513,11.365-17.789c0.441-4.051,4.235-11.107,8.051-8.175c3.113,2.393,1.007,8.008,0,13.159
	c-1.871,9.569,8.058,2.113,9.494,14.155c2.592,21.732,21.184-0.675,29.309,7.976c5.216,5.553,18.413,5.552,15.426,12.942
	c-3.131,7.745-15.825-4.369-23.8,2.903C126.261,418.271,118.301,411.567,111.873,411.567z
                          ;
                          M111.873,411.567c-3.119,0-9.226,0-11.874,0c-2.646,0-9.734,4.069-12.853,4.069
	c-7.086,0-10.712-4.069-16.306-4.069c-6.592,0-12.12,6.013-19.166,3.008c-7.053-3.008-7.458,2.026-18.659,1.165
	c-6.832-0.525-7.522-3.034-7.533-6.265c-0.037-10.336,22.073-2.452,36.613-2.628c10.234-0.124,19.856-1.439,37.905-2.102
	c16.642-0.61,32.699,1.552,46.009,1.927c12.438,0.351,29.663-8.99,31.532,3.315c0.773,5.093-5.605,3.342-11.211,9.579
	c-5.093,5.667-7.59-4.605-12.965-3.832c-8.269,1.189-14.962-8.537-22.937-1.265C126.261,418.271,118.301,411.567,111.873,411.567z
                          ;
                          M110.946,413.652c-2.904-1.137-8.405-2.748-12.446-0.97c-6.099,2.685-7.273,10.358-13.253,8.242
	c-7.843-2.775-8.953-5.008-14.546-5.01c-24.653-0.011-4.849,26.507-18.264,26.507c-12.377,0,5.791-33.537-19.422-26.682
	c-7.703,2.095-9.806-0.942-9.817-4.173c-0.037-10.336,24.357-4.544,38.897-4.72c10.234-0.124,19.856-1.439,37.905-2.102
	c16.642-0.61,32.699,1.552,46.009,1.927c12.438,0.351,28.973-8.865,31.532,3.315c1.449,6.896,0.318,15.624-3.874,15.624
	c-7.619,0-1.788-15.192-19.243-7.111c-7.581,3.51-15.963-9.738-26.669,1.066C120.644,426.744,118.381,416.561,110.946,413.652z
                          ;
                          M111.547,413.9c-2.969-0.956-8.775-0.949-13.167-0.5c-14.667,1.5-8.325,16.508-14.667,16.666
	c-6.667,0.166-0.167-13.5-13.013-14.151c-30.471-1.545-5.572,46.651-18.987,46.651c-12.377,0,10.333-50.166-18.667-44.5
	c-7.835,1.531-9.537-1.417-9.548-4.647c-0.037-10.336,23.675-5.177,38.215-5.353c10.234-0.124,20.618-1.671,38.667-2.333
	c16.642-0.61,32.023,1.458,45.333,1.833c12.438,0.351,33.819-8.431,33.199,4.001c-0.532,10.666,0.414,26.166-5.245,25.833
	c-7.606-0.447-2.954-31.5-19.243-18.899c-7.985,6.177-17.658-5.969-27.377,5.732C118.88,434.066,121.38,417.067,111.547,413.9z
                          ;
                          M111.547,415.233c-6.667-0.834-9.667,4.667-13.833,3.333c-19.649-6.291-8.158,22.176-14.5,22.334
	c-6.667,0.166,2.833-18-13.333-22.167c-29.544-7.615-9.667,43.833-20.167,43.833c-10.333,0,8.004-55.006-16.833-39
	c-7.5,4.833-9.508-3.78-9.299-7.004c0.799-12.329,23.592-7.153,38.132-7.329c10.234-0.124,20.238-1.505,38.287-2.167
	c16.642-0.61,32.903,1.125,46.213,1.5c12.438,0.351,35.058-5.579,31.863,6.451c-5.532,20.833,1.25,28.216-4.409,27.883
	c-7.606-0.447-6.058-37.895-20.62-23.333c-10.167,10.166-15.972-0.747-25,12C119.547,443.568,121.798,416.515,111.547,415.233z
                          "
        />
      </path>
      <rect x="10" y="475.571" fill="#fefae9" width="180" height="4" />
    </svg>
  </div>
</template>

<style scoped>
#cake {
  display: block;
  position: relative;
  margin: -10em auto 0 auto;
}

/* ============================================== Candle
*/
.velas {
  background: #ffffff;
  border-radius: 10px;
  position: absolute;
  top: 228px;
  left: 50%;
  margin-left: -2.5px;
  margin-top: -8.33333333px;
  width: 5px;
  height: 35px;
  transform: translateY(-300px);
  -ms-transform: translateY(-300px);
  transform: translateY(-300px);
  backface-visibility: hidden;
  -ms-backface-visibility: hidden;
  backface-visibility: hidden;
  animation: in 500ms 6s ease-out forwards;
  animation: in 500ms 6s ease-out forwards;
}

.velas:after,
.velas:before {
  background: rgba(255, 0, 0, 0.4);
  content: "";
  position: absolute;
  width: 100%;
  height: 2.22222222px;
}

.velas:after {
  top: 25%;
  left: 0;
}

.velas:before {
  top: 45%;
  left: 0;
}

/* ============================================== Fire
*/

.fuego {
  border-radius: 100%;
  position: absolute;
  top: -20px;
  left: 50%;
  margin-left: -2.2px;
  width: 6.66666667px;
  height: 18px;
  animation: fuego 2s infinite;
}

/* ============================================== Animation Fire
*/
@keyframes fuego {
  0%,
  100% {
    background: rgba(254, 248, 97, 0.5);
    box-shadow: 0 0 40px 10px rgba(248, 233, 209, 0.2);
    box-shadow: 0 0 40px 10px rgba(248, 233, 209, 0.2);
    transform: translateY(0) scale(1);
    transform: translateY(0) scale(1);
  }

  50% {
    background: rgba(255, 50, 0, 0.1);
    box-shadow: 0 0 40px 20px rgba(248, 233, 209, 0.2);
    box-shadow: 0 0 40px 20px rgba(248, 233, 209, 0.2);
    transform: translateY(-20px) scale(0);
    transform: translateY(-20px) scale(0);
  }
}
@keyframes fuego {
  0%,
  100% {
    background: rgba(254, 248, 97, 0.5);
    box-shadow: 0 0 40px 10px rgba(248, 233, 209, 0.2);
    box-shadow: 0 0 40px 10px rgba(248, 233, 209, 0.2);
    transform: translateY(0) scale(1);
    transform: translateY(0) scale(1);
  }

  50% {
    background: rgba(255, 50, 0, 0.1);
    box-shadow: 0 0 40px 20px rgba(248, 233, 209, 0.2);
    box-shadow: 0 0 40px 20px rgba(248, 233, 209, 0.2);
    transform: translateY(-20px) scale(0);
    transform: translateY(-20px) scale(0);
  }
}
@keyframes in {
  to {
    transform: translateY(0);
    transform: translateY(0);
  }
}
@keyframes in {
  to {
    transform: translateY(0);
    transform: translateY(0);
  }
}
</style>


上一篇
Day 28 Vue.js 動效分類實戰 (19) 星球特輯 - 把宇宙裝進你的網頁
下一篇
Day30 Vue.js 最終:打造貓咪動效廣告牆的最後一哩路
系列文
創意前端設計:用 Vue.js 打造 30 個互動實用功能30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言