简体   繁体   中英

How do I get my canvas animation to play/stop when the play/pause button is clicked?

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM