天天看點

「《奇迹再現》專屬音樂播放器」緻以躍動的心與陽光

大家好,我是寒草????,一隻草系碼猿????。間歇性熱血????,持續性沙雕????

如果喜歡我的文章,可以關注➕ 點贊,與我一同成長吧~

前言

這篇文章的産生有兩個原因:

第一個是我在​​「canvas」國慶将至????????,"手繪"一幅那兔,并暢談我的夢​​中搞了一個彩蛋,彩蛋的标題是:獻給寒草未來的夫妻,再加上我最近看到了很多代碼寫的三行情書,就像這種:

#倘若你回首看看我
ifyou.turn_round_aguang():
#我永遠在你背後
I.behind(you).forever()
#關注着你
see(you)      

于是乎我就萌生了一個想法,就是講一講程式員如何表白,後來想起來,老朽并沒有這種經曆,我咋給大家講嘛,而且我在搜尋如何用程式表白的時候發現很多人回答是:

大直男才用程式表白

我瞬間自閉,就打算放棄這個主題。

還有一件事就是我前一陣寫了一個小太陽自娛自樂:

「《奇迹再現》專屬音樂播放器」緻以躍動的心與陽光

但是我有個遺憾,就是太陽的光芒太單調,希望他加入一些動感。

于是我心生一計,将兩個主題合二為一,快,叫我小天才!

蹩腳的設計之路

其實這個 demo 的主題已經明确了:

  • 具有表白能力
  • 有動感的小太陽

那麼如何搞一個有動感的小太陽呢,我首先想到的就是音樂播放器的動效,就像網易雲的這個​

​咚次哒次​

​的效果

「《奇迹再現》專屬音樂播放器」緻以躍動的心與陽光

我就把樣式搞的更像太陽就好了。

那具有表白能力咋搞啊,我也不太會設計這方面的東西,我就先搞了一個心❤️(其實是之前試驗web-components的時候做的),代碼寫都寫了,即使再短我也要複用一下的!那麼心和太陽怎麼結合呢?

我陷入了痛苦,常考後,心生一計:

用那個心做按鈕吧,點完了開始播放音樂(我這個想法真的是太土鼈了哈哈哈哈哈,但是我會想辦法讓這個想法不那麼土鼈)

實作 ????

音樂處理 ????

參考MDN:​​developer.mozilla.org/zh-CN/docs/…​​

let audio = new Audio("dijia.mp3");
let audioCtx = new (window.AudioContext || window.webkitAudioContext)();
let source = audioCtx.createMediaElementSource(audio)
let analyser = audioCtx.createAnalyser();
source.connect(analyser);
analyser.connect(audioCtx.destination)
analyser.fftSize = 1024;
let bufferLength = analyser.frequencyBinCount;
let dataArray = new Uint8Array(bufferLength);
audio.play();
setInterval(() => {
  analyser.getByteTimeDomainData(dataArray);
  // 這裡的dataArray就是我要的資訊
  dataArray.slice(0, 360).forEach((item, index) => {
    rays[index].style.height = `${item / 2}px`;
  })
}, 1000)      

跳躍的心 ❤️

「《奇迹再現》專屬音樂播放器」緻以躍動的心與陽光

這裡用的 ​

​web-component​

<!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>web-component</title>
</head>

<body>
  <my-heart></my-heart>
  <template id="my-heart">
    <style>
      :host {
        position: absolute;
        top: 100px;
        left: 100px;
        animation: tiaodong .8s linear infinite;
      }

      .left {
        position: absolute;
        width: 80px;
        height: 120px;
        background-color: red;
        border-radius: 50px 50px 0 0;
        transform: rotate(-45deg);
      }

      .right {
        width: 80px;
        position: absolute;
        height: 120px;
        background-color: red;
        border-radius: 50px 50px 0 0;
        left: 28px;
        transform: rotate(45deg)
      }

      @keyframes tiaodong {
        0% {
          transform: scale(1);
        }

        50% {
          transform: scale(1.05);
        }

        100% {
          transform: scale(1);
        }
      }
    </style>
    <div class="left"></div>
    <div class="right"></div>
  </template>
  <script>
    class MyHeart extends HTMLElement {
      constructor() {
        super();
        const templateElem = document.getElementById('my-heart');
        const content = templateElem.content.cloneNode(true);

        this.attachShadow({ mode: 'closed' }).appendChild(content);
      };
    }
    window.customElements.define('my-heart', MyHeart);
  </script>
</body>

</html>      

360 度環繞太陽 ☀️

「《奇迹再現》專屬音樂播放器」緻以躍動的心與陽光

html:

<div class="sun"></div>      

css:

body {
      display: flex;
      padding: 0;
      align-items: center;
      justify-content: center;
      min-height: 100vh;
      background-color: #f3eeea;
      margin: 0;
    }

    .sun {
      position: relative;
      left: 300px;
      width: 40vmin;
      height: 40vmin;
      border-radius: 100%;
      background-color: #fdf4ae;
    }

    .ray {
      position: absolute;
      top: 40vmin;
      left: 20vmin;
      width: 1vmin;
      height: 6.25vmin;
      transform-origin: 0 -20vmin;
      transform: translateY(25vmin);
      transition: all 1s linear;
    }

    .ray:after {
      content: '';
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      border-radius: 50%;
      background: linear-gradient(to bottom, #fcec71, #edc353);
    }

    .ray:after {
      height: 100%;
      transform-origin: 50% 100%;
    }      

js:

// 動态生成360個光線
const sun = document.getElementsByClassName('sun')[0];
let html = '';
(new Array(360)).fill('hancao-design').forEach((item, index) => {
  html += `<div class="ray" style="transform: rotate(${index * 1}deg);"></div>`;
})
sun.innerHTML = html;      

躍動的陽光 ????

​我感覺我錄的 gif 一直都不好,我一定努力搞一個好用的 gif 錄制軟體​

​​

「《奇迹再現》專屬音樂播放器」緻以躍動的心與陽光

我就是單純的用:

transition: all 1s linear;

配合定時器

setInterval(() => {
  analyser.getByteTimeDomainData(dataArray);
  dataArray.slice(0, 360).forEach((item, index) => {
    rays[index].style.height = `${item / 2}px`;
  })
}, 1000)      

心的巧妙用法 ❤️

「《奇迹再現》專屬音樂播放器」緻以躍動的心與陽光

我做了一個類似于終端的界面,最後會出來一個心髒,我去點選之後就可以播放音樂并讓太陽躍動起來~

// 内容如下,和那兔那篇文章關聯起來了有沒有~
hancao-design
for my feature lover
sun loading
...
retry
...
loaded
I wanna to be your sun
pleading enjoy the sunshine
click my-heart to start      
window.customElements.define('my-heart', MyHeart);
    const list = ['<span style="color: red;"">hancao-design</span>', 'for my feature lover', 'sun loading', '...', 'retry',  '...', 'loaded', 'I wanna to be your sun', 'pleading enjoy the sunshine', 'click <span style="color: red;">my-heart</span> to start', '⬇️']
    const editor = document.getElementsByClassName('editor')[0];
    let i = 0;
    let len = list.length;
    const timer = setInterval(() => {
      if(i < len){
        editor.innerHTML += `<div>${list[i]}</div>`
      }else{
        clearInterval(timer);
        editor.innerHTML += `<my-heart></my-heart>`
      }
      i++;
    }, 500);      

完整代碼 ????

<!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>music</title>
  <style>
    body {
      display: flex;
      padding: 0;
      align-items: center;
      justify-content: center;
      min-height: 100vh;
      background-color: #f3eeea;
      margin: 0;
    }

    .sun {
      position: relative;
      left: 300px;
      width: 40vmin;
      height: 40vmin;
      border-radius: 100%;
      background-color: #fdf4ae;
    }

    .ray {
      position: absolute;
      top: 40vmin;
      left: 20vmin;
      width: 1vmin;
      height: 6.25vmin;
      transform-origin: 0 -20vmin;
      transform: translateY(25vmin);
      transition: all 1s linear;
    }

    .ray:after {
      content: '';
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      border-radius: 50%;
      background: linear-gradient(to bottom, #fcec71, #edc353);
    }

    .ray:after {
      height: 100%;
      transform-origin: 50% 100%;
    }

    .editor {
      width: 600px;
      height: 100vh;
      position: fixed;
      background-color: #1c1d21;
      left: 0px;
      color: #c1c5cd;
      padding-left: 32px;
      padding-top: 64px;
      font-size: 32px;
    }
  </style>
</head>

<body>
  <div class="sun"></div>
  <div class="editor"></div>
  <template id="my-heart">
    <style>
      :host {
        position: absolute;
        animation: tiaodong .8s linear infinite;
        cursor: pointer;
      }

      .left {
        position: absolute;
        width: 80px;
        height: 120px;
        background-color: red;
        border-radius: 50px 50px 0 0;
        transform: rotate(-45deg);
      }

      .right {
        width: 80px;
        position: absolute;
        height: 120px;
        background-color: red;
        border-radius: 50px 50px 0 0;
        left: 28px;
        transform: rotate(45deg)
      }

      @keyframes tiaodong {
        0% {
          transform: scale(1);
        }

        50% {
          transform: scale(1.05);
        }

        100% {
          transform: scale(1);
        }
      }
    </style>
    <div class="left"></div>
    <div class="right"></div>
  </template>
  <script>
    const sun = document.getElementsByClassName('sun')[0];
    let html = '';
    (new Array(360)).fill('hancao-design').forEach((item, index) => {
      html += `<div class="ray" style="transform: rotate(${index * 1}deg);"></div>`;
    })
    sun.innerHTML = html;
    const rays = sun.childNodes;
    class MyHeart extends HTMLElement {
      constructor() {
        super();
        const templateElem = document.getElementById('my-heart');
        const content = templateElem.content.cloneNode(true);
        this.onclick =() => {
            this.onclick = null;
            let audio = new Audio("dijia.mp3");
            let audioCtx = new (window.AudioContext || window.webkitAudioContext)();
            let source = audioCtx.createMediaElementSource(audio)
            let analyser = audioCtx.createAnalyser();
            source.connect(analyser);
            analyser.connect(audioCtx.destination)
            analyser.fftSize = 1024;
            let bufferLength = analyser.frequencyBinCount;
            let dataArray = new Uint8Array(bufferLength);
            audio.play();
            setInterval(() => {
              analyser.getByteTimeDomainData(dataArray);
              dataArray.slice(0, 360).forEach((item, index) => {
                rays[index].style.height = `${item / 2}px`;
              })
            }, 1000)
        }
        this.attachShadow({ mode: 'closed' }).appendChild(content);
      };
    }
    window.customElements.define('my-heart', MyHeart);
    const list = ['<span style="color: red;"">hancao-design</span>', 'for my feature lover', 'sun loading', '...', 'retry',  '...', 'loaded', 'I wanna to be your sun', 'pleading enjoy the sunshine', 'click <span style="color: red;">my-heart</span> to start', '⬇️']
    const editor = document.getElementsByClassName('editor')[0];
    let i = 0;
    let len = list.length;
    const timer = setInterval(() => {
      if(i < len){
        editor.innerHTML += `<div>${list[i]}</div>`
      }else{
        clearInterval(timer);
        editor.innerHTML += `<my-heart></my-heart>`
      }
      i++;
    }, 500);

  </script>
</body>
</html>      

結束語

「《奇迹再現》專屬音樂播放器」緻以躍動的心與陽光

生活要有儀式感哦~

祝大家的生活充滿陽光☀️

​為什麼題目中有奇迹再現呢,因為我引的音樂是這個童年經典的主題曲,本文标題也是在緻敬最後一話的題目《緻以輝煌的人》​

我最後用《生命永存》這一話的經典台詞結尾:

努力活完短暫的一生

将成果留給後代繼承

人類就是如此反複

繼續閱讀