2019-09-16 21:18:01 +02:00
|
|
|
|
|
|
|
export interface Dictionary<T> {
|
|
|
|
[Key: string]: T;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
interface OnLoadable {
|
|
|
|
onload: any;
|
|
|
|
}
|
|
|
|
|
|
|
|
export function onload2promise<T extends OnLoadable>(obj: T): Promise<T> {
|
|
|
|
return new Promise(resolve => {
|
|
|
|
obj.onload = () => resolve(obj);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
export function resizeCanvasToDisplaySize(
|
|
|
|
canvas: HTMLCanvasElement,
|
|
|
|
multiplier?: number,
|
|
|
|
): boolean {
|
|
|
|
multiplier = multiplier || 1;
|
|
|
|
var width = canvas.clientWidth * multiplier | 0;
|
|
|
|
var height = canvas.clientHeight * multiplier | 0;
|
|
|
|
if (canvas.width !== width || canvas.height !== height) {
|
|
|
|
canvas.width = width;
|
|
|
|
canvas.height = height;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
export class FPSCounter {
|
|
|
|
last: number;
|
|
|
|
count: number;
|
|
|
|
constructor() {
|
|
|
|
this.last = 0;
|
|
|
|
this.count = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
frame(now: number) {
|
|
|
|
this.count += 1;
|
2019-09-17 20:19:04 +02:00
|
|
|
if (now - this.last > 1000) {
|
2019-09-16 21:18:01 +02:00
|
|
|
this.last = now;
|
|
|
|
console.log(this.count + " fps");
|
|
|
|
this.count = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-17 20:19:04 +02:00
|
|
|
export class Resizer {
|
2019-09-18 12:29:56 +02:00
|
|
|
hoovering = false;
|
|
|
|
dragging = false;
|
2019-09-16 21:18:01 +02:00
|
|
|
|
2019-09-18 12:29:56 +02:00
|
|
|
mouse_pos = [0, 0];
|
|
|
|
last_drag = [0, 0];
|
2019-09-16 21:18:01 +02:00
|
|
|
|
2019-09-17 20:19:04 +02:00
|
|
|
viewbox: number[];
|
|
|
|
orig_viewbox: number[];
|
2019-09-16 21:18:01 +02:00
|
|
|
|
2019-09-18 12:29:56 +02:00
|
|
|
el_box: number[];
|
2019-09-16 21:18:01 +02:00
|
|
|
|
2019-09-17 20:19:04 +02:00
|
|
|
scaleX = 1;
|
|
|
|
scaleY = 1;
|
2019-09-16 21:18:01 +02:00
|
|
|
|
2019-09-17 20:19:04 +02:00
|
|
|
constructor(el: HTMLCanvasElement, viewbox: number[], keep_aspect_ratio=false) {
|
2019-09-16 21:18:01 +02:00
|
|
|
|
2019-09-17 20:19:04 +02:00
|
|
|
this.viewbox = [...viewbox];
|
2019-09-18 12:29:56 +02:00
|
|
|
this.el_box = [el.width, el.height];
|
2019-09-16 21:18:01 +02:00
|
|
|
|
2019-09-17 20:19:04 +02:00
|
|
|
if (keep_aspect_ratio) {
|
|
|
|
const or_width = this.viewbox[2];
|
|
|
|
const or_height = this.viewbox[3];
|
|
|
|
|
2019-09-18 12:29:56 +02:00
|
|
|
const width_percentage = this.viewbox[2] / el.width;
|
|
|
|
const height_percentage = this.viewbox[3] / el.height;
|
|
|
|
|
|
|
|
if (width_percentage < height_percentage) {
|
|
|
|
// width should be larger
|
|
|
|
this.viewbox[2] = height_percentage * el.width;
|
2019-09-17 20:19:04 +02:00
|
|
|
} else {
|
2019-09-18 12:29:56 +02:00
|
|
|
this.viewbox[3] = width_percentage * el.height;
|
|
|
|
// height should be larger
|
2019-09-17 20:19:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
this.viewbox[0] -= (this.viewbox[2] - or_width) / 2;
|
|
|
|
this.viewbox[1] -= (this.viewbox[3] - or_height) / 2;
|
2019-09-18 12:29:56 +02:00
|
|
|
|
|
|
|
this.scaleX = this.viewbox[2] / this.viewbox[3];
|
2019-09-17 20:19:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
this.orig_viewbox = [...this.viewbox];
|
|
|
|
|
|
|
|
el.addEventListener("mouseenter", this.mouseenter.bind(this), { capture: false, passive: true});
|
|
|
|
el.addEventListener("mouseleave", this.mouseleave.bind(this), { capture: false, passive: true});
|
|
|
|
el.addEventListener("mousemove", this.mousemove.bind(this), { capture: false, passive: true});
|
|
|
|
el.addEventListener("mousedown", this.mousedown.bind(this), { capture: false, passive: true});
|
|
|
|
el.addEventListener("mouseup", this.mouseup.bind(this), { capture: false, passive: true});
|
|
|
|
|
|
|
|
window.addEventListener('wheel', this.wheel.bind(this), { capture: false, passive: true});
|
|
|
|
}
|
|
|
|
|
2019-09-18 12:29:56 +02:00
|
|
|
_clip_viewbox() {
|
2019-09-17 20:19:04 +02:00
|
|
|
this.viewbox[0] = Math.max(this.viewbox[0], this.orig_viewbox[0]);
|
|
|
|
this.viewbox[1] = Math.max(this.viewbox[1], this.orig_viewbox[1]);
|
|
|
|
|
|
|
|
this.viewbox[0] = Math.min(this.viewbox[0] + this.viewbox[2], this.orig_viewbox[0] + this.orig_viewbox[2]) - this.viewbox[2];
|
|
|
|
this.viewbox[1] = Math.min(this.viewbox[1] + this.viewbox[3], this.orig_viewbox[1] + this.orig_viewbox[3]) - this.viewbox[3];
|
|
|
|
}
|
|
|
|
|
|
|
|
mouseenter() {
|
|
|
|
this.hoovering = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
mouseleave() {
|
|
|
|
this.hoovering = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
mousemove(e: MouseEvent) {
|
2019-09-18 12:29:56 +02:00
|
|
|
this.mouse_pos = [e.offsetX, this.el_box[1] - e.offsetY];
|
2019-09-17 20:19:04 +02:00
|
|
|
|
|
|
|
if (this.dragging) {
|
2019-09-18 12:29:56 +02:00
|
|
|
const scaleX = this.viewbox[2] / this.el_box[0];
|
|
|
|
const scaleY = this.viewbox[3] / this.el_box[1];
|
|
|
|
|
|
|
|
this.viewbox[0] += (this.last_drag[0] - this.mouse_pos[0]) * scaleX;
|
|
|
|
this.viewbox[1] += (this.last_drag[1] - this.mouse_pos[1]) * scaleY;
|
2019-09-17 20:19:04 +02:00
|
|
|
|
|
|
|
this.last_drag = [...this.mouse_pos];
|
|
|
|
|
2019-09-18 12:29:56 +02:00
|
|
|
this._clip_viewbox();
|
2019-09-17 20:19:04 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
mousedown() {
|
|
|
|
this.dragging = true;
|
|
|
|
this.last_drag = [...this.mouse_pos];
|
|
|
|
}
|
|
|
|
|
|
|
|
mouseup() {
|
|
|
|
this.dragging = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
wheel(e: WheelEvent) {
|
|
|
|
if (this.hoovering) {
|
2019-09-18 12:29:56 +02:00
|
|
|
const delta = e.deltaY > 0 ? 0.1 * this.viewbox[2] : -0.1 * this.viewbox[2];
|
|
|
|
const dx = delta * this.scaleX;
|
|
|
|
|
2019-09-17 20:19:04 +02:00
|
|
|
this.viewbox[2] += dx;
|
|
|
|
this.viewbox[0] -= dx / 2;
|
|
|
|
this.viewbox[2] = Math.min(this.viewbox[2], this.orig_viewbox[2]);
|
|
|
|
|
2019-09-18 12:29:56 +02:00
|
|
|
const dy = delta * this.scaleY;
|
2019-09-17 20:19:04 +02:00
|
|
|
this.viewbox[3] += dy;
|
|
|
|
this.viewbox[1] -= dy / 2;
|
|
|
|
this.viewbox[3] = Math.min(this.viewbox[3], this.orig_viewbox[3]);
|
|
|
|
|
2019-09-18 12:29:56 +02:00
|
|
|
this._clip_viewbox();
|
2019-09-17 20:19:04 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
get_viewbox(): number[] {
|
|
|
|
return this.viewbox;
|
|
|
|
}
|
|
|
|
|
|
|
|
get_mouse_pos(): number[] {
|
|
|
|
return this.mouse_pos;
|
|
|
|
}
|
2019-09-16 21:18:01 +02:00
|
|
|
}
|