[マイおもちゃ]動くボール2-JavaScript
46108 ワード
ボールを弾く(ボールを捕まえることもできる!)
布を点けてから積み木をもう一つ作るつもりです.
canvasで感じた、こいつは...本当に座標しかありません.ははは
ブロックを形成するために、位置決めします.
では、これで積み木があります.このように置くと少し単調なので、ブロックにmoveTo、lineToで座標をつなぎ、立体的に見えます.
では.
ちゃんとした街が形成されています!ただし、ブロックはまだブロックにバウンドしていないので、ウィンドウでバウンドするのと同じように、ブロックにも関数が作成されます.
積み木に正常に跳ね上がったボールの様子が見えます.
しかし、ここで問題が発生した.
ブロックが不可侵領域として指定されているため、最初に生成されたボールがブロック内に現れると.
ボールは積み木に閉じ込められている.
この問題を解決するために、条件文を指定します.
ここで終わるのはちょっと残念ですが、ボールを勝手に動かしてもらえませんか?そこで、またマウスを使ったアクティビティを作りました.(drag & drop)
私が自由に操ることができるボールが完成しました!(パチパチ)
classでeventを追加および削除すると、望ましくない動作がしばしば発生します.
特に、addEventListener(「mouseup」,this.function)という関数の部分がthisです.function.bind(this)のようにbindで包まないと動作しません.
だからbindで包んで運転してみると今回removeEventListenerは動作していません
(今考えても鬱陶しいハハ)
原理を理解するために、いろいろ探しましたが、あまり理解していません.
そしてbindに関する良い文章を見つけました->bind了解
だからRemoveEventListenerは動いていませんない事件を取り除きたいからだ.
この問題を解決するために、関数をthisに設定します.function.bind(this)として宣言し、変数を作成して値を割り当てます. this.onMouseUp = this.mouseup.bind(this) これにより、eventはどこで作成されても、直接関数呼び出しではなく変数呼び出しによって同じeventを追加および削除できます.(今の私の理解の道の上でこれは最も良いです呜呜)
このように仮定を確立して実行して、幸いなことにeventは正常に実行します!!
でも.また一つ問題が発生した.
mouseupアクティビティでボールの方向を覚えているせいか、
マウスは空のスクリーンを往復移動したが、ボールの方向が急に変わった.ははは
それを解消するために、私は多くの試みをしました.私は少しも好きではありません.
mousedownイベントが再び発生すると、元のmouseupイベントがキャンセルされます.
期待した機能の実現はうまくいかなかったが、収穫があり、うれしかった.😄
🔨 さぎょうコード
-ブロックを描画
布を点けてから積み木をもう一つ作るつもりです.
canvasで感じた、こいつは...本当に座標しかありません.ははは
ブロックを形成するために、位置決めします.
export class Block {
// 블록의 x, y 좌표와 길이와 높이를 받는다.
constructor(x, y, width, height) {
this.width = width;
this.height = height;
this.x = x;
this.y = y;
}
draw(ctx) {
ctx.fillStyle = "tomato";
ctx.beginPath();
// 좌표를 받아 사각형을 만들어준다
ctx.rect(this.x, this.y, this.width, this.height);
ctx.fill();
}
}
class App {
constructor() {
...
this.ball = new Ball(this.stageWidth, this.stageHeight, 60, 10);
// 임의로 블록의 크기를 지정
this.block = new Block(200, 300, 400, 30);
window.requestAnimationFrame(this.animate.bind(this));
}
...
animate() {
window.requestAnimationFrame(this.animate.bind(this));
this.ctx.clearRect(0, 0, this.stageWidth, this.stageHeight);
// 블록 그리기
this.block.draw(this.ctx);
this.ball.draw(this.ctx, this.stageWidth, this.stageHeight);
}
}
では、これで積み木があります.このように置くと少し単調なので、ブロックにmoveTo、lineToで座標をつなぎ、立体的に見えます.
では.
ちゃんとした街が形成されています!ただし、ブロックはまだブロックにバウンドしていないので、ウィンドウでバウンドするのと同じように、ブロックにも関数が作成されます.
-ブロックイメージ化
class App {
...
animate() {
window.requestAnimationFrame(this.animate.bind(this));
this.ctx.clearRect(0, 0, this.stageWidth, this.stageHeight);
this.block.draw(this.ctx);
// draw에 블록을 추가한 후
this.ball.draw(this.ctx, this.stageWidth, this.stageHeight, this.block);
}
}
export class Ball {
...
draw(ctx, stageWidth, stageHeight, block) {
this.x += this.vx;
this.y += this.vy;
this.bounceWindow(stageWidth, stageHeight);
// 블록 함수 추가
this.bounceBlock(block);
...
}
...
bounceBlock(block) {
const minX = block.x - this.radius;
const maxX = block.maxX + this.radius;
const minY = block.y - this.radius;
const maxY = block.maxY + this.radius;
// 블록 영역 정의
if (this.x > minX && this.x < maxX && this.y > minY && this.y < maxY) {
// 블록의 x, y 중 어느 쪽에 닿았는지 판별
const x1 = Math.abs(minX - this.x);
const x2 = Math.abs(maxX - this.x);
const y1 = Math.abs(minY - this.y);
const y2 = Math.abs(maxY - this.y);
const min1 = Math.min(x1, x2);
const min2 = Math.min(y1, y2);
const min = Math.min(min1, min2);
if (min === min1) {
this.vx *= -1;
this.x += this.vx;
} else if (min === min2) {
this.vy *= -1;
this.y += this.vy;
}
}
}
}
では.積み木に正常に跳ね上がったボールの様子が見えます.
しかし、ここで問題が発生した.
-エラーを検出🔍
ブロックが不可侵領域として指定されているため、最初に生成されたボールがブロック内に現れると.
ボールは積み木に閉じ込められている.
この問題を解決するために、条件文を指定します.
-エラー修復ライブラリ
class App {
constructor() {
...
this.block = new Block(200, 300, 400, 30);
// 블록을 ball 안에 넣어준다.(블록의 좌표를 얻어야 하기 때문)
this.ball = new Ball(this.stageWidth, this.stageHeight, 50, 5, this.block);
window.requestAnimationFrame(this.animate.bind(this));
}
export class Ball {
constructor(stageWidth, stageHeight, radius, speed, block) {
...
const diameter = this.radius * 2;
this.checkX = this.radius + Math.random() * (stageWidth - diameter);
this.checkY = this.radius + Math.random() * (stageHeight - diameter);
// 생성된 위치가 블록 안일 경우를 체크
this.checkXYWithBlock =
block.x - this.radius < this.checkX &&
this.checkX < block.maxX + this.radius &&
block.y - this.radius < this.checkY &&
this.checkY < block.maxY + this.radius;
// checkXYWithBlock이 참이면 블록 안에 공이 만들어진 것이므로
// 갇히는 것을 막기 위해 좌측 상단에 공이 나오게 지정
this.x = this.checkXYWithBlock ? this.radius : this.checkX;
this.y = this.checkXYWithBlock ? this.radius : this.checkY;
}
...
}
これで、普通に仕事をしている様子が見えます!-その他の機能の実装
ここで終わるのはちょっと残念ですが、ボールを勝手に動かしてもらえませんか?そこで、またマウスを使ったアクティビティを作りました.(drag & drop)
export class Ball {
constructor(stageWidth, stageHeight, radius, speed, block) {
...
// 추가할 이벤트 함수를 변수로 선언 (그 이유는 뒤에서 말하겠다.)
this.onMouseDown = this.mousedown.bind(this);
this.onMouseUp = this.mouseup.bind(this);
this.onMouseMove = this.mousemove.bind(this);
}
draw(ctx, stageWidth, stageHeight, block) {
// mousedown 이벤트를 추가
window.addEventListener("mousedown", this.onMouseDown);
...
}
setDirection() {
// 현재 공의 방향을 변수에 저장
this.vxDirection = this.vx < 0 ? -1 : 1;
this.vyDirection = this.vy < 0 ? -1 : 1;
}
mousedown(event) {
// 7. 다시 mousedown이 발생하면 맨 뒤에 발생했던 mouseup제거 (그 이유는 뒤에서 말하겠다.)
window.removeEventListener("mouseup", this.onMouseUp);
this.offsetX = event.clientX - this.x;
this.offsetY = event.clientY - this.y;
// 1. mousedown이 발생될 때 현재 공의 방향을 불러온다.
this.setDirection();
// 2. 만약 공 안에서 mousedown이 발생하면 mousemove를 이벤트를 실행
if (
Math.abs(this.offsetX) <= this.radius &&
Math.abs(this.offsetY) <= this.radius
) {
window.addEventListener("mousemove", this.onMouseMove);
}
}
mousemove(event) {
// 3. mousemove 이벤트 실행시 공이 멈추고 공이 마우스를 따라 이동
this.x = event.clientX - this.offsetX;
this.y = event.clientY - this.offsetY;
this.vx = 0;
this.vy = 0;
// 4. 마우스를 떼면 mouseup 이벤트 실행
window.addEventListener("mouseup", this.onMouseUp);
}
mouseup() {
// 5. 공을 mousedown으로 집었을 때의 방향을 불러와 공이 다시 움직이도록 구현
this.vx = this.speed;
this.vy = this.speed;
if (this.vxDirection < 0) {
this.vx *= -1;
}
if (this.vyDirection < 0) {
this.vy *= -1;
}
// 6. mousemove, mousedown 이벤트 제거
window.removeEventListener("mousemove", this.onMouseMove);
window.removeEventListener("mousedown", this.onMouseDown);
}
}
🎉 結果
私が自由に操ることができるボールが完成しました!(パチパチ)
🩹 辛いところ
classでeventを追加および削除すると、望ましくない動作がしばしば発生します.
特に、addEventListener(「mouseup」,this.function)という関数の部分がthisです.function.bind(this)のようにbindで包まないと動作しません.
だからbindで包んで運転してみると今回removeEventListenerは動作していません
(今考えても鬱陶しいハハ)
原理を理解するために、いろいろ探しましたが、あまり理解していません.
そしてbindに関する良い文章を見つけました->bind了解
const object = {
name: 'object',
getName() {
return this.name;
}
}
const getName = object.getName;
const bindGetName = object.getName.bind(object);
console.log(getName === bindGetName); // false
リンクの文章を見ると、上のコードが違うことがわかります. class TryEvent {
...
add() {
this.element.addEventListener('click', this.click.bind(this));
}
remove() {
this.element.removeEventListener('click', this.click);
this.element.removeEventListener('click', this.click.bind(this));
}
}
したがって,この3つの関数にも異なる値がある.だからRemoveEventListenerは動いていませんない事件を取り除きたいからだ.
この問題を解決するために、関数をthisに設定します.function.bind(this)として宣言し、変数を作成して値を割り当てます.
このように仮定を確立して実行して、幸いなことにeventは正常に実行します!!
でも.また一つ問題が発生した.
mouseupアクティビティでボールの方向を覚えているせいか、
マウスは空のスクリーンを往復移動したが、ボールの方向が急に変わった.ははは
それを解消するために、私は多くの試みをしました.私は少しも好きではありません.
mousedownイベントが再び発生すると、元のmouseupイベントがキャンセルされます.
期待した機能の実現はうまくいかなかったが、収穫があり、うれしかった.😄
Reference
この問題について([マイおもちゃ]動くボール2-JavaScript), 我々は、より多くの情報をここで見つけました https://velog.io/@mandarine_punch/My-toy-움직이는-공-2-JavaScriptテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol