CanvasAPIを使用したアニメーション-パート2:基本的な衝突
このシリーズのパート1では、再利用可能なオブジェクトをキャンバスにレンダリングし、GUIを使用してより直感的なコントロールを行い、アニメーションループで基本的な動きの錯覚を作成する基本について説明しました。 このパートでは、キャンバスの境界に当たると色が変わる単純なボールを使用して、衝突効果を作成することに慣れます。
ボイラープレート
ほとんどのアニメーションの開始点として、Part 1
のプロジェクトを使用できます。
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"/> <meta name="viewport" content="width=device-width, initial-scale=1.0"/> <meta http-equiv="X-UA-Compatible" content="ie=edge"/> <title>HTML Canvas</title> </head> <body> <canvas></canvas> </body> <script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.7.6/dat.gui.min.js"></script> <script src="./canvas.js"></script> </html>
canvas.js
// Get canvas element const canvas = document.querySelector('canvas'); const c = canvas.getContext('2d'); // Make canvas fullscreen canvas.width = innerWidth; canvas.height = innerHeight; addEventListener('resize', () => { canvas.width = innerWidth; canvas.height = innerHeight; }); // Control Panel const gui = new dat.GUI(); const controls = { dx: 0, dy: 0, }; gui.add(controls, 'dx', 0, 10); gui.add(controls, 'dy', 0, 10); // New Object class Ball { constructor(x, y, radius, color) { this.x = x; this.y = y; this.radius = radius; this.color = color; } } Ball.prototype.draw = function () { c.beginPath(); c.fillStyle = this.color; c.arc(this.x, this.y, this.radius, 0, Math.PI * 2, false); c.fill(); c.closePath(); }; Ball.prototype.update = function () { this.x += controls.dx; this.y += -controls.dy; this.draw(); }; const ball = new Ball(innerWidth / 2, innerHeight / 2, 50, 'red'); // Render new instances const init = () => ball.draw(); // Handle changes const animate = () => { requestAnimationFrame(animate); c.clearRect(0, 0, canvas.width, canvas.height); ball.update(); }; init(); animate();
バウンサー
最終結果ここをプレビューできます。
衝突時の動作を変更するには、update
メソッドに条件を追加するだけで、ボールが境界に当たるたびに、この場合は方向を逆にして、ボールの動作を変更します。 ブラウザはオブジェクトの中心でその位置を確認しているため、常に半径を計算に含める必要があることに注意してください。
canvas.js
Ball.prototype.update = function() { if (this.y + this.radius > canvas.height || this.y - this.radius < 0) { controls.dy = -controls.dy; } this.y -= controls.dy; if (this.x + this.radius > canvas.width || this.x - this.radius < 0) { controls.dx = -controls.dx; } this.x += controls.dx; this.draw(); };
色
次に、ボールの色を変更するなど、何かをヒットしたときのさらに興味深い動作を追加しましょう。 まず、選択する色の配列と、ランダムに選択する関数が必要です。 境界線にぶつかったときはいつでも、色の値を新しいランダムな値に再割り当てできます。
Kuler をチェックして、独自のカラーパレットを作成することをお勧めします。
// Returns a color between 0 and the length of our color array const randomColor = colors => colors[Math.floor(Math.random() * colors.length)]; const colors = [ '#e53935', '#d81b60', '#8e24aa', '#5e35b1', '#3949ab', '#1e88e5', '#039be5', '#00acc1', '#00897b', '#43a047', '#ffeb3b', '#ef6c00' ]; // Re-assign color on contact Ball.prototype.update = function () { if (this.y + this.radius > canvas.height || this.y - this.radius < 0) { this.color = randomColor(colors); controls.dy = -controls.dy; }; this.y -= controls.dy; if (this.x + this.radius > canvas.width || this.x - this.radius < 0) { this.color = randomColor(colors); controls.dx = -controls.dx; }; this.x += controls.dx; this.draw(); }; // Make it start with a random color const newBall = new Ball(innerWidth / 2, innerHeight / 2, 50, randomColor(colors));
しっぽ
基本的な機能が整ったので、後ろに続く色付きの尻尾を追加することで、視覚的にもう少し面白くすることができます。 これを行うには、clearRect
を削除し、キャンバス全体を暗いRGBA値で塗りつぶします。 これにより、通過するものすべてから「残余」効果が作成され、背景の不透明度で残差の強度を制御できます。
const animate = () => { requestAnimationFrame(animate); c.fillStyle = `rgba(33, 33, 33, ${-controls.tail / 10})`; // Lower opacity creates a longer tail c.fillRect(0, 0, canvas.width, canvas.height); newBall.update(); }; // We also need to update our controls with some default values const controls = { dx: 5, dy: 5, tail: -5 }; gui.add(controls, 'dx', 0, 10); gui.add(controls, 'dy', 0, 10); gui.add(controls, 'tail', -10, 0);
結論
ちょうどそのように、私たちは今、いくつかの特殊効果を備えた非常に基本的な衝突システムを持っています。 このシリーズの次のパート3では、ここで説明する概念を使用して、この動的な雨のアニメーションを作成します。
それに続いて問題が発生した場合は、Codepenで実用的な例を利用できます。 気軽にフォークして、作ったものを共有してください。