From afa77dad8862decc1ffac3ee6344be8c6f243ee4 Mon Sep 17 00:00:00 2001 From: Alina Marquardt Date: Thu, 15 May 2025 22:49:14 +0200 Subject: [PATCH] track player styling fixes for mobile, beautified documents --- public_html/functions.js | 294 ++++++++++++++++++++++++--------------- public_html/index.html | 70 ++-------- public_html/style.css | 44 ++++-- 3 files changed, 225 insertions(+), 183 deletions(-) diff --git a/public_html/functions.js b/public_html/functions.js index 0c98f90..6687b52 100644 --- a/public_html/functions.js +++ b/public_html/functions.js @@ -1,115 +1,135 @@ // gif player document.querySelectorAll('.paused-animation').forEach(el => { - el.addEventListener('click', () => { - el.classList.toggle('active'); - }); + el.addEventListener('click', () => { + el.classList.toggle('active'); + }); }); // track players const players = document.querySelectorAll('.track-player'); + +function updateAllWaveformWidths() { + players.forEach(player => { + const container = player.querySelector('.track-container'); + if (container) update_player_waveform_widths(container); + }); +} + +document.addEventListener('DOMContentLoaded', updateAllWaveformWidths); +window.addEventListener('resize', updateAllWaveformWidths); + players.forEach(player => { - const trackName = player.getAttribute('data-track'); + 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 = ` + const wrapper = document.createElement('div'); + wrapper.className = 'track'; + wrapper.innerHTML = `
`; - player.appendChild(wrapper); + 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 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); + 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'); - } - } - }); + 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(); + // 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 }); + 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; - } + 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'); - } - }); + 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'); - }); + 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; + 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); + const portion = Math.min(Math.max(clickX / width, 0), 1); - audio.currentTime = portion * audio.duration; - }); + audio.currentTime = portion * audio.duration; + }); - audio.addEventListener('timeupdate', () => { - const portion = audio.duration ? audio.currentTime / audio.duration : 0; - update_play_position(played, unplayed, portion); - }); + audio.addEventListener('timeupdate', () => { + const portion = audio.duration ? audio.currentTime / audio.duration : 0; + update_play_position(played, unplayed, portion); + }); + update_play_position(played, unplayed, 0.03); }); 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 + "%"; + const playedPercent = portion * 100; + const unplayedPercent = 100 - playedPercent; + played_element.style.width = playedPercent + "%"; + unplayed_element.style.width = unplayedPercent + "%"; +} + +function update_player_waveform_widths(player_container_element) { + const trackWidth = player_container_element.offsetWidth; + const played_element = player_container_element.querySelector('.track-played'); + const unplayed_element = player_container_element.querySelector('.track-unplayed'); + played_element.style.backgroundSize = trackWidth + "px 80px"; + unplayed_element.style.backgroundSize = trackWidth + "px 80px"; } @@ -158,23 +178,53 @@ window.onload = function() { // Create vertices const vertices = [ - [-1, t, 0], [1, t, 0], [-1, -t, 0], [1, -t, 0], - [0, -1, t], [0, 1, t], [0, -1, -t], [0, 1, -t], - [t, 0, -1], [t, 0, 1], [-t, 0, -1], [-t, 0, 1] + [-1, t, 0], + [1, t, 0], + [-1, -t, 0], + [1, -t, 0], + [0, -1, t], + [0, 1, t], + [0, -1, -t], + [0, 1, -t], + [t, 0, -1], + [t, 0, 1], + [-t, 0, -1], + [-t, 0, 1] ].map(v => new THREE.Vector3(v[0] * normRadius, v[1] * normRadius, v[2] * normRadius)); // Define edges (pairs of vertex indices) const edges = [ - [0, 11], [0, 5], [0, 1], [0, 7], [0, 10], - [1, 5], [1, 7], [1, 8], [1, 9], - [2, 3], [2, 4], [2, 6], [2, 10], [2, 11], - [3, 4], [3, 6], [3, 8], [3, 9], - [4, 5], [4, 9], [4, 11], - [5, 9], [5, 11], - [6, 7], [6, 8], [6, 10], - [7, 8], [7, 10], + [0, 11], + [0, 5], + [0, 1], + [0, 7], + [0, 10], + [1, 5], + [1, 7], + [1, 8], + [1, 9], + [2, 3], + [2, 4], + [2, 6], + [2, 10], + [2, 11], + [3, 4], + [3, 6], + [3, 8], + [3, 9], + [4, 5], + [4, 9], + [4, 11], + [5, 9], + [5, 11], + [6, 7], + [6, 8], + [6, 10], + [7, 8], + [7, 10], [8, 9], /*[8, 10],*/ - /*[9, 11],*/ [10, 11] + /*[9, 11],*/ + [10, 11] ]; return { @@ -224,7 +274,7 @@ window.onload = function() { // 1. A thin cylindrical tube with back material that ignores depth // 2. A cylindrical tube with front material that uses depth testing const backRadius = 0.025; // thin for back lines - const frontRadius = 0.035; // thick for front lines + const frontRadius = 0.035; // thick for front lines icosa.edges.forEach((edge, index) => { const start = icosa.vertices[edge[0]]; @@ -261,10 +311,26 @@ window.onload = function() { // Define faces of icosahedron (each is a triangle of vertex indices) const faces = [ - [0, 11, 5], [0, 5, 1], [0, 1, 7], [0, 7, 10], [0, 10, 11], - [1, 5, 9], [5, 11, 4], [11, 10, 2], [10, 7, 6], [7, 1, 8], - [3, 9, 4], [3, 4, 2], [3, 2, 6], [3, 6, 8], [3, 8, 9], - [4, 9, 5], [2, 4, 11], [6, 2, 10], [8, 6, 7], [9, 8, 1] + [0, 11, 5], + [0, 5, 1], + [0, 1, 7], + [0, 7, 10], + [0, 10, 11], + [1, 5, 9], + [5, 11, 4], + [11, 10, 2], + [10, 7, 6], + [7, 1, 8], + [3, 9, 4], + [3, 4, 2], + [3, 2, 6], + [3, 6, 8], + [3, 8, 9], + [4, 9, 5], + [2, 4, 11], + [6, 2, 10], + [8, 6, 7], + [9, 8, 1] ]; // Create invisible faces for depth testing @@ -279,7 +345,7 @@ window.onload = function() { geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3)); const faceMesh = new THREE.Mesh(geometry, faceMaterial); - faceMesh.scale.set(0.975,0.975,0.975); + faceMesh.scale.set(0.975, 0.975, 0.975); faceMesh.renderOrder = 0; // Render first for depth buffer group.add(faceMesh); @@ -288,19 +354,19 @@ window.onload = function() { const internalMesh3 = new THREE.Mesh(geometry, internalMaterial); const internalMesh4 = new THREE.Mesh(geometry, internalMaterial); const internalMesh5 = new THREE.Mesh(geometry, internalMaterial); - internalMesh1.scale.set(0.85,0.85,0.85); + internalMesh1.scale.set(0.85, 0.85, 0.85); internalMesh1.renderOrder = 1; // Render between front and back group.add(internalMesh1); - internalMesh2.scale.set(0.65,0.65,0.65); + internalMesh2.scale.set(0.65, 0.65, 0.65); internalMesh2.renderOrder = 1; // Render between front and back group.add(internalMesh2); - internalMesh3.scale.set(0.5,0.5,0.5); + internalMesh3.scale.set(0.5, 0.5, 0.5); internalMesh3.renderOrder = 1; // Render between front and back group.add(internalMesh3); - internalMesh4.scale.set(0.4,0.4,0.4); + internalMesh4.scale.set(0.4, 0.4, 0.4); internalMesh4.renderOrder = 1; // Render between front and back group.add(internalMesh4); - internalMesh5.scale.set(0.3,0.3,0.3); + internalMesh5.scale.set(0.3, 0.3, 0.3); internalMesh5.renderOrder = 1; // Render between front and back group.add(internalMesh5); }); @@ -315,7 +381,7 @@ window.onload = function() { const length = direction.length(); // Create cylinder - const geometry = new THREE.CylinderGeometry(radius, radius, length*lengthmultiplier, 4, 1); + const geometry = new THREE.CylinderGeometry(radius, radius, length * lengthmultiplier, 4, 1); // By default, cylinder is along Y-axis, so rotate it geometry.rotateX(Math.PI / 2); @@ -340,26 +406,26 @@ window.onload = function() { let lastFrameTime = 0; const targetFPS = 20; - const animMultiplier = 30/targetFPS; + const animMultiplier = 30 / targetFPS; const frameDuration = 1000 / targetFPS; // Animation function function animate(now) { - requestAnimationFrame(animate); + requestAnimationFrame(animate); - const delta = now - lastFrameTime; - if (delta < frameDuration) return; + const delta = now - lastFrameTime; + if (delta < frameDuration) return; - lastFrameTime = now; + lastFrameTime = now; - // Rotate if animation is enabled - if (animating) { - icosahedronGroup.rotation.x -= 0.002 * animMultiplier; - icosahedronGroup.rotation.y += 0.004 * animMultiplier; - icosahedronGroup.rotation.z -= 0.001 * animMultiplier; - } + // Rotate if animation is enabled + if (animating) { + icosahedronGroup.rotation.x -= 0.002 * animMultiplier; + icosahedronGroup.rotation.y += 0.004 * animMultiplier; + icosahedronGroup.rotation.z -= 0.001 * animMultiplier; + } - renderer.render(scene, camera); + renderer.render(scene, camera); } // Start animation diff --git a/public_html/index.html b/public_html/index.html index 9e8e084..b1b9e0c 100644 --- a/public_html/index.html +++ b/public_html/index.html @@ -12,8 +12,8 @@ - - + + @@ -50,28 +50,14 @@

music releases - +

- album cover for the lastfuture album signal to noise + album cover for the lastfuture album signal to noise

lastfuture signal to noise

listen or buy on bandcamp
@@ -80,14 +66,7 @@
- album cover for the lastfuture album dreamshifter + album cover for the lastfuture album dreamshifter

lastfuture dreamshifter

listen or buy on bandcamp
@@ -95,14 +74,7 @@
- album cover for the lastfuture track misinterpreter + album cover for the lastfuture track misinterpreter

lastfuture misinterpreter

listen or buy on bandcamp
@@ -111,29 +83,15 @@
-

highlighted tracks - +

highlight tracks +

@@ -153,14 +111,7 @@

from the lab - +

@@ -187,4 +138,5 @@
+ diff --git a/public_html/style.css b/public_html/style.css index 7745d89..25f3f90 100644 --- a/public_html/style.css +++ b/public_html/style.css @@ -461,6 +461,7 @@ body { .elementshadow { box-shadow: 0 2px 1px rgba(0, 0, 0, 1); } + .headlineshadow { text-shadow: 0 2px 1px rgba(0, 0, 0, 1); } @@ -534,7 +535,7 @@ a { font-size: 1.125rem; font-style: italic; font-weight: 300; - transition: margin 0.25s, padding 0,25s; + transition: margin 0.25s, padding 0.25s; } .sidebaritem a { @@ -698,6 +699,7 @@ a { width: 100%; position: relative; } + .contentitem div.opaque h2 em { font-weight: 500; } @@ -731,37 +733,45 @@ div.opaque h2 span.halfbubble { /* height: 7rem; */ cursor: pointer; } + .paused-animation .play-btn { position: absolute; width: 100%; height: 100%; - background-color: rgba(99,150,180,0.2); + background-color: rgba(99, 150, 180, 0.2); background-image: url('img/play-btn.svg'); background-position: center center; background-repeat: no-repeat; background-size: 80px 80px; - box-shadow: 0px 0px 6px rgba(0,0,0,0.3); + box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.3); } + .paused-animation img { display: block; width: auto; height: 100%; margin: 0; } + .paused-animation .anim { display: none; } + .paused-animation.active { height: auto; } -.paused-animation.active .poster-frame, .paused-animation.active .play-btn { + +.paused-animation.active .poster-frame, +.paused-animation.active .play-btn { display: none; } + .paused-animation.active .anim { display: block; } + .watchface { - width: calc( ( 100% / 2 ) - 0.6rem ); + width: calc((100% / 2) - 0.6rem); margin: 0.325rem 0.3rem; height: auto; display: block; @@ -838,7 +848,7 @@ img.albumcover { float: left; margin-right: 1.4rem; z-index: 10; - box-shadow: 3px 0px 6px rgba(0,0,0,0.15); + box-shadow: 3px 0px 6px rgba(0, 0, 0, 0.15); } article.album a:hover { @@ -848,24 +858,32 @@ article.album a:hover { .track h2 { font-size: 1.2em; } + .track .halfbubble { margin-bottom: -0.125em; } + .track-player { + position: relative; margin: 0.5rem 0 1.5rem; } + .track-player .track-container { width: 400px; + max-width: calc(100% - 95px); height: 80px; border-radius: 0.3rem; } -.track-player .track-played, .track-player .track-unplayed { + +.track-player .track-played, +.track-player .track-unplayed { height: 100%; + width: 100%; float: left; background-repeat: no-repeat; background-size: 400px 80px; - } + .track-player .play-button { display: block; height: 80px; @@ -876,17 +894,21 @@ article.album a:hover { 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%; @@ -958,6 +980,7 @@ article.album a:hover { .contentitem { max-width: 495px; } + #music { flex: 1; order: 2; @@ -994,7 +1017,7 @@ article.album a:hover { } .sidebaritem { - margin-left: calc( ( 100% - 210px ) / 2 ); + margin-left: calc((100% - 210px) / 2); } .sidebaritem#greeting #icosahedron-container { @@ -1025,7 +1048,8 @@ article.album a:hover { padding-left: 1rem; } - .sidebaritem#findme .line2, .sidebaritem#findme .line3 { + .sidebaritem#findme .line2, + .sidebaritem#findme .line3 { margin-top: 0.2em; } }