单击播放/暂停按钮时,如何让我的画布动画播放/停止?

时间:2021-04-24 04:17:37

标签: javascript function animation canvas onclick

如何在单击播放按钮时开始我的雨的画布动画,反之亦然(单击暂停按钮时停止下雨)?

我真的很感谢您的帮助。

到目前为止,我可以在窗口加载后立即播放下雨动画,并且在与播放按钮交互时,背景中的音频是唯一播放的内容。

我不知道如何让雨动画开始,以便音频也与雨同步播放,反之亦然。

// 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(r.x, r.y);
    context.lineTo(r.x, 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 (r.y > 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>

1 个答案:

答案 0 :(得分:0)

首先,音频文件在本地对我不起作用(我下载了自己的 mp3 - 我现在正在努力让它工作),所以我专注于播放/暂停画布动画而忽略了声音功能.让我们从 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>

您会看到我做了一些事情来正确显示 canvas。无论出于何种原因,我都看不到您的按钮,并且画布显示为空白。我决定inline CSS widthheight,并将脚本放在body 中。

此外,由于我们忽略了声音功能,我将该函数重命名为 startStopRain() 以在您的 JS 文件中更有意义。我们接下来谈谈:

// 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()
    }
}

您的初衷是在 btn 上使用两个类名,以便您可以区分播放/暂停。虽然有使用多个类名的用例,但我个人不认为这是其中之一。相反,我在脚本中使用了一个全局 isClicked 变量,以便我可以控制函数的流程。

从上到下跟踪 isClicked 变量以更好地了解我如何使用它来调用/停止函数。减去初始化顶部的变量,您会注意到它只出现在两个函数中:draw()startStopRain()

编辑:声音的流量控制应该没有什么不同。您可以使用相同的 isClicked boolean 值来确定何时应该播放声音。如果你愿意,我可以更新它以反映这一点,但老实说,这对你来说是一个很好的做法。此外,我将按钮的 id 更改为 audio-1,因为原始代码是通过特定的 id

选择元素