2018.12.15 18:04 ES6学习中
Thejsway/chapter18 Coding time
<Bouncing ball>``(<Chronometer>)
原题:
Bouncing ball
The goal of this exercise is to make a basketball bounce across the screen. You can download the ball image here.
Start with the following HTML and CSS content.
<p>
<button id="start">Start</button>
<button id="stop" disabled>Stop</button>
</p>
<div id="frame">
<!-- Update the "src" attribute if you downloaded the image locally -->
<img id="ball" src="https://raw.githubusercontent.com/bpesquet/thejsway/master/resources/basketball.jpg">
</div>
#ball {
position: relative;
left: 0px;
top: 1px;
height: 111px;
}
Write the JavaScript code that makes the ball bounce horizontally.
With your solution, create a variable with values 1 or -1 that dictates the direction in which the ball should move.
与开始和停止计时类似。
出现问题:
1.无法停止动画。
(似乎是因为 balljump()
内部带有 requestAnimationFrame()
而重复启用。
改进代码:
const balljump = () => {
const weizhi = parseFloat(getComputedStyle(ball).top);
if (weizhi + ballheight >= 300 || weizhi <= 0) {
movement = -movement;
}
ball.style.top = weizhi + movement + 'px';
let a = requestAnimationFrame(balljump);
console.log(a);
};
尝试在 balljump()
调用时显示函数编号 结果为
故 balljump()
内部多次调用该函数 无法停止
2.多次点击开始会多次累加 requestAnimationFrame()
而导致动画速度加快。
3.
const balljump = () => {
const weizhi = parseFloat(getComputedStyle(ball).top);
if (weizhi + ballheight >= 300 || weizhi <= 0) {
movement = -movement;
}
ball.style.top = weizhi + movement + 'px';
requestAnimationFrame(balljump);
};
let animationId = 0;
let movement = 10;
const ball = document.getElementById('ball');
const ballheight = parseFloat(getComputedStyle(ball).height);
document.getElementById('start').addEventListener('click', e => {
if (animationId === 0) {
animationId = requestAnimationFrame(balljump);
}
e.target.disabled = true;
document.getElementById('stop').disabled = false;
});
document.getElementById('stop').addEventListener('click', e => {
cancelAnimationFrame(animationId);
animationId = 0;
e.target.disabled = true;
document.getElementById('start').disabled = false;
});
出现了打开即两个按钮都启用的状态。原因未知。
(似乎文件出了问题。注释掉所有的js代码依然两个按钮都启用,重开文件后解决)
const balljump = () => {
const weizhi = parseFloat(getComputedStyle(ball).top);
if (weizhi + ballheight >= 300 || weizhi <= 0) {
movement = -movement;
}
ball.style.top = weizhi + movement + 'px';
if (tostart != 0 || tostop != 0) {
if (tostart === 1) {
tostart = 0;
animationId = requestAnimationFrame(balljump);
}
if (tostop === 1) {
tostop = 0;
cancelAnimationFrame(balljump);
}
} else {
requestAnimationFrame(balljump);
}
};
let tostart = 0;
let tostop = 0;
let animationId = 0;
let movement = 10;
const ball = document.getElementById('ball');
const ballheight = parseFloat(getComputedStyle(ball).height);
document.getElementById('start').addEventListener('click', e => {
tostart = 1;
if (animationId === 0) {
animationId = requestAnimationFrame(balljump);
}
e.target.disabled = true;
document.getElementById('stop').disabled = false;
});
document.getElementById('stop').addEventListener('click', e => {
tostop = 1;
e.target.disabled = true;
document.getElementById('start').disabled = false;
});
尝试改写,添加 tostop
、tostart
变量来判断,将继续动画与停止动画判断放在了 balljump()
函数中。
结果:可以停止动画,但无法二次启动动画。原因未知。
在 cancelAnimationFrame()
函数之后重置 animationId
为 0
即可解决。
最终代码:
const balljump = () => {
const weizhi = parseFloat(getComputedStyle(ball).top);
if (weizhi + ballheight >= 300 || weizhi <= 0) {
movement = -movement;
}
ball.style.top = weizhi + movement + 'px';
if (tostart != 0 || tostop != 0) {
if (tostart === 1) {
tostart = 0;
animationId = requestAnimationFrame(balljump);
}
if (tostop === 1) {
tostop = 0;
cancelAnimationFrame(balljump);
animationId = 0;
}
} else {
requestAnimationFrame(balljump);
}
};
let tostart = 0;
let tostop = 0;
let animationId = 0;
let movement = 10;
const ball = document.getElementById('ball');
const ballheight = parseFloat(getComputedStyle(ball).height);
document.getElementById('start').addEventListener('click', e => {
tostart = 1;
if (animationId === 0) {
animationId = requestAnimationFrame(balljump);
}
e.target.disabled = true;
document.getElementById('stop').disabled = false;
});
document.getElementById('stop').addEventListener('click', e => {
tostop = 1;
e.target.disabled = true;
document.getElementById('start').disabled = false;
});
效果基本实现。