Frontend Forever App
We have a mobile app for you to download and use. And you can unlock many features in the app.
Get it now
Intall Later
Run
HTML
CSS
Javascript
Output
Document
2000
ms
@charset "UTF-8"; @import url(https://fonts.googleapis.com/css?family=Nunito+Sans:300,400,600,700,800); *, :after, :before { box-sizing: border-box; padding: 0; margin: 0; } body { margin: 0 auto; background: #000; } #polyrythm { position: relative; min-width: 100px; min-height: 100px; max-height: clamp(100px, calc(100vh - 130px), 400px); max-width: clamp(100px, calc(100vw - 100px), 400px); } #soundIcon { cursor: pointer; background: none; color: #fff; padding: 10px; border-radius: 5px; position: absolute; bottom: 20px; right: 20px; padding: 5px; height: 50px; width: 50px; border: none; } .shapeSelections { display: flex; flex-direction: column; align-items: center; } .btn-row { display: flex; justify-content: center; margin-bottom: 10px; /* Adjust margin between button rows */ } .shapeSelections button { position: relative; height: 50px; width: 50px; margin: 5px; padding: 10px; background: none; cursor: pointer; border: none; } .shapeSelections button.active { border: 2px solid rgba(255, 255, 255, 0.2); } .shapeSelections button:hover { border: 2px solid rgba(255, 255, 255, 0.1); } .shapeSelections button:active { border: 2px solid rgba(0, 255, 255, 0.2); } .shapeSelections button svg { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); } .gonezo { opacity: 0; } .sVal { color: #fff; } .slider { width: 230px; cursor: grab; } .slider:active { cursor: grabbing; } /* Styling the slider for Chrome, Edge, and other WebKit-based browsers */ .slider { -webkit-appearance: none; appearance: none; width: 230px; height: 10px; background-color: #000; border-radius: 5px; outline: none; margin-bottom: 5px; } .slider::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 20px; height: 20px; background-color: #333; border-radius: 50%; } .slider::-webkit-slider-runnable-track { width: 100%; height: 10px; background-color: #333; border-radius: 5px; } /* Styling the slider for Firefox */ .slider::-moz-range-thumb { width: 20px; height: 20px; background-color: #333; border: none; border-radius: 50%; } .slider::-moz-range-track { width: 100%; height: 10px; background-color: #222; border-radius: 5px; } /* Styling the slider for Safari */ .slider::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 20px; height: 20px; transform: translateY(-5px); background-color: #333; border-radius: 50%; } .slider::-webkit-slider-runnable-track { width: 100%; height: 10px; background-color: #222; border-radius: 5px; }
console.log("Event Fired") // Initialize audio context and nodes globally const audioContext = new (window.AudioContext || window.webkitAudioContext)(); let oscillator = null; let gainNode = audioContext.createGain(); gainNode.connect(audioContext.destination); function playBeep(pitch, duration) { // Create oscillator if not already created if (!oscillator) { oscillator = audioContext.createOscillator(); oscillator.connect(gainNode); } else { // If oscillator is already started, return if (oscillator.state !== "stopped") { return; } } // Set pitch (in Hz) oscillator.frequency.value = pitch; // Start oscillator oscillator.start(); // Set volume to full gainNode.gain.setValueAtTime(1, audioContext.currentTime); // Fade out gainNode.gain.exponentialRampToValueAtTime( 0.001, audioContext.currentTime + duration / 1000 ); // Stop oscillator after duration setTimeout(function () { if (oscillator && oscillator.state !== "closed") { oscillator.stop(); oscillator = null; // Reset oscillator } }, duration); } let int2, int3, int4, int5; let bloops = false; let soundOn = false; function addBloops() { if (!bloops) { if (document.querySelector(".line").classList.contains("active")) { int2 = setInterval(() => { playBeep(220, 30); }, sliderValue / 2); } if (document.querySelector(".tri").classList.contains("active")) { int3 = setInterval(() => { playBeep(330, 30); }, sliderValue / 3); } if (document.querySelector(".square").classList.contains("active")) { int4 = setInterval(() => { playBeep(440, 30); }, sliderValue / 4); } if (document.querySelector(".pent").classList.contains("active")) { int5 = setInterval(() => { playBeep(220, 30); }, sliderValue / 5); } bloops = true; } } function clearSounds() { clearInterval(int2); clearInterval(int3); clearInterval(int4); clearInterval(int5); } function addSound(muted = false) { if (soundOn || muted) { document.querySelector("#a2").removeEventListener("repeatEvent", addBloops); document.querySelector("#an2").beginElement(); document.querySelector("#aan2").beginElement(); clearSounds(); soundOn = false; bloops = false; } else { document.querySelector("#a2").addEventListener("repeatEvent", addBloops); document.querySelector("#an1").beginElement(); document.querySelector("#aan1").beginElement(); soundOn = true; } } // Get all buttons const buttons = document.querySelectorAll(".shapeSelections button"); // Loop through each button and add click event listener buttons.forEach((button) => { button.addEventListener("click", () => { // Toggle active class for the clicked button button.classList.toggle("active"); clearSounds(); addSound(true); if (button.classList.contains("pent")) { document.querySelector("#p5").classList.toggle("gonezo"); document.querySelector("#c5").classList.toggle("gonezo"); } else if (button.classList.contains("square")) { document.querySelector("#p4").classList.toggle("gonezo"); document.querySelector("#c4").classList.toggle("gonezo"); } else if (button.classList.contains("tri")) { document.querySelector("#p3").classList.toggle("gonezo"); document.querySelector("#c3").classList.toggle("gonezo"); } else if (button.classList.contains("line")) { document.querySelector("#p2").classList.toggle("gonezo"); document.querySelector("#c2").classList.toggle("gonezo"); } }); }); let sliderValue = 2000; // Get the slider element const slider = document.querySelector(".slider"); // Get the span element for displaying slider value const sliderValueSpan = document.querySelector(".slider-value"); // Get all SVG elements with the "move" class const moveElements = document.querySelectorAll(".move"); // Add an input event listener to the slider slider.addEventListener("input", function () { // Get the slider value sliderValue = this.value; addSound(true); // Update the span element to display the current slider value sliderValueSpan.textContent = sliderValue; // Update the animation duration for each SVG element with the "move" class moveElements.forEach((element) => { // Update the animation duration based on the slider value element.setAttribute("dur", sliderValue + "ms"); }); });