From c4acccbb8564b3fc900cce746cb9acda3b4205f4 Mon Sep 17 00:00:00 2001 From: skelbon Date: Thu, 8 Aug 2024 17:36:04 +0100 Subject: [PATCH] latest update --- assets/svg/mute.svg | 2 +- index.html | 111 +++++++++++++++++++++--------- notes.txt | 19 +++-- src/script.js | 164 ++++++++++++++++++++++++++++++++++++-------- styles.css | 118 ++++++++++++++++++++++++++----- 5 files changed, 327 insertions(+), 87 deletions(-) diff --git a/assets/svg/mute.svg b/assets/svg/mute.svg index 3d91765..c5ae2ec 100755 --- a/assets/svg/mute.svg +++ b/assets/svg/mute.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/index.html b/index.html index 7728fd2..f8716e5 100644 --- a/index.html +++ b/index.html @@ -1,38 +1,83 @@ - - - - Conductor - - - - -
- -
-
-
-
-
- 15.5.2024 08:00:00 - 08:01:00 UTC -
- -
- -
+ + + + Conductor + + + + + +
+ +
- - - +
+
+ + +
+
+ +
+ The Conductor +
+
+ 15.5.2024 08:00:00 - 08:01:00 UTC + +
+ + +
+ +
+
+
+ +
+ +
+
+
+
+
+

+ The Conductor translates live lightning strikes from around the world into a graphic score for seven percussion instruments. + +

+ + +

+ The project was conceived and developed by the artist Mishka Henner between 2023 and 2024 with a team of musicians, sound artists and acoustics engineers during an artist's residency at Energy House 2.0 at the University of Salford. +

+

+ The Conductor was first performed at the University of Salford’s Acoustic Laboratories during the Sounds From the Other City Festival on 5 May 2024. +

+

+ Click here to read more about the project. Download a copy of the artist's graphic score here. +

+
+
+
+
+ Project Conception and Design by Mishka Henner. +
+ Data Capture, Web Design and Coding by Joe Gibson. +
+ Lightning data from Blitzortung.org +
+

+ With support from the University of Salford Art Collection in partnership with Open Eye Gallery, Liverpool as part of the LOOK Photo Biennial, and Castlefield Gallery, Manchester. Generously supported by Friends of Energy House Labs. +

+
+ +
+
+ + + + \ No newline at end of file diff --git a/notes.txt b/notes.txt index 8a11270..21f6b67 100644 --- a/notes.txt +++ b/notes.txt @@ -1,6 +1,15 @@ - - change title to timestamp - date and time - program - - add a tab in the date/time format - - Mishka gonna send a mute symbol - - Add circle logo - - Mishka gonna change up the samples +stop zooming issue - resize rules +mishka gonna send an x icon for the back behaviour +look at memory leak?? +make the sound and menu icons part of an 'app bar' along with the conductor logo +make the mid size the default size but double check the size on the phone isnt too small +refactor when it's all done +format the key as per the pdf +sort out the title size +sort out the blitzortung connection issue + + + + + diff --git a/src/script.js b/src/script.js index f78736d..ebd2032 100644 --- a/src/script.js +++ b/src/script.js @@ -2,32 +2,106 @@ import { Client, BrowserSocketFactory } from "./blitz.js"; import { loadInstruments } from "./instruments.js"; document.addEventListener("DOMContentLoaded", async () => { + let showing; + let audioContext; + let interacted = false; + let gainNode; + + function startAudio() { + audioContext = new (window.AudioContext || window.webkitAudioContext)(); + gainNode = audioContext.createGain(); + gainNode.gain.value = 0; + gainNode.connect(audioContext.destination); + } + + function muter() { + fadeOutVolume(); + } + + function unMute() { + startAudio(); + fadeInVolume(); + } + + function padZero(num) { + return num.toString().padStart(2, "0"); + } + + function setTitle() { + const now = new Date(); + const future = new Date(now.getTime() + 59 * 1000); // 59 seconds later + + const formattedDate = `${padZero(now.getDate())}.${padZero( + now.getMonth() + 1 + )}.${now.getFullYear()}`; + const formattedTime = `${padZero(now.getHours())}:${padZero( + now.getMinutes() + )}:${padZero(now.getSeconds())}`; + const formattedFutureTime = `${padZero(future.getHours())}:${padZero( + future.getMinutes() + )}:${padZero(future.getSeconds())}`; + + title.innerHTML = `${formattedDate}${formattedTime} - ${formattedFutureTime} UTC`; + } + function fadeInVolume() { gainNode.gain.setValueAtTime(0, audioContext.currentTime); // Start at 0 - gainNode.gain.linearRampToValueAtTime(1, audioContext.currentTime + 10); // Fade to full volume + gainNode.gain.linearRampToValueAtTime(1, audioContext.currentTime + 2); // Fade to full volume + } + function fadeOutVolume() { + gainNode.gain.setValueAtTime(1, audioContext.currentTime); // Start at 0 + gainNode.gain.linearRampToValueAtTime(0, audioContext.currentTime + 2); // Fade to full volume } function showMainContent() { - const loadingScreen = document.getElementById("loading-screen"); - const mainContent = document.getElementById("main-content"); - loadingScreen.classList.add("fade-out"); - loadingScreen.addEventListener("transitionend", (event) => { - if (event.propertyName === "opacity") { - loadingScreen.style.display = "none"; - mainContent.style.display = "flex"; - mainContent.style.opacity = "0"; - void mainContent.offsetWidth; - mainContent.classList.add("fade-in"); - mainContent.style.opacity = "1"; - fadeInVolume(); - } + setTitle(); + const mute = document.getElementById("mute"); + + mute.addEventListener("click", () => { + const mutedSrc = "/assets/svg/sound-on.svg"; + const unMutedSrc = "/assets/svg/mute.svg"; + interacted = !interacted; + interacted ? unMute() : muter(); + mute.src = interacted ? mutedSrc : unMutedSrc; + + startAudio(); + fadeInVolume(); }); + + fadeAndReplaceADiv("main-content", "loading-screen"); + fadeAndReplaceADiv("buttons", "buttons"); + showing = "main-content"; + + document.getElementById("menu-button").onclick = function () { + console.log(showing); + toggleInfo(); + }; } - const audioContext = new (window.AudioContext || window.webkitAudioContext)(); - const gainNode = audioContext.createGain(); - gainNode.gain.value = 0; - gainNode.connect(audioContext.destination); + function toggleInfo() { + if (showing === "main-content") { + fadeAndReplaceADiv("about-content", "main-content"); + cleanUpAndRestart(); + showing = "about-content"; + } else { + fadeAndReplaceADiv("main-content", "about-content"); + showing = "main-content"; + } + } + + function fadeAndReplaceADiv(innyDivId, outtyDivId) { + const outty = document.getElementById(outtyDivId); + const inny = document.getElementById(innyDivId); + outty.classList.remove("fade-in"); + outty.classList.add("fade-out"); + + outty.style.display = "none"; + inny.style.display = "flex"; + inny.style.opacity = "0"; + void inny.offsetWidth; + inny.classList.add("fade-in"); + inny.style.opacity = "1"; + } const socketFactory = new BrowserSocketFactory(); let client = new Client(socketFactory); @@ -44,7 +118,31 @@ document.addEventListener("DOMContentLoaded", async () => { let currStaveNumber = 1; const instruments = await loadInstruments(); + console.log(instruments); + const instNames = Object.keys(instruments); + showMainContent(); + + /*** + * add the instrument images and names into the about section + * + */ + + const instrumentsKey = document.getElementById("instrument-key-div"); + for (const instrument of instNames) { + console.log(instrument); + const keyDiv = document.createElement("div"); + const keySvg = document.createElement("object"); + const keyName = document.createElement("div"); + keyName.innerText = instrument.toUpperCase(); + keySvg.type = "image/svg+xml"; + keySvg.data = instruments[instrument].image; + keyDiv.appendChild(keySvg); + keyDiv.appendChild(keyName); + keyDiv.classList.add("instrument-key"); + instrumentsKey.appendChild(keyDiv); + } + const numStaves = 6; const sheetWindow = document.getElementById("music-window"); @@ -71,31 +169,37 @@ document.addEventListener("DOMContentLoaded", async () => { } }); - const cleanUpAndRestart = () => { + const cleanUpAndRestart = (reload = false) => { const icons = document.querySelectorAll(".event-icon"); const timeIndicator = document.getElementById("time-indicator"); icons.forEach((icon) => { icon.classList.add("fade-out"); icon.addEventListener("transitionend", () => { icon.remove(); - currStaveNumber = 1; }); }); - location.reload(); + currStaveNumber = 1; + setTitle(); + if (reload) location.reload(); }; - window.addEventListener("orientationchange", cleanUpAndRestart); + window.addEventListener("orientationchange", () => { + cleanUpAndRestart(true); + }); const playSound = (instrument) => { - const source = audioContext.createBufferSource(); - const samples = instrument.samples; - const sampleKeys = Object.keys(samples); - const numSamples = sampleKeys.length; - const ramdomKey = sampleKeys[Math.floor(Math.random() * (numSamples - 1))]; + if (interacted) { + const source = audioContext.createBufferSource(); + const samples = instrument.samples; + const sampleKeys = Object.keys(samples); + const numSamples = sampleKeys.length; + const ramdomKey = + sampleKeys[Math.floor(Math.random() * (numSamples - 1))]; - source.buffer = samples[`${ramdomKey}`]; // Example: Play the 'Gong' sound - source.connect(audioContext.destination); - source.start(); + source.buffer = samples[`${ramdomKey}`]; // Example: Play the 'Gong' sound + source.connect(gainNode); + source.start(); + } }; const placeIcon = (instrument) => { diff --git a/styles.css b/styles.css index 9d7d1f9..1e66edf 100644 --- a/styles.css +++ b/styles.css @@ -2,16 +2,15 @@ body { display: flex; flex-direction: column; - /* justify-content: center; */ align-items: center; background-color: rgb(24, 24, 24); - position: absoulute; height: 100vh; } #main-content { position: absolute; width: 100%; + max-width: 800px; height: 100%; display: none; flex-direction: column; @@ -19,8 +18,28 @@ body { align-items: center; opacity: 0; transition: opacity 2s ease; - } + +#about-content { + position: relative; + flex-direction: column; + display: none; + width: 80vw; + max-width: 700px; + padding-right: 10px; + height: 100%; + color: #fff; + /* justify-content: center; */ + align-items: center; + font-family: 'Courier'; + font-size: 12pt; + line-height: 1.2; + margin: 20px; + opacity: 0; + transition: opacity 2s ease; + +} + #loading-screen { position: absolute; width: 100%; @@ -31,14 +50,22 @@ body { align-items: center; color: #fff; transition: opacity 1s ease; - } + +#buttons { + display: none; + opacity: 0; + transition: opacity 1s ease; +} + + .logo { color: #fff; width: 20%; height: 20%; animation: rotate360 10s linear infinite; } + .loading { font-family: Helvetica; font-size: 10pt; @@ -50,30 +77,85 @@ body { min-width: 10px; } +.instruments-key { + position: relative; + display: flex; + margin: 8px; +padding-top: 8% ; +padding-bottom: 8% ; + flex-direction: row; + align-content: center; + justify-content: space-around; +} + +.instrument-key { + display: flex; + flex-direction: column; + vertical-align: baseline; + justify-content: space-between; + width: 25px; + font-size: xx-small; + margin: 0; + +} .sheet-music-window { position: relative; - width: 80vw; max-width: 700px; height: 70%; margin: 0; background-color: rgb(24,24,24); margin-bottom: 100px; - /* overflow: hidden; */ } -.title{ - position: relative; - align-content: center; - max-width: 500px; - width: auto; - height: 15%; +.conductor-title{ + width: 40%; +} + +.menu { + position: fixed; + padding: 40px; + width: 21px; + top: 0; + left: 0; + flex: 0 0 auto; + z-index: 99; +} + +.audio{ + position: fixed; + padding: 40px; + width: 20px; + top: 0; + right: 0; + flex: 0 0 auto; + z-index: 99; +} + +.title{ + top: 30px; + width: 30%; + margin: 30px; + text-align: center; color: white; background-color: rgb(24,24,24); /* height: 20vh; */ font-family: Helvetica; - font-size: 10pt; - + font-size: 1.4vw; +} + +.title-title { + font-family: Helvetica; + color: #fff; + font-size: 1.5vw;; +} + +.production-credits { + font-size: smaller; +} + +.tab-space::before { + content: '\00a0\00a0\00a0\00a0\00a0\00a0'; /* 6 non-breaking spaces */ } .stave-wrapper { @@ -88,12 +170,13 @@ body { top: 0; left: 0; position: absolute; - width: 2px; /* Adjust width of SVG as needed */ - height: 100%; /* Adjust height of SVG as needed */ + width: 2px; + /* height: 100%; */ animation: moveRight 10s linear infinite; - z-index: 2; /* Ensure it is above other elements */ + z-index: 2; } + .fade-in { opacity: 1; } @@ -101,7 +184,6 @@ body { .fade-out { opacity: 0; transition: opacity 1s ease; - } @keyframes rotate360 {