How do I get my canvas animation of the rain to start when the play button is clicked and vice versa (stop the rain when the pause button is clicked)?
I really would appreciate a helping hand.
So far I have the rain animation to play as soon as the window is loaded and the audio in the background is the only thing that plays when interacting with the play button.
I'm not sure how to go about getting the rain animation to start so that the audio also plays in sync with the rain and vice versa.
// Get the canvas and context and store in variables var canvas = document.getElementById("canvas"); var context = canvas.getContext("2d"); // Set canvas dimensions to window height and width canvas.width = window.innerHeight; canvas.height = window.innerHeight; // Generate the raindrops and apply attributes var rainNum = 200; // max raindrops var rainDrops = []; let isClicked = true; // Loop through the empty raindrops and apply attributes for (var i = 0; i < rainNum; i++) { rainDrops.push({ x: Math.random() * canvas.width, y: Math.random() * canvas.height, }) } // Draw raindrops onto canvas function draw() { context.clearRect(0, 0, canvas.width, canvas.height); context.lineWidth = 0.1; context.strokeStyle = "white"; context.beginPath(); for (var i = 0; i < rainNum; i++) { var r = rainDrops[i]; context.moveTo(rx, r.y); context.lineTo(rx, r.y + 30); rainDrops[i].y += 13; context.stroke(); } if (isClicked == true) { moveRain(); } else { return false } window.requestAnimationFrame(draw); } window.requestAnimationFrame(draw); // Animate the raindrops function moveRain() { for (var i = 0; i < rainNum; i++) { // Store current raindrops var r = rainDrops[i]; // If the rain reaches the bottom, send a new one to the top if (ry > canvas.height) { rainDrops[i] = { x: Math.random() * canvas.width, y: 0 }; } } } // Create a reference to the audio var audioOne = document.querySelector("#audio-1"); function playAudio() { if (isClicked == true) { isClicked = false audioOne.pause(); btn.className = "play"; } else if (isClicked == false) { isClicked = true audioOne.play(); btn.className = "pause"; draw() } }
html { height: 100%; width: 100%; } body { height: 100vh; width: 100vw; margin: 0; padding: 0; overflow: hidden; } canvas { height: 100%; width: 100%; background-color: transparent; position: absolute; z-index: 10; } #sky-top { height: 100%; width: 100%; position: absolute; z-index: 1; animation: lightning 20s ease-in-out infinite; } @keyframes lightning { /****** This will create a lightning effect every 20 seconds ******/ 0% { background-color: rgb(46, 46, 46); } 6.25% { background-color: rgb(46, 46, 46); } 8% { background-color: rgb(255, 255, 255); } 9% { background-color: rgb(46, 46, 46); } 11% { background-color: rgb(255, 255, 255); } 30% { background-color: rgb(46, 46, 46); } 100% { background-color: rgb(46, 46, 46); } } #sky-bottom { height: 100%; width: 100%; position: absolute; z-index: 2; background: linear-gradient(rgba(255, 255, 255, 0), rgb(45, 45, 45)); }.center-container { position: absolute; top: 0; left: 0; width: 100%; height: 100%; text-align: center; z-index: 20; background-color: transparent; }.button-center { position: absolute; top: 40%; -webkit-transform: translateY(-50%); -moz-transform: translateY(-50%); -ms-transform: translateY(-50%); -o-transform: translateY(-50%); transform: translateY(-50%); -webkit-transform: translateX(-50%); -moz-transform: translateX(-50%); -ms-transform: translateX(-50%); -o-transform: translateX(-50%); transform: translateX(-50%); }.center-container:after, .button-center { display: inline-block; vertical-align: middle; } #btn { height: 130px; width: 130px; border: none; background-size: 100% 100%; outline: none; }.play { background: url('../image/play-button.png'); border-radius: 50%; cursor: pointer; -webkit-filter: drop-shadow(2px 2px 2px #666666); filter: drop-shadow(2px 2px 2px #666666); }.pause { background: url('../image/pause-button.png'); border-radius: 50%; cursor: pointer; -webkit-filter: drop-shadow(2px 2px 2px #666666); filter: drop-shadow(2px 2px 2px #666666); }
<,DOCTYPE html> <html lang="en"> <head> <title>Rain</title> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width. initial-scale=1.0"> <meta name="description" content="Relax your mind with some rain and thunder."> <link href="css/styles.css" type="text/css" rel="stylesheet"> </head> <body> <div id="sky-top"></div> <div id="sky-bottom"></div> <canvas id="canvas"></canvas> <div class="center-container"> <div class="button-center"> <button id="btn" class="play" class="pause" onclick="playAudio()"></button> </div> <audio src="audio/rain-and-thunder.mp3" id="audio-1" loop="loop" type="audio/mp3"></audio> </div> <script src="js/script.js"></script> </body> </html>
First off, the audio file won't work for me here locally (I downloaded my own mp3 - I am working on getting it to work now), so I focused on playing/pausing the canvas animation and ignored the sound functionality. Let's start with the HTML:
<html>
<head>
<link rel = "stylesheet"
type = "text/css"
href = "index.css" />
</head>
<body>
<canvas id="canvas"></canvas>
<div class="center-container">
<div class="button-center">
<button id="btn" class="play" class="pause" onclick="playAudio()"></button>
</div>
<audio loop="loop" id="audio-1" width="100%" height="auto">
<source src="audio/rain-and-thunder.mp3" type="audio/mpeg">
</audio>
</div>
</body>
<script src='index.js'></script>
</html>
You'll see I did a few things to display the canvas
properly. For whatever reason, I couldn't see your button and the canvas was showing up blank. I decided to inline CSS
the width
and height
, as well as put the script within the body
.
Also, since we are ignoring the sound functionality, I renamed the function to startStopRain()
to make more sense in your JS file. Let's talk about that next:
// Get the canvas and context and store in variables
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
var audioOne = document.getElementById("audio-1");
// Set canvas dimensions to window height and width
canvas.width = window.innerHeight;
canvas.height = window.innerHeight;
// Generate the raindrops and apply attributes
var rainNum = 200; // max raindrops
var rainDrops = [];
let isClicked = false
// Loop through the empty raindrops and apply attributes
for(var i = 0; i < rainNum; i ++)
{
rainDrops.push({
x: Math.random() * canvas.width,
y: Math.random() * canvas.height,
})
}
// Draw raindrops onto canvas
function draw()
{
context.clearRect(0, 0, canvas.width, canvas.height);
context.lineWidth = 0.1;
context.strokeStyle = "red";
context.beginPath();
for(var i = 0; i < rainNum; i ++)
{
var r = rainDrops[i];
context.moveTo(r.x, r.y);
context.lineTo(r.x, r.y + 30);
rainDrops[i].y += 13;
context.stroke();
}
if (isClicked == true) {
moveRain();
} else{
return false
}
document.getElementById("canvas").onclick = moveRain();
window.requestAnimationFrame(draw);
}
window.requestAnimationFrame(draw);
// Animate the raindrops
function moveRain(){
for(var i = 0; i < rainNum; i++)
{
// Store current raindrops
var r = rainDrops[i];
// If the rain reaches the bottom, send a new one to the top
if(r.y > canvas.height) {
rainDrops[i] = {x: Math.random() * canvas.width, y: 0};
}
}
}
// Create a reference to the audio
// need to figure out why the audio wont play - this is new to me :D
function playAudio(){
audioOne.play();
if (isClicked == true){
isClicked = false
audioOne.pause();
} else if (isClicked == false){
isClicked = true
audioOne.play();
draw()
}
}
Your original intent was to use two class names on the btn
so you could distinguish between play/pause. While there are use cases for using multiple class names, I don't personally believe this is one of them. Instead, I used a global isClicked
variable in the script so I could control the flow of the functions.
Follow the isClicked
variable from top to bottom to better understand how I used it to call/stop functions. Minus initializing the variable at the top, you'll notice it shows up in only two functions: draw()
and startStopRain()
.
EDIT: The flow control for the sound should be no different. You can use the same isClicked
boolean
value to determine when the sound should be played or not. If you want, I can update it to reflect that but truthfully, that would be good practice for you. Also, I changed the id
of the button to audio-1
since the original code was selecting the element via that specific id
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.