前言
这篇文章的产生有两个原因:
第一个是我在「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>
结束语
生活要有仪式感哦~
祝大家的生活充满阳光☀️
为什么题目中有奇迹再现呢,因为我引的音乐是这个童年经典的主题曲,本文标题也是在致敬最后一话的题目《致以辉煌的人》
我最后用《生命永存》这一话的经典台词结尾:
努力活完短暂的一生
将成果留给后代继承
人类就是如此反复
真的很了不起!
如果喜欢我的文章或者创意📖,可以用点赞+关注支持我~感谢✨