Bouncing ball - test
by jonahe
HTML
<div id="app"></div>
CSS
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
}
.arena {
background: yellow;
border: 1px solid teal;
}
.ball {
display: flex;
justify-content: center;
align-items: center;
background: red;
color: white;
font-weight: bold;
}
React
const stageX = 300;
const stageY = 200;
const ballDiameter = 30;
class TodoApp extends React.Component {
constructor(props) {
super(props);
this.state = { velocity: [-5,-2], x: 40, y: 20};
this.updatePosition();
}
updatePosition() {
requestAnimationFrame(() => {
const {velocity, x, y} = this.state;
let newX, newY;
let newVelocity = [...velocity];
const shouldBounceAgainstLeftWall = (x <= 0 && velocity[0] <= -1);
const shouldBounceAgainstRightWall = (x >= stageX - ballDiameter && velocity[0] >= 1);
if(shouldBounceAgainstLeftWall || shouldBounceAgainstRightWall) {
newVelocity[0] = velocity[0] * -1;
}
const shouldBounceAgainstTopWall = (y <= 0 && velocity[1] <= -1);
const shouldBounceAgainstBottomWall = (y >= stageY - ballDiameter && velocity[1] >= 1);
if(shouldBounceAgainstTopWall || shouldBounceAgainstBottomWall) {
newVelocity[1] = velocity[1] * -1;
}
newX = x + newVelocity[0];
newY = y + newVelocity[1];
this.setState({velocity: newVelocity, x: newX, y: newY });
this.updatePosition();
});
}
speedChanger(multiplier) {
return () => {
const oldVelocity = this.state.velocity;
this.setState({
velocity: oldVelocity.map(v => v * multiplier)
});
}
}
render() {
return (
<div>
<button onClick={this.speedChanger(1.1)}>Click to increase speed</button>
<button onClick={this.speedChanger(0.9)}>Click to decrease speed</button>
<div className="arena" style={{height: stageY + "px", width: stageX + "px"}}>
<div className="ball" style={
{
height: ballDiameter + "px",
width: ballDiameter + "px",
borderRadius: (ballDiameter/2) + "px",
transform: `translateX(${this.state.x}px) translateY(${this.state.y}px)`
}
} >4</div>
</div>
</div>
)
}
}
ReactDOM.render(<TodoApp />,...