如何在单击播放按钮时开始我的雨的画布动画,反之亦然(单击暂停按钮时停止下雨)?
我真的很感谢您的帮助。
到目前为止,我可以在窗口加载后立即播放下雨动画,并且在与播放按钮交互时,背景中的音频是唯一播放的内容。
我不知道如何让雨动画开始,以便音频也与雨同步播放,反之亦然。
// 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>
答案 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
width
和height
,并将脚本放在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