この記事では、キャンバスを使用して美しい雨のエフェクトを描く方法について説明します。最終的なエフェクトを見てみましょう。
レンダリング
説明する写真を見て、どのような効果を達成する必要があるかを分析してください。
1. 雨滴の落下エフェクト、マウスを動かして落下方向を制御します
2. 雨粒は落下し、小さな水滴となって飛び散ります。その小さな水滴の移動方向は、マウスの移動方向と同じです。
3. 雨滴はマウス座標の一定の範囲内に落ち、小さな水滴に分散します。同様に、小さな水滴の移動方向はマウスの移動方向と同じです。
さて、全体の効果を大まかに 3 つの効果に分割し、これら 3 つの効果を達成すれば完了です。
段階的にやってみましょう。
1. 雨滴の落下エフェクト、マウスを動かして落下方向を制御します全体的な効果を達成するためのアイデアは次のとおりです。
初期時間配列を使用して雨粒オブジェクトを保存します。
雨滴オブジェクトには、雨滴の x 座標、y 座標、長さ、落下速度、色、および削除するかどうかを決定するフラグを表すために使用されるさまざまな属性があります。
アニメーションを更新するとき特定の数の雨滴オブジェクトを配列に追加し、配列を走査し、各雨滴オブジェクトの X 座標と Y 座標を変更し、キャンバスを使用して雨滴オブジェクトの座標に基づいて 2 つの点を描画します。雨粒が形成されます。
したがって、効果を実現するための焦点は座標にあります
レインドロップを初期化する場合雨滴の x 座標: 乱数
雨滴の y 座標: -100、これは雨滴が可視領域の外側から入ってくることを許可します。
アニメーションを更新するとき雨粒 x 座標:原x坐标的值+ speed * speedx
速度は雨滴の落下速度を示す固定値です。
速度x はマウスの移動方向に関連する変数です。 speedx = speedx + (maxspeedx - speedx) / 50
また、maxspeedx はマウスの移動方向に基づいて取得される値です。
maxspeedx = (e.clientX - canvasEl.clientWidth / 2) / (canvasEl.clientWidth / 2)
,
e.clientX: 表示領域の左側へのマウス距離の値
CanvasEl.clientWidth: ビジュアル領域全体の幅
つまり、speedx は徐々に maxspeedx に近づく値になります。
maxspeedx の値の範囲は -1 から 1 です。値が -1 に近いほど、方向は左にあり、値が 1 に近いほど、方向は右にあります。
なぜ単に maxspeedx を使用しないのでしょうか?
これは、雨滴がすぐに方向を変えるのを防ぐためであり、マウスを変更した直後に方向を変えるのではなく、見栄えを良くするためにわずかな遅延が必要です。
maxspeedxを使うと効果はこんな感じ
Speedxを使うと効果はこんな感じ
雨滴のy座標:原y坐标的值+ speed
速度は上記のx座標で述べたものと同じで、雨滴の落下速度を表す固定値です。
さて、最後にキャンバスを使って雨粒オブジェクトの座標に合わせて2点を描き、それを結ぶと雨粒が描画されます。
最初の点の座標は比較的単純で、この点の座標である雨滴オブジェクトの x 座標と y 座標を直接取得します。
2 番目の点の座標:
x坐标= 雨滴x坐标的值+ 雨滴长度* speedx
y坐标= 雨滴y坐标的值+ 雨滴长度
最後に、これら 2 つの点を結ぶと、線ができます。これが雨滴です。
x 座標を設定するときに、再び変数 Speedx を使用します。これは、雨滴の方向と雨滴の落下方向を一致させるためです。
Speedxを使用しない場合はこんな感じ
Speedx を使用する場合はこれに当てはまります
2. 雨粒は落下し、小さな水滴となって飛び散ります。その小さな水滴の移動方向は、マウスの移動方向と同じです。ここでのアイデアは実際には上記の効果と多少似ています
初期時間配列を使用して小さな水滴オブジェクトを保存します。
小さな水滴は実際には円弧です。
小さな水滴オブジェクトには、小さな水滴の座標、X 軸の移動速度、Y 軸の移動速度、円の半径、削除するかどうかを決定するフラグなどを表すさまざまな属性があります。
アニメーションを更新するとき一定数の小さな水滴オブジェクトを配列に追加し、配列を走査し、各小さな水滴オブジェクトの x 座標と y 座標を変更し、キャンバスを使用して小さな水滴オブジェクトの座標属性と半径属性に基づいて円弧を描きます。水滴のオブジェクト。
したがって、効果を達成するための焦点は依然として座標にあります。
小さな水滴を初期化する場合雨滴が消えると小さな水滴が現れるので、小さな水滴の座標も雨滴の座標に基づいています。雨滴を削除するといくつかの小さな水滴が現れ、小さな水滴の移動方向は次のようになります。雨滴の落ちる方向もマウスの移動方向と同じなので、前述の可変速度xが引き続き必要になります。
小水珠x坐标: 删除的雨滴x坐标+ 删除的雨滴长度* speedx
小水珠y坐标:删除的雨滴y坐标+ 删除的雨滴长度
ここでは、小さな水滴オブジェクトの 2 つの属性 vx (x 軸の値の変化速度) と vy (y 軸の値の変化速度) を使用する必要があります。
小さな水滴のx座標
vx = vx + speedx / 2
小水珠的x坐标=原x坐标+ vx
、
Speedx: 前述のマウスの移動方向に関連する変数。ここでの機能は、小さな水滴の移動方向を他の方向と同じ方向に制御することです。
speedx / 2
、2 で割る目的は、x 軸上の小さな水滴の移動距離を短くし、より現実的に見せることです。
小さな水滴のy座標
vy = vy + gravity
小水珠的y坐标= 原y坐标+ vy;
vy: 負の数
Gravity: 重力、正の数。完全なコードでは 0.5 に設定されます。
元の y 座標は正の数であるため、小さな水滴の y 座標の値は最初に減少し、次に増加します。これは、小さな水滴が最初に上昇し、次に下降するという効果を実現するためです。
最後に、キャンバスを使用して、小さな水滴の座標属性と半径属性に基づいて円弧を描画します。円弧はランダムです。
3. 雨滴はマウス座標の一定の範囲内に落ち、小さな水滴に分散します。同様に、小さな水滴の移動方向はマウスの移動方向と同じです。
画像内の円のサイズを決定するのは簡単です。円の半径が 35 であると仮定します。マウスの座標を円の中心として、35 を半径として取得できます。 、円の大きさを決定できます。
重要な点は、雨滴がこの範囲に入ったかどうかを判断する方法です。これにはピタゴラスの定理を使用する必要があります。写真を見てください。
雨滴は 2 つの点を結ぶ線であるため、雨滴がこの範囲に入ったかどうかを確認するには、マウスからの直線距離が線分の長さとなります。写真のABです。
ピタゴラスの定理: 直角三角形の直角な 2 辺の二乗の和は斜辺の二乗に等しい。
AB = 数学.sqrt(BC BC + AC AC)
BC = 雨滴の X 座標 - マウスの X 座標
AC = 雨滴の y 座標 - マウスの y 座標
Math.sqrt() メソッドは、数値の平方根を計算するために使用されます。
雨滴からマウスまでの直線距離がわかったら、それを円の半径と比較します。それが半径より大きい場合は範囲内にありません。そうでない場合は範囲内にあります。
範囲内であれば雨粒を削除し、小さな水滴を描きます。
要約する
この効果を実現するには、雨滴の方向、雨粒の落ちる方向、そして小さな水滴の移動方向が問題になります。これらはすべてマウスの移動方向に関係します。キャンバスを使用して、距離に基づいて連続的に線を描画します。
完全なコード
<!doctype html><html lang=ja><head> <meta charset=UTF-8> <style> * { margin: 0 } </style></head><body> <canvas id; =canvas style=position:absolute; height:100%; width:100%;></canvas> <script> window.onload = main() { // キャンバス要素を取得します var CanvasEl = document.getElementById('canvas'); var ctx = CanvasEl.getContext('2d'); // キャンバス Canvas の背景色 = '#000';表示領域の幅 CanvasEl. width = CanvasEl.clientWidth; // キャンバスの高さは表示領域の高さと同じです CanvasEl.height = CanvasEl.clientHeight; // 小さな水滴を保存するための配列雨粒が落ちた後、小さな水滴は円弧状に飛び散ります。 雨粒は落ちた後、小さな水滴に飛び散ります。主に重力の影響で落下します。 var gravity = 0.5 // 雨滴の配列を保存します。 // それぞれの雨滴は描画された線です。 var linelist = []; // マウスの座標を保存します。 】 x 軸の値を表し、mousePos[1] は y 軸の値を表します。 var MousePos = [0, 0] // マウスに続いて、mouseDis サイズ領域の雨滴が消え、散乱効果が形成されます。 // MousePos を円の中心として、mouseDis を Radius にすると、この範囲内の雨滴が広がり、多数の小さな水滴が形成されます。 var MouseDis = 35 // アニメーションを 1 回更新して lineNum の雨滴を描画します。 lineNum の値が大きいほど。 、雨はより濃くなるでしょう。 lineNum = 3; // マウスの方向に従って雨の方向の速度を変更します // マウスが移動した後、雨の方向は主に変数 Speedx に応じてゆっくりと変化します var Speedx = 0;は、speedx が取り得る最大値です。 // Speedx = maxspeedx の場合、雨の方向はマウスの移動方向に応じて即座に変わります。 var maxspeedx = 0 // ページ サイズが変更されると、キャンバス サイズがリセットされます。 window.onresize = function; () { CanvasEl.width = CanvasEl.clientWidth; CanvasEl.height = CanvasEl.clientHeight; } //マウスを移動してイベントをトリガーします window.onmousemove = function (e) { //mousePos をマウス座標に設定します // e.clientX は、ブラウザ ウィンドウの表示領域の左側 Distance // e.clientY はブラウザ ウィンドウの表示領域の上部からの距離です MousePos[0] = e.clientX; e.clientY; // マウスの位置によって maxspeedx の値を設定します。値の範囲は -1 から 1 です。 // maxspeedx の値は、 // 1. 雨滴の方向 // 2. 雨滴の方向に関連します。 Raindrops // 3. マウスの移動方向によって雨滴の落ちる方向が変化する速度 // 4. 小さな水滴の移動方向 // 値が 1 に近いほど右方向になります // / 値が -1 に近づくほど、方向は左に進みます。 maxspeedx = (e.clientX - CanvasEl.clientWidth / 2) / (canvasEl.clientWidth / 2) } // パラメータに従って、雨滴の色の設定に使用される rgb カラーを返します function getRgb(r, g, b) { return rgb( + r + , + g + , + b + ); } // 雨粒(線)を描画します function createLine(e) { // 雨粒の長さをランダムに生成します var temp = 0.25 * (50 + Math.random() * 100); // 雨滴を表す line オブジェクト var line = { // 雨滴の落下速度 Speed: 5.5 * (Math.random() * 6 + 3), / / 削除するかどうかを決定し、値が true の場合は削除 die: false, // 雨滴の x 座標 posx: e, // 雨滴の y 座標 posy: -50, // 雨滴の長さ h: temp, // 雨粒の色 color: getRgb(Math.floor(temp * 255 / 75), Math.floor(temp * 255 / 75), Math.floor(temp * 255 / 75)) }; line (raindrop) オブジェクト、raindrop を保持する配列に追加 linelist.push(line); } //小さな水滴を描画します (雨滴が分散した後の小さな水滴は円弧です) function createDrop(x, y) { // 円弧を表すドロップ オブジェクト var Drop = { // 削除するかどうかを決定し、値 true の場合は削除しますdie: false, // 円弧の中心の x 座標 posx: x, // 円弧の中心の y 座標 posy: y, // vx は、x 軸の値が変化する速度を表します vx: (Math.random ( ) - 0.5) * 8, // vy は y 軸値の変化の速度範囲を表します: -3 から -9 vy: Math.random() * (-6) - 3, // 円弧の半径: Math.random() * 1.5 + 1 }; returndrop } // 一定数の小さな水滴を描画します function madedrops(x, y) { // ランダムな数値を生成します // maxi描画される小さな水滴の数を表します var maxi = Math.floor(Math.random() * 5 + 5); for (var i = 0; i < maxi; i++) {dropList.push(createDrop(x, y) ); } } // アニメーションを更新するために update 関数の呼び出しを開始します window.requestAnimationFrame(update) // アニメーション関数を更新します update() { // 小さな水滴を保持する配列にコンテンツがある場合(dropList.length > 0) { // 小さな水滴を保持する配列を走査します dropList.forEach(function (e) { // e.vx を設定します。vx は x 座標の変化の速度を表します // (speedx)/2 はfor, 小さな水滴の x 軸上の移動距離を短くし、よりリアルに見せます // また、小さな水滴の移動方向を雨滴の方向、雨滴の落ちる方向と同じにするマウスの移動方向 e.vx = e.vx + (speedx / 2); e.posx = e.posx + e.vx; // e.vy を設定し、vy は y 座標の変化の速度を表します // e.vy の範囲は -3 ~ -9 ですe.posy ( y 座標) は正の値でなければならないため、e.posy の値は最初に減少し、次に増加します。 // つまり、雨滴は小さな水滴に分散し、小さな水滴は最初に上昇し、その後上昇します。 e.vy = e.vy + 重力; e.posy = e.posy + e.vy; // 小さな水滴の y 座標が表示領域の高さより大きい場合、die 属性を true に設定します。 // 小さな水滴が表示領域を超える場合、削除します (e. posy > CanvasEl.clientHeight) { e .die = true } }) } // die 属性が true の配列メンバーを削除 // 表示領域の外側にある小さな水滴を削除します (var i =dropList.length - 1) ; i >= 0; i- -) { (dropList[i].die) {dropList.splice(i, 1) } } // 雨の方向の変化の速度を設定します。値の範囲: -1 ~ 1 // 速度 x = maxspeedx の場合、雨の方向は変化します。マウスの移動方向を即座に指定します Speedx = Speedx + (maxspeedx - Speedx) // // lineNum の値に従って特定の数の雨滴を描画します for (var i = 0; i < lineNum; i++) { // createLine 関数を呼び出します。パラメータは雨滴の x 座標です。 createLine(Math.random() * 2 * CanvasEl.width - (0.5 * CanvasEl.width)) } // 終了ライン、つまり雨粒が広がり、多数の小さな水滴を形成します。 Position var endLine = CanvasEl.clientHeight - Math.random() * CanvasEl.clientHeight //雨滴を保持する配列を走査します linelist.forEach(function (e) { // ピタゴラスの定理を使用して、雨滴が広がって小さな水滴を形成する範囲を決定します // e.posx + Speedx * eh は次の x 座標です雨滴/ / e.posy + eh は雨滴の y 座標です var dis = Math.sqrt(((e.posx + Speedx * eh) - MousePos[0]) * ((e.posx + Speedx) * eh) - MousePos[0]) + (e.posy + eh - MousePos[1]) * (e.posy + eh - MousePos[1])); // マウスディス領域内にある場合は、レインドロップを削除します。いくつかの小さな水滴 (円弧) // マウスが雨滴に触れ、雨滴が小さな水滴に散らばる効果を実現します。 if (dis < MouseDis) { // 雨滴を削除します。 e.die = true; // 描画します。いくつかの小さな水滴(円)が弧を描きます) madedrops(e.posx + Speedx * eh, e.posy + eh) } // 雨滴が終了線を超えた場合は、雨滴を削除し、小さな水滴 (円弧) を描画します if ((e.posy + eh) > endLine) { e.die = true; madedrops(e.posx + Speedx * eh, e.posy + eh) } // 雨滴の y 座標が表示領域の高さより大きい場合、ダイスを設定します。属性を true に設定 //雨滴が表示領域を超えた場合は削除します if (e.posy >= CanvasEl.clientHeight) { e.die = true; } else { // 雨滴の y 座標の値を徐々に増加させます。 e.posy = e. posy + e.speed ; // 雨滴の x 座標を変更します // * 雨滴の落下方向を制御するために、speedx を使用します // 雨滴の落下方向をマウスの移動方向と同じにします e.posx = e .posx + e.speed x } }); die 属性が true の配列メンバーを削除します // マウス領域、終了線を超え、表示領域の外側の雨滴を削除します for (var i = linelist.length - 1; i >= 0; i--) { if (linelist[i].die) { linelist.splice(i, 1) } } // 再帰的に update を呼び出してアニメーション効果を実現します window.requestAnimationFrame(update); // レンダリング関数 render() { // 表示領域と同じ大きさの四角形を描画します ctx.fillStyle = backgroundColor; ctx.fillRect(0, 0, CanvasEl.width, CanvasEl.height); // 雨滴効果を描画します。 lineWidth = 5; linelist.forEach(function (line) { ctx.drawingStyle = line.color; ctx.beginPath(); ctx.moveTo(line.posx, line.posy); // * 雨滴の方向を制御するためにspeedxが使用されます // 雨滴の方向をマウスの移動方向と同じにします ctx.lineTo(line.posx + line. h *speedx, line.posy + line.h); ctx.blood() }); // 小さな水滴を形成する雨滴を描画します。 dropList.forEach(function (e) { ctx.beginPath(); ctx.arc(e.posx, e.posy, e.radius, Math.random() * Math.PI * 2, 1 * Math.PI); ctx.ストローク() }); // コメントを解除すると、マウスの範囲が表示されます/* ctx.arc(mousePos[0],マウスポス[1], マウスディス, 0, 2 * Math.PI) */ } } </script></body></html>
以上がこの記事の全内容です。皆様の学習のお役に立てれば幸いです。また、VeVb Wulin Network をご支援いただければ幸いです。