diff --git a/src/App.tsx b/src/App.tsx
index 8929a42..56bf30b 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -1,5 +1,5 @@
import React, {useEffect, useRef} from 'react';
-import {draw, init, update} from "./draw/MainDraw";
+import {canvasClick, draw, init, update, canvasMouseMove} from "./draw/MainDraw";
let CANVAS_WIDTH = 1500;
let CANVAS_HEIGHT = 700;
@@ -24,10 +24,11 @@ function App() {
return (
Redox
-
);
}
export {CANVAS_WIDTH, CANVAS_HEIGHT};
-export default App;
+export default App;
\ No newline at end of file
diff --git a/src/draw/MainDraw.ts b/src/draw/MainDraw.ts
index f36182d..25ada27 100644
--- a/src/draw/MainDraw.ts
+++ b/src/draw/MainDraw.ts
@@ -1,17 +1,23 @@
import {rect} from "./Shapes";
-import {updateParticles, particlesInit, drawParticles} from "./Particles";
+import {drawParticles, initParticles, updateParticles} from "./Particles";
import {CANVAS_HEIGHT, CANVAS_WIDTH} from "../App";
+import {MouseEvent} from "react";
+import Vector from "./classes/Vector";
+import {drawUI, handleUIMouseMove, handleUIClick, initUI} from "./ui/UI";
type FillStyle = string | CanvasGradient | CanvasPattern;
type Ctx = CanvasRenderingContext2D;
+type MouseEvt = MouseEvent;
function init() {
- particlesInit();
+ initParticles();
+ initUI();
}
function draw(ctx: Ctx) {
rect(ctx, 0, 0, CANVAS_WIDTH, CANVAS_HEIGHT, "lightgrey");
drawParticles(ctx);
+ drawUI(ctx);
requestAnimationFrame(() => draw(ctx));
}
@@ -19,5 +25,23 @@ function update() {
updateParticles();
}
-export type {Ctx, FillStyle};
-export {update, init, draw};
+function canvasMouseMove(e: MouseEvt) {
+ console.log(getMousePos(e))
+ handleUIMouseMove(getMousePos(e));
+}
+
+function canvasClick(e: MouseEvt) {
+ console.log(getMousePos(e))
+ handleUIClick(e);
+}
+
+function getMousePos(evt: MouseEvt): Vector {
+ const rect = evt.currentTarget.getBoundingClientRect();
+ return new Vector(
+ evt.clientX - rect.left,
+ evt.clientY - rect.top
+ );
+}
+
+export type {Ctx, FillStyle, MouseEvt};
+export {update, init, draw, canvasClick, canvasMouseMove};
diff --git a/src/draw/Particles.ts b/src/draw/Particles.ts
index 4c20b09..6dc4465 100644
--- a/src/draw/Particles.ts
+++ b/src/draw/Particles.ts
@@ -5,15 +5,14 @@ import {CANVAS_HEIGHT, CANVAS_WIDTH} from "../App";
const particles: Particle[] = [];
-
-export function particlesInit() {
+export function initParticles() {
const chargeToMass = [0.1, 1, 10];
for (let i = 0; i < 200; i++) {
const charge = Math.random() < 0.3 ? 0 : Math.random() < 0.5 ? 1 : -1;
particles.push(new Particle(new Vector(
Math.random() * (CANVAS_WIDTH - 100) + 50,
Math.random() * (CANVAS_HEIGHT - 100) + 50
- ), charge, chargeToMass[charge - 1]));
+ ), charge, chargeToMass[charge + 1]));
}
}
diff --git a/src/draw/classes/Particle.ts b/src/draw/classes/Particle.ts
index 4bbf189..fe120f3 100644
--- a/src/draw/classes/Particle.ts
+++ b/src/draw/classes/Particle.ts
@@ -1,5 +1,5 @@
import Vector from "./Vector";
-import SimObject from "./Drawable";
+import SimObject from "./SimObject";
import {Ctx, FillStyle} from "../MainDraw";
import {circle} from "../Shapes";
import {CANVAS_HEIGHT, CANVAS_WIDTH} from "../../App";
@@ -12,8 +12,8 @@ const RANDOM_ACCELERATION = 2;
export default class Particle implements SimObject {
private _position: Vector;
private _velocity: Vector;
- private _mass: number;
- private _charge: number;
+ private readonly _mass: number;
+ private readonly _charge: number;
constructor(position: Vector, charge = 0, mass = 1) {
this._position = position;
diff --git a/src/draw/classes/Drawable.ts b/src/draw/classes/SimObject.ts
similarity index 100%
rename from src/draw/classes/Drawable.ts
rename to src/draw/classes/SimObject.ts
diff --git a/src/draw/classes/Vector.ts b/src/draw/classes/Vector.ts
index 654eff3..87c64ab 100644
--- a/src/draw/classes/Vector.ts
+++ b/src/draw/classes/Vector.ts
@@ -39,4 +39,4 @@ export default class Vector {
const factor = this.magnitude();
return new Vector(this.x / factor, this.y / factor);
}
-}
+}
\ No newline at end of file
diff --git a/src/draw/ui/Button.ts b/src/draw/ui/Button.ts
new file mode 100644
index 0000000..4e42ff3
--- /dev/null
+++ b/src/draw/ui/Button.ts
@@ -0,0 +1,24 @@
+import {Ctx} from "../MainDraw";
+import Vector from "../classes/Vector";
+import {rect} from "../Shapes";
+import UIComponent from "./UIComponent";
+
+class Button extends UIComponent {
+ private _clicked: boolean;
+
+ constructor(pos: Vector, size: Vector) {
+ super(pos, size);
+ this._clicked = false;
+ }
+
+ public draw(ctx: Ctx) {
+ const color = this._isHovered ? "red" : "grey";
+ rect(ctx, this._position.x, this._position.y, this._size.x, this._size.y, color);
+ }
+
+ public click() {
+ this._clicked = true;
+ }
+}
+
+export default Button;
\ No newline at end of file
diff --git a/src/draw/ui/MouseChargeButton.ts b/src/draw/ui/MouseChargeButton.ts
new file mode 100644
index 0000000..106277b
--- /dev/null
+++ b/src/draw/ui/MouseChargeButton.ts
@@ -0,0 +1,8 @@
+import Button from "./Button";
+import Vector from "../classes/Vector";
+
+export default class MouseChargeButton extends Button {
+ constructor(pos: Vector, size: Vector) {
+ super(pos, size);
+ }
+}
\ No newline at end of file
diff --git a/src/draw/ui/PauseButton.ts b/src/draw/ui/PauseButton.ts
new file mode 100644
index 0000000..09ee359
--- /dev/null
+++ b/src/draw/ui/PauseButton.ts
@@ -0,0 +1,5 @@
+import Button from "./Button";
+
+export default class PauseButton extends Button {
+
+}
\ No newline at end of file
diff --git a/src/draw/ui/UI.ts b/src/draw/ui/UI.ts
new file mode 100644
index 0000000..462316c
--- /dev/null
+++ b/src/draw/ui/UI.ts
@@ -0,0 +1,38 @@
+import {Ctx, MouseEvt} from "../MainDraw";
+import Vector from "../classes/Vector";
+import Button from "./Button";
+import {CANVAS_WIDTH} from "../../App";
+import UIComponent from "./UIComponent";
+
+const uiComponents: UIComponent[] = [];
+
+export function initUI() {
+ uiComponents.push(new Button(
+ new Vector(CANVAS_WIDTH - 60, 10),
+ new Vector(50, 50),
+ ));
+ uiComponents.push(new Button(
+ new Vector(CANVAS_WIDTH - 60, 70),
+ new Vector(50, 50)
+ ));
+}
+
+export function handleUIMouseMove(coords: Vector) {
+ for (let component of uiComponents) {
+ const isInside = component.isInside(coords);
+ if (isInside && !component.wasHovered) {
+ component.onHoverEnter();
+ } else if (!isInside && component.wasHovered) {
+ component.onHoverLeave();
+ }
+ component.wasHovered = isInside;
+ }
+}
+
+export function handleUIClick(e: MouseEvt) {
+
+}
+
+export function drawUI(ctx: Ctx) {
+ uiComponents.forEach(uic => uic.draw(ctx))
+}
\ No newline at end of file
diff --git a/src/draw/ui/UIComponent.ts b/src/draw/ui/UIComponent.ts
new file mode 100644
index 0000000..117e0dc
--- /dev/null
+++ b/src/draw/ui/UIComponent.ts
@@ -0,0 +1,44 @@
+import {Ctx} from "../MainDraw";
+import Vector from "../classes/Vector";
+
+export default abstract class UIComponent {
+ protected _size: Vector;
+ protected _position: Vector;
+ protected _isHovered: boolean;
+
+ private _wasHovered: boolean;
+
+ protected constructor(pos: Vector, size: Vector) {
+ this._position = pos;
+ this._size = size;
+ this._wasHovered = false;
+ this._isHovered = false;
+ }
+
+ abstract draw(ctx: Ctx): void;
+
+ abstract click(): void;
+
+ onHoverEnter(): void {
+ this._isHovered = true;
+ }
+
+ onHoverLeave(): void {
+ this._isHovered = false;
+ }
+
+ get wasHovered(): boolean {
+ return this._wasHovered;
+ }
+
+ set wasHovered(wasHovered) {
+ this._wasHovered = wasHovered;
+ }
+
+ public isInside(coords: Vector): boolean {
+ return coords.x > this._position.x
+ && coords.x < this._position.x + this._size.x
+ && coords.y > this._position.y
+ && coords.y < this._position.y + this._size.y;
+ }
+}
\ No newline at end of file