All files / ts/controller/surface surfaceController.ts

100% Statements 54/54
100% Branches 15/15
100% Functions 9/9
100% Lines 53/53

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102  1x 1x                   1x 1x                   1x       1x       1x       16x 16x 16x 16x       11x 11x 11x 11x 11x 11x       18x 18x 18x 18x 18x 18x 18x 18x 18x   18x 18x 18x 18x   18x 3x 3x 3x     15x 15x 15x   18x 18x 4x 4x   18x 18x 18x 18x 18x 18x       2x 1x   1x       1x 1x 1x    
import { IDestroyable } from "../../environment/objectStates.js";
import { IBounds2, Bounds2 } from "../../models/bounds2.js";
import { ISurfaceSettings, SurfaceSettings } from "./surfaceSettings.js";
 
export interface ISurfaceController extends IBounds2, IDestroyable {
    readonly context2d: CanvasRenderingContext2D;
    readonly settings: ISurfaceSettings;
    readonly clientBounds: IBounds2;
    initialize(context2d: CanvasRenderingContext2D, window: Window): void;
    update(): void;
    clear(): void;
}
export class SurfaceController extends Bounds2 implements ISurfaceController {
    public static readonly surfaceChangeEvent = "surfacechange";
 
    private readonly _settings: ISurfaceSettings;
    private readonly _clientBounds: IBounds2;
    private readonly _update: () => void;
 
    private _window!: Window;
    private _context2d!: CanvasRenderingContext2D;
 
    public get context2d(): CanvasRenderingContext2D {
        return this._context2d;
    }
 
    public get settings(): ISurfaceSettings {
        return this._settings;
    }
 
    public get clientBounds(): IBounds2 {
        return this._clientBounds;
    }
 
    public constructor(settings: ISurfaceSettings) {
        super(0, 0, settings.targetResolution.x, settings.targetResolution.y);
        this._settings = settings;
        this._clientBounds = new Bounds2();
        this._update = (): void => this.update();
    }
 
    public initialize(context2d: CanvasRenderingContext2D, window: Window): void {
        this._window = window;
        this._context2d = context2d;
        this._window.addEventListener("resize", this._update);
        this._window.addEventListener("orientationchange", this._update);
        this._settings.addEventListener(SurfaceSettings.maxResolutionChangeEvent, this._update);
        this.update();
    }
 
    public update(): void {
        const canvas = this._context2d.canvas;
        const target = <HTMLElement>canvas.parentElement;
        const targetClientRect = target.getBoundingClientRect();
        const pixelRatio = this._window.devicePixelRatio > 2 ? 2 : this._window.devicePixelRatio;
        const targetSize = new Bounds2(targetClientRect.x, targetClientRect.y, targetClientRect.width, targetClientRect.height);
        const resolutionSize = new Bounds2(0, 0, this.width, this.height);
        const scaleFactor = targetSize.getScale(resolutionSize);
        const containSize = new Bounds2(0, 0, this.width * scaleFactor, this.height * scaleFactor);
        const centerVector = containSize.getCenter(targetSize);
 
        canvas.style.left = `${centerVector.x}px`;
        canvas.style.top = `${centerVector.y}px`;
        canvas.style.width = `${containSize.width}px`;
        canvas.style.height = `${containSize.height}px`;
 
        if (pixelRatio <= 1) {
            canvas.width = this.width;
            canvas.height = this.height;
            this._context2d.setTransform(1, 0, 0, 1, 0, 0);
        }
        else {
            canvas.width = this.width * pixelRatio;
            canvas.height = this.height * pixelRatio;
            this._context2d.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0);
        }
        const maxResolution = this._settings.maxResolution;
        if (maxResolution && maxResolution.x > 0 && maxResolution.y > 0) {
            canvas.width = canvas.width > maxResolution.x ? maxResolution.x : canvas.width;
            canvas.height = canvas.height > maxResolution.y ? maxResolution.y : canvas.height;
        }
        const rect = canvas.getBoundingClientRect();
        this._clientBounds.x = rect.x;
        this._clientBounds.y = rect.y;
        this._clientBounds.width = rect.width;
        this._clientBounds.height = rect.height;
        this.dispatchEvent(new Event(SurfaceController.surfaceChangeEvent));
    }
 
    public clear(): void {
        if (!this._context2d)
            return
 
        this._context2d.clearRect(0, 0, this.width, this.height);
    }
 
    public destroy(): void {
        this._window.removeEventListener("resize", this._update);
        this._window.removeEventListener("orientationchange", this._update);
        this._settings.removeEventListener(SurfaceSettings.maxResolutionChangeEvent, this._update);
    }
}