Implementing Dynamic Image Rotation and Audio Playback Controls with Vanilla JavaScript
Core Technologies
This solution integrates the HTML5 Audio API with CSS Transforms to create an interactive user experience. The functionality relies on event listeners for input detection and DOM manipulation for state changes.
Media Control
The <audio> element is configured with properties such as src for resource loading, loop for repetition, and preload optimization. Modern browser security models often require a direct user gesture, like a click, before invoking media playback APIs.
Visual Animations
CSS3's transform property facilitates geometric manipulations without altering the document layout. By incrementally adjusting the degree value of rotate() within a timed loop, continuous motion is rendered. Properly managing the timer instance ensures animations can be paused or stoped efficiently.
Implementation Source Code
Markup Structure
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive Display</title>
<link rel="stylesheet" href="./styles.css">
</head>
<body>
<div class="display-area">
<span class="control-trigger">
<div class="btn-icon"></div>
</span>
</div>
<audio id="bg-track" src="./audio.mp3" preload="auto" loop></audio>
</body>
</html>
Styling Configuration
.display-area {
position: relative;
top: 150px;
left: 48vw;
width: 150px;
height: 150px;
border-radius: 50%;
border: 1px solid gray;
background: url('../img/content.jpg') no-repeat center center;
background-size: cover;
}
.control-trigger .btn-icon {
position: absolute;
top: 30px;
left: 30px;
width: 100px;
height: 100px;
display: none;
opacity: 0.5;
background: url('../img/start.png') no-repeat;
background-size: contain;
}
Logic Scripting
document.addEventListener('DOMContentLoaded', () => {
const toggleBtn = document.querySelector('.btn-icon');
const visualContainer = document.querySelector('.display-area');
const soundEngine = document.getElementById('bg-track');
let rotationAngle = 0;
let animationTimer = null;
let audioState = true;
// Show button when hovering over container
visualContainer.addEventListener('mouseenter', () => {
toggleBtn.style.display = 'block';
});
// Hide button when mouse leaves
visualContainer.addEventListener('mouseleave', () => {
toggleBtn.style.display = 'none';
});
// Handle interaction toggle
toggleBtn.addEventListener('click', (event) => {
event.stopPropagation();
if (audioState) {
soundEngine.pause();
clearInterval(animationTimer);
toggleBtn.style.backgroundImage = "url('./play.png')";
} else {
soundEngine.play();
startSpinning();
toggleBtn.style.backgroundImage = "url('./stop.png')";
}
audioState = !audioState;
});
function startSpinning() {
animationTimer = setInterval(() => {
rotationAngle += 1;
visualContainer.style.transform = `rotate(${rotationAngle}deg)`;
}, 100);
}
});
Functional Behavior
Hovering over the central image reveals the control interface. Activating the trigger initiates synchronized actions: the background music toggles between playing and pausing states, while the container begins or ceases rotating. The rotation logic increments an angle variable continuously until explicitly halted by clearing the interval ID.