0%

start and stop

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.

image-20201013184742806

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() 调用时显示函数编号 结果为

image-20201013184742806

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;
});

尝试改写,添加 tostoptostart 变量来判断,将继续动画与停止动画判断放在了 balljump() 函数中。
结果:可以停止动画,但无法二次启动动画。原因未知。
cancelAnimationFrame() 函数之后重置 animationId0 即可解决。

最终代码:

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;
});

效果基本实现。