From add4166030f858fe568fc7bd54861a5251fda604 Mon Sep 17 00:00:00 2001 From: Nilstrieb Date: Thu, 17 Jun 2021 14:03:36 +0200 Subject: [PATCH] button --- src/App.tsx | 7 +-- src/draw/MainDraw.ts | 32 ++++++++++++-- src/draw/Particles.ts | 5 +-- src/draw/classes/Particle.ts | 6 +-- .../classes/{Drawable.ts => SimObject.ts} | 0 src/draw/classes/Vector.ts | 2 +- src/draw/ui/Button.ts | 24 ++++++++++ src/draw/ui/MouseChargeButton.ts | 8 ++++ src/draw/ui/PauseButton.ts | 5 +++ src/draw/ui/UI.ts | 38 ++++++++++++++++ src/draw/ui/UIComponent.ts | 44 +++++++++++++++++++ 11 files changed, 157 insertions(+), 14 deletions(-) rename src/draw/classes/{Drawable.ts => SimObject.ts} (100%) create mode 100644 src/draw/ui/Button.ts create mode 100644 src/draw/ui/MouseChargeButton.ts create mode 100644 src/draw/ui/PauseButton.ts create mode 100644 src/draw/ui/UI.ts create mode 100644 src/draw/ui/UIComponent.ts 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