Skip to content

Commit

Permalink
add renderer option, abstract classes and refactor code
Browse files Browse the repository at this point in the history
  • Loading branch information
himanshurajora committed Sep 13, 2023
1 parent 9c6bb50 commit c26573b
Show file tree
Hide file tree
Showing 12 changed files with 185 additions and 20 deletions.
9 changes: 6 additions & 3 deletions examples/point/script.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { Engine, createCanvas } from '../../lib';
import { Engine, createCanvas, Point } from '../../lib';

const { canvas } = createCanvas();
const engine = new Engine(canvas);

const renderer = engine.renderer;

renderer.drawPoint({ x: 100, y: 100 });
for (let i = 0; i < 100; i++) {
renderer.addObject(
new Point({ x: Math.random() * 400, y: Math.random() * 400 }),
);
}
9 changes: 8 additions & 1 deletion lib/constants/renderer.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
export const DefaultPointOptions = {
import { DrawableObjectOptions, PointOptions } from '../types';

export const DefaultDrawableObjectOptions: DrawableObjectOptions = {
show: true,
};

export const DefaultPointOptions: PointOptions = {
...DefaultDrawableObjectOptions,
x: 0,
y: 0,
radius: 5,
Expand Down
12 changes: 12 additions & 0 deletions lib/render/engine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,19 @@ export class Engine {
);
}

const render = () => {
this.renderer.render();
requestAnimationFrame(render);
};

this.renderer = new Renderer(this.context);
requestAnimationFrame(render);

// Set useful options to window
// INFO: Make sure whenever new Engine is created it will overwrite the default
// renderer and engine in the global scope
window.MiniPointDefaultEngine = this;
window.MiniPointDefaultRenderer = this.renderer;
}

get currentContext(): CanvasRenderingContext2D | null {
Expand Down
1 change: 1 addition & 0 deletions lib/render/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export * from './engine';
export * from './minipoint';
export * from '../types';
export * from '../constants';
export * from './objects';
27 changes: 27 additions & 0 deletions lib/render/objects/base-object.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { v4 } from 'uuid';
import { DrawableObjectOptions, BaseObjectInterface } from '../../types';
import { Renderer } from '../renderer';

/**
* The Base Object Class
*/
export abstract class BaseObject<T, K> implements BaseObjectInterface {
id: string;
options: T & DrawableObjectOptions;
context: CanvasRenderingContext2D;
constructor(options: DrawableObjectOptions<T>, renderer?: Renderer) {
this.options = options;
// Either the specifically given render or the global renderer
this.context = renderer?.context || window.MiniPointDefaultRenderer.context;
this.id = v4();
this.checkDrawConditionAndDraw();
}

abstract draw(): K;

checkDrawConditionAndDraw() {
if (this.options.show) {
this.draw();
}
}
}
2 changes: 2 additions & 0 deletions lib/render/objects/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './base-object';
export * from './point';
31 changes: 31 additions & 0 deletions lib/render/objects/point.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { PointOptions } from '../../types';
import { DefaultPointOptions } from '../../constants';
import { BaseObject } from './base-object';
import { Renderer } from '../renderer';
/**
* The Point Class
*/
export class Point extends BaseObject<PointOptions, Point> {
constructor(
options: PointOptions = DefaultPointOptions,
renderer?: Renderer,
) {
options = { ...DefaultPointOptions, ...options };
super(options, renderer);
}

draw() {
if (!this.options.show) return this;
this.context.beginPath();
this.context.arc(
this.options.x,
this.options.y,
this.options.radius!,
0,
Math.PI * 2,
);

this.context.fill();
return this;
}
}
27 changes: 14 additions & 13 deletions lib/render/renderer.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,24 @@
import { PointOptions, RendererInterface } from '../types';
import { forEach } from 'lodash';
import { DefaultPointOptions } from '../constants';
import { BaseRenderer, PointOptions } from '../types';
import { Point } from './objects';
/**
* The class that is responsible for drawing
*/
export class Renderer implements RendererInterface {
context: CanvasRenderingContext2D;
export class Renderer extends BaseRenderer {
constructor(context: CanvasRenderingContext2D) {
this.context = context;
super(context);
}

drawPoint(options?: PointOptions) {
options = {
...DefaultPointOptions,
...options,
};
render() {
forEach(this.objects, (object) => {
object.checkDrawConditionAndDraw();
});
}

this.context.beginPath();
// @ts-ignore
this.context.arc(options.x, options.y, options.radius, 0, Math.PI * 2);
this.context.fill();
point(options: PointOptions = DefaultPointOptions) {
const point = new Point(options, this);
this.objects.push(point);
return point;
}
}
27 changes: 26 additions & 1 deletion lib/types/renderer.ts
Original file line number Diff line number Diff line change
@@ -1 +1,26 @@
export interface RendererInterface {}
declare global {
interface Window {
MiniPointDefaultRenderer: Renderer;
MiniPointDefaultEngine: Engine;
}
}

import { Engine } from '../render';
import { Renderer } from '../render/renderer';
import { BaseObjectInterface } from './shapes';

export abstract class BaseRenderer {
context: CanvasRenderingContext2D;
objects: BaseObjectInterface[];

constructor(context: CanvasRenderingContext2D) {
this.context = context;
this.objects = [];
}
abstract render(): void;

addObject<T>(object: T): T {
this.objects.push(object as BaseObjectInterface<T>);
return object;
}
}
20 changes: 18 additions & 2 deletions lib/types/shapes.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,21 @@
export type PointOptions = {
export interface BaseObjectInterface<T = unknown> {
// draw: () => T;
checkDrawConditionAndDraw: () => T;
/**
* A Unique Id that will help us identify each object in the Engine
*/
id?: string;
}

export type DrawableObjectOptions<T = unknown> = T & {
/**
* Weather to show the object or not
*/
show?: boolean;
};

export type PointOptions = DrawableObjectOptions<{
x: number;
y: number;
radius?: number;
};
}>;
34 changes: 34 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,18 @@
"devDependencies": {
"@types/jest": "^29.5.4",
"@types/jsdom": "^21.1.2",
"@types/uuid": "^9.0.3",
"jest": "^29.6.4",
"jest-canvas-mock": "^2.5.2",
"jest-environment-jsdom": "^29.6.4",
"jsdom": "^22.1.0",
"ts-jest": "^29.1.1",
"ts-node": "^10.9.1",
"typescript": "^5.2.2"
},
"dependencies": {
"@types/lodash": "^4.14.198",
"lodash": "^4.17.21",
"uuid": "^9.0.1"
}
}

0 comments on commit c26573b

Please sign in to comment.