JSFiddle - React, Tailwind, and code Playground

by gustav75

HTML

<!DOCTYPE html>
<html lang="de">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Drum-Sequenzer</title>
    <style>
        body {
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            height: 100vh;
            background-color: #333;
            color: white;
            font-family: Arial, sans-serif;
            margin: 0;
        }
        .sequencer {
            display: grid;
            grid-template-columns: repeat(16, 1fr);
            grid-gap: 2px;
            margin: 20px 0;
        }
        .step {
            width: 40px;
            height: 40px;
            background-color: #555;
            border-radius: 4px;
            cursor: pointer;
        }
        .step.active {
            background-color: #ff5722;
        }
        .controls {
            margin: 20px;
        }
        button {
            padding: 10px 20px;
            margin: 0 10px;
            font-size: 16px;
            cursor: pointer;
            border: none;
            border-radius: 4px;
            background-color: #ff5722;
            color: white;
        }
        button:disabled {
            background-color: #777;
            cursor: not-allowed;
        }
    </style>
</head>
<body>
    <h1>Drum-Sequenzer</h1>
    
    <div id="kick" class="sequencer">
        <!-- Kick Sequencer -->
    </div>
    <div id="snare" class="sequencer">
        <!-- Snare Sequencer -->
    </div>
    <div id="hihat" class="sequencer">
        <!-- Hi-Hat Sequencer -->
    </div>
    
    <div class="controls">
        <button id="play">Play</button>
        <button id="stop" disabled>Stop</button>
    </div>
    
    <script src="script.js"></script>
</body>
</html>

JavaScript

const steps = 16;
const tempo = 120; // BPM (Beats per Minute)

const kickSequencer = document.getElementById('kick');
const snareSequencer = document.getElementById('snare');
const hihatSequencer = document.getElementById('hihat');

const kickSound = new Audio('https://static.wixstatic.com/mp3/efdc4b_25353dc62f3b41e1bd71001b22b767a9.wav');
const snareSound = new Audio('https://static.wixstatic.com/mp3/efdc4b_e79caa7bfe0a4b33a1acdb68badd9ae7.wav');
const hihatSound = new Audio('https://static.wixstatic.com/mp3/efdc4b_f34e4b39a7b546ac9e1d75b4f07f17d7.wav');

let isPlaying = false;
let currentStep = 0;
let interval;

function createSequencer(sequencerElement) {
    for (let i = 0; i < steps; i++) {
        const step = document.createElement('div');
        step.classList.add('step');
        step.dataset.step = i;
        sequencerElement.appendChild(step);

        step.addEventListener('click', () => {
            step.classList.toggle('active');
        });
    }
}

function playSequence() {
    interval = setInterval(() => {
        document.querySelectorAll('.step').forEach(step => {
            step.style.backgroundColor = step.classList.contains('active') ? '#ff5722' : '#555';
        });

        const kickSteps = kickSequencer.querySelectorAll('.step');
        const snareSteps = snareSequencer.querySelectorAll('.step');
        const hihatSteps = hihatSequencer.querySelectorAll('.step');

        if (kickSteps[currentStep].classList.contains('active')) {
            kickSound.currentTime = 0;
            kickSound.play();
        }
        if (snareSteps[currentStep].classList.contains('active')) {
            snareSound.currentTime = 0;
            snareSound.play();
        }
        if (hihatSteps[currentStep].classList.contains('active')) {
            hihatSound.currentTime = 0;
            hihatSound.play();
        }

        currentStep = (currentStep + 1) % steps;
    }, (60 / tempo) * 1000 / 4);
}

function stopSequence() {
   ...