added audio player section and player script
|
@ -1,9 +1,117 @@
|
|||
// gif player
|
||||
document.querySelectorAll('.paused-animation').forEach(el => {
|
||||
el.addEventListener('click', () => {
|
||||
el.classList.toggle('active');
|
||||
});
|
||||
});
|
||||
|
||||
// track players
|
||||
const players = document.querySelectorAll('.track-player');
|
||||
players.forEach(player => {
|
||||
const trackName = player.getAttribute('data-track');
|
||||
|
||||
const button = document.createElement('div');
|
||||
button.className = 'play-button play'; // start as play
|
||||
player.appendChild(button);
|
||||
|
||||
const wrapper = document.createElement('div');
|
||||
wrapper.className = 'track';
|
||||
wrapper.innerHTML = `
|
||||
<div class="blurgreen track-container">
|
||||
<div class="track-played"></div>
|
||||
<div class="track-unplayed"></div>
|
||||
</div>
|
||||
`;
|
||||
player.appendChild(wrapper);
|
||||
|
||||
const playercontainer = player.querySelector('.track-container');
|
||||
const played = player.querySelector('.track-played');
|
||||
const unplayed = player.querySelector('.track-unplayed');
|
||||
played.style.backgroundImage = `url('tracks/${trackName}-played.png')`;
|
||||
unplayed.style.backgroundImage = `url('tracks/${trackName}.png')`;
|
||||
|
||||
const audio = document.createElement('audio');
|
||||
audio.style.display = 'none';
|
||||
player.appendChild(audio);
|
||||
|
||||
button.addEventListener('click', () => {
|
||||
// Pause other players immediately
|
||||
players.forEach(p => {
|
||||
const otherAudio = p.querySelector('audio');
|
||||
const otherBtn = p.querySelector('.play-button');
|
||||
if (otherAudio !== audio) {
|
||||
if (!otherAudio.paused) otherAudio.pause();
|
||||
if (otherBtn) {
|
||||
otherBtn.classList.add('play');
|
||||
otherBtn.classList.remove('pause');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Then lazy-load and play/pause current audio as before...
|
||||
if (!audio.src) {
|
||||
audio.src = 'tracks/' + trackName + '.mp3';
|
||||
audio.currentTime = 0;
|
||||
audio.load();
|
||||
|
||||
audio.addEventListener('canplay', () => {
|
||||
audio.play().then(() => {
|
||||
button.classList.remove('play');
|
||||
button.classList.add('pause');
|
||||
}).catch(() => {
|
||||
button.classList.add('play');
|
||||
button.classList.remove('pause');
|
||||
});
|
||||
}, { once: true });
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (audio.paused) {
|
||||
audio.play().then(() => {
|
||||
button.classList.remove('play');
|
||||
button.classList.add('pause');
|
||||
}).catch(() => {
|
||||
button.classList.add('play');
|
||||
button.classList.remove('pause');
|
||||
});
|
||||
} else {
|
||||
audio.pause();
|
||||
button.classList.add('play');
|
||||
button.classList.remove('pause');
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
audio.addEventListener('ended', () => {
|
||||
button.classList.add('play');
|
||||
button.classList.remove('pause');
|
||||
});
|
||||
|
||||
|
||||
playercontainer.addEventListener('click', e => {
|
||||
const rect = playercontainer.getBoundingClientRect(); // Use container rect!
|
||||
const clickX = e.clientX - rect.left;
|
||||
const width = rect.width;
|
||||
|
||||
const portion = Math.min(Math.max(clickX / width, 0), 1);
|
||||
|
||||
audio.currentTime = portion * audio.duration;
|
||||
});
|
||||
|
||||
audio.addEventListener('timeupdate', () => {
|
||||
const portion = audio.duration ? audio.currentTime / audio.duration : 0;
|
||||
update_play_position(played, unplayed, portion);
|
||||
});
|
||||
});
|
||||
|
||||
function update_play_position(played_element, unplayed_element, portion) {
|
||||
const playedPercent = portion * 100;
|
||||
const unplayedPercent = 100 - playedPercent;
|
||||
played_element.style.width = playedPercent + "%";
|
||||
unplayed_element.style.width = unplayedPercent + "%";
|
||||
}
|
||||
|
||||
|
||||
// icosahedron
|
||||
// Wait for everything to load
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<rect x="464.497" y="245.176" width="95.007" height="95.01"/>
|
||||
</clipPath>
|
||||
<g clip-path="url(#_clip1)">
|
||||
<g transform="matrix(1,0,0,1,462.499,242.853)">
|
||||
<g transform="matrix(1,0,0,1,462.002,242.677)">
|
||||
<path d="M49.9,2.5C23.6,2.8 2.1,24.4 2.5,50.4C2.9,76.5 24.7,98 50.3,97.5C76.7,96.9 97.7,75.7 97.5,49.8C97.3,23.7 75.7,2.3 49.9,2.5" style="fill:rgb(99,168,184);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(1,0,0,1,462.499,242.853)">
|
||||
|
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
@ -0,0 +1,20 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg width="100%" height="100%" viewBox="0 0 96 96" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||
<g transform="matrix(1,0,0,1,-126,-134)">
|
||||
<g id="track-pause" transform="matrix(1,0,0,1,-338.497,-111.176)">
|
||||
<rect x="464.497" y="245.176" width="95.007" height="95.01" style="fill:none;"/>
|
||||
<clipPath id="_clip1">
|
||||
<rect x="464.497" y="245.176" width="95.007" height="95.01"/>
|
||||
</clipPath>
|
||||
<g clip-path="url(#_clip1)">
|
||||
<g transform="matrix(1,0,0,1,462.002,242.677)">
|
||||
<path d="M49.9,2.5C23.6,2.8 2.1,24.4 2.5,50.4C2.9,76.5 24.7,98 50.3,97.5C76.7,96.9 97.7,75.7 97.5,49.8C97.3,23.7 75.7,2.3 49.9,2.5" style="fill:white;fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(1,0,0,1,338.582,110.729)">
|
||||
<path d="M170.225,165.93C170.225,164.274 168.881,162.93 167.225,162.93L159.923,162.93C158.268,162.93 156.923,164.274 156.923,165.93L156.923,198.318C156.923,199.974 158.268,201.318 159.923,201.318L167.225,201.318C168.881,201.318 170.225,199.974 170.225,198.318L170.225,165.93ZM190.906,165.93C190.906,164.274 189.562,162.93 187.906,162.93L180.605,162.93C178.949,162.93 177.605,164.274 177.605,165.93L177.605,198.318C177.605,199.974 178.949,201.318 180.605,201.318L187.906,201.318C189.562,201.318 190.906,199.974 190.906,198.318L190.906,165.93Z" style="fill:rgb(99,168,184);"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.8 KiB |
|
@ -0,0 +1,20 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg width="100%" height="100%" viewBox="0 0 96 96" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||
<g transform="matrix(1,0,0,1,0,-134)">
|
||||
<g id="track-play" transform="matrix(1,0,0,1,-464.497,-111.176)">
|
||||
<rect x="464.497" y="245.176" width="95.007" height="95.01" style="fill:none;"/>
|
||||
<clipPath id="_clip1">
|
||||
<rect x="464.497" y="245.176" width="95.007" height="95.01"/>
|
||||
</clipPath>
|
||||
<g clip-path="url(#_clip1)">
|
||||
<g transform="matrix(1,0,0,1,462.002,242.677)">
|
||||
<path d="M49.9,2.5C23.6,2.8 2.1,24.4 2.5,50.4C2.9,76.5 24.7,98 50.3,97.5C76.7,96.9 97.7,75.7 97.5,49.8C97.3,23.7 75.7,2.3 49.9,2.5" style="fill:white;fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(1,0,0,1,462.499,242.853)">
|
||||
<path d="M38,69C37,69.5 36.2,69 36.2,67.9L36.2,32.1C36.2,31 37,30.5 38,31L72,49C73,49.5 73,50.4 72,50.9L38,69Z" style="fill:rgb(99,168,184);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.4 KiB |
|
@ -123,6 +123,31 @@
|
|||
<div class="listenbuy"><em>listen</em> or <em>buy</em> on bandcamp</div>
|
||||
</a>
|
||||
</article>
|
||||
|
||||
<header class="blurgreen headlineshadow spaceup">
|
||||
<h1><em>highlighted</em> tracks
|
||||
<img
|
||||
class="icon"
|
||||
src="img/head-music.webp"
|
||||
srcset="img/head-music.webp 2x, img/head-music_1x.webp 1x"
|
||||
width="69"
|
||||
height="77"
|
||||
alt
|
||||
>
|
||||
</h1>
|
||||
</header>
|
||||
|
||||
<div class="transparent headlineshadow">
|
||||
<article class="track">
|
||||
<h2><span class="halfbubble whitebg elementshadow"></span>lastfuture <em> – rattlefox</em></h2>
|
||||
<div class="track-player" data-track="lastfuture-rattlefox"></div>
|
||||
</article>
|
||||
<article class="track">
|
||||
<h2><span class="halfbubble whitebg elementshadow"></span>lastfuture <em> – majesty</em></h2>
|
||||
<div class="track-player" data-track="lastfuture-majesty"></div>
|
||||
</article>
|
||||
</div>
|
||||
|
||||
</section>
|
||||
|
||||
<section class="contentitem box maincontent" id="experiments">
|
||||
|
|
|
@ -458,10 +458,17 @@ body {
|
|||
background-attachment: fixed;
|
||||
}
|
||||
|
||||
.elementshadow {
|
||||
box-shadow: 0 2px 1px rgba(0, 0, 0, 1);
|
||||
}
|
||||
.headlineshadow {
|
||||
text-shadow: 0 2px 1px rgba(0, 0, 0, 1);
|
||||
}
|
||||
|
||||
.spaceup {
|
||||
margin-top: 4rem;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: underline;
|
||||
transition: all 0.2s ease-in-out;
|
||||
|
@ -489,10 +496,6 @@ a {
|
|||
margin: 1.5rem;
|
||||
}
|
||||
|
||||
.whitebg {
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
.nowrap {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
@ -670,13 +673,12 @@ a {
|
|||
text-shadow: 0 2px 1px rgba(0, 100, 125, 1);
|
||||
}
|
||||
|
||||
.contentitem.invertedbox header h1 {
|
||||
.contentitem header.whitebg h1 {
|
||||
color: #4e8595;
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
.contentitem header h1 em,
|
||||
section.invertedbox h2 em {
|
||||
.contentitem header h1 em {
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
@ -700,12 +702,16 @@ section.invertedbox h2 em {
|
|||
font-weight: 500;
|
||||
}
|
||||
|
||||
.contentitem div.opaque h2 span.halfbubble {
|
||||
h2 span.halfbubble {
|
||||
height: 22px;
|
||||
width: 11px;
|
||||
border-bottom-right-radius: 11px;
|
||||
border-top-right-radius: 11px;
|
||||
display: inline-block;
|
||||
margin: 0 0.7rem -0.25rem 0;
|
||||
}
|
||||
|
||||
div.opaque h2 span.halfbubble {
|
||||
margin: 0 0.7rem -0.25rem -1.25rem;
|
||||
}
|
||||
|
||||
|
@ -733,7 +739,7 @@ section.invertedbox h2 em {
|
|||
background-image: url('img/play-btn.svg');
|
||||
background-position: center center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 4rem;
|
||||
background-size: 80px 80px;
|
||||
box-shadow: 0px 0px 6px rgba(0,0,0,0.3);
|
||||
}
|
||||
.paused-animation img {
|
||||
|
@ -774,6 +780,7 @@ article.album a {
|
|||
width: 100%;
|
||||
height: 120px;
|
||||
color: var(--text-color);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
article.album h2 {
|
||||
|
@ -838,14 +845,63 @@ article.album a:hover {
|
|||
height: 160px;
|
||||
}
|
||||
|
||||
.track h2 {
|
||||
font-size: 1.2em;
|
||||
}
|
||||
.track .halfbubble {
|
||||
margin-bottom: -0.125em;
|
||||
}
|
||||
.track-player {
|
||||
margin: 0.5rem 0 1.5rem;
|
||||
}
|
||||
.track-player .track-container {
|
||||
width: 400px;
|
||||
height: 80px;
|
||||
border-radius: 0.3rem;
|
||||
}
|
||||
.track-player .track-played, .track-player .track-unplayed {
|
||||
height: 100%;
|
||||
float: left;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 400px 80px;
|
||||
|
||||
}
|
||||
.track-player .play-button {
|
||||
display: block;
|
||||
height: 80px;
|
||||
width: 80px;
|
||||
float: right;
|
||||
background-position: center center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: contain;
|
||||
cursor: pointer;
|
||||
}
|
||||
.track-player .play-button.play {
|
||||
background-image: url('img/track-play.svg');
|
||||
}
|
||||
.track-player .play-button.pause {
|
||||
background-image: url('img/track-pause.svg');
|
||||
}
|
||||
.track-player .track-played {
|
||||
width: 0%;
|
||||
background-position: top left;
|
||||
background-image: none;
|
||||
}
|
||||
.track-player .track-unplayed {
|
||||
background-position: top right;
|
||||
width: 100%;
|
||||
background-image: none;
|
||||
}
|
||||
|
||||
/* backgrounds */
|
||||
|
||||
.whitebg {
|
||||
background-color: white;
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
.blurgreen {
|
||||
background-color: #437888;
|
||||
background-color: #1e3f2d;
|
||||
background-image: url('img/bg_blur.webp');
|
||||
background-repeat: no-repeat;
|
||||
background-attachment: fixed;
|
||||
|
|
After Width: | Height: | Size: 39 KiB |
After Width: | Height: | Size: 39 KiB |
After Width: | Height: | Size: 38 KiB |
After Width: | Height: | Size: 38 KiB |