113 lines
2.7 KiB
HTML
113 lines
2.7 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="utf-8" />
|
||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||
<title>Mindboost – Media Server</title>
|
||
|
||
<style>
|
||
/* ----- Reset & flex centering ----- */
|
||
html,
|
||
body {
|
||
height: 100%;
|
||
margin: 0;
|
||
padding: 0;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
background: #111;
|
||
color: #fff;
|
||
font-family: sans-serif;
|
||
}
|
||
/* ----- The clickable image “button” ----- */
|
||
#soundBtn {
|
||
width: 200px; /* tweak size here */
|
||
cursor: pointer;
|
||
transition: filter 0.2s;
|
||
}
|
||
#soundBtn:hover {
|
||
filter: brightness(1.3);
|
||
}
|
||
/* ----- Wobble animation (2× back-and-forth) ----- */
|
||
@keyframes wobble {
|
||
0% {
|
||
transform: rotate(0deg);
|
||
}
|
||
25% {
|
||
transform: rotate(7deg);
|
||
}
|
||
50% {
|
||
transform: rotate(-7deg);
|
||
}
|
||
75% {
|
||
transform: rotate(5deg);
|
||
}
|
||
100% {
|
||
transform: rotate(0deg);
|
||
}
|
||
}
|
||
.animate {
|
||
animation: wobble 0.6s ease-in-out 2;
|
||
}
|
||
</style>
|
||
</head>
|
||
|
||
<body>
|
||
<!-- Replace play.png with any PNG/SVG/JPG in your html folder -->
|
||
<img id="soundBtn" src="fasting.png" alt="Fasting" />
|
||
<div>
|
||
Thanks to
|
||
<a href="https://www.flaticon.com/free-icons/fart" title="fart icons">
|
||
BomSymbols
|
||
</a>
|
||
for creating the icon and share it via Flaticon Plattform and thanks to
|
||
the
|
||
<a
|
||
href="https://pixabay.com/users/freesound_community-46691455/"
|
||
title="freesound_community"
|
||
>
|
||
freesound_community
|
||
</a>
|
||
to share this incredible sound on pixabay!
|
||
</div>
|
||
<script>
|
||
/* ---------- Audio-setup & wobbly button ---------- */
|
||
;(async () => {
|
||
const BUTTON = document.getElementById("soundBtn")
|
||
const AUDIO_FILE = "demo-ping.mp3" // <-- change path/format at will
|
||
let ctx, buffer
|
||
|
||
// Pre-fetch & decode once (lazy: only on first click)
|
||
async function initAudio() {
|
||
ctx = new (window.AudioContext || window.webkitAudioContext)()
|
||
const res = await fetch(AUDIO_FILE)
|
||
const array = await res.arrayBuffer()
|
||
buffer = await ctx.decodeAudioData(array)
|
||
}
|
||
|
||
function playSound() {
|
||
const src = ctx.createBufferSource()
|
||
src.buffer = buffer
|
||
src.connect(ctx.destination)
|
||
src.start()
|
||
}
|
||
|
||
// Click handler: spin + sound 🌀🎵
|
||
BUTTON.addEventListener("click", async () => {
|
||
// First click: create context & decode
|
||
if (!ctx) await initAudio()
|
||
playSound()
|
||
|
||
// Trigger wobble animation
|
||
BUTTON.classList.add("animate")
|
||
BUTTON.addEventListener(
|
||
"animationend",
|
||
() => BUTTON.classList.remove("animate"),
|
||
{ once: true },
|
||
)
|
||
})
|
||
})()
|
||
</script>
|
||
</body>
|
||
</html>
|