UNPKG

@spearwolf/twopoint5d

Version:

a library to create 2.5d realtime graphics and pixelart with three.js

103 lines 3.35 kB
import { emit, eventize } from '@spearwolf/eventize'; import { Sprite, SpriteMaterial, Texture } from 'three'; import { TextureFactory } from '../texture/TextureFactory.js'; import { OrthographicProjection } from './OrthographicProjection.js'; import { Stage2D } from './Stage2D.js'; export class Canvas2DStage { #fit; get fit() { return this.#fit; } set fit(value) { if (this.#fit === value) return; this.#fit = value; this.projection.viewSpecs.fit = value; this.stage.update(true); } get width() { return this.canvas.width; } get height() { return this.canvas.height; } get scene() { return this.stage.scene; } #textureFactory; #lastWidth; #lastHeight; constructor(renderer, ...args) { this.#fit = 'contain'; this.needsUpdate = false; this.#lastWidth = 0; this.#lastHeight = 0; eventize(this); this.renderer = renderer; if (typeof args[0] === 'number') { const [width, height, fit] = args; this.#fit = fit ?? this.#fit; this.canvas = document.createElement('canvas'); this.canvas.width = width; this.canvas.height = height; } else { const [canvas, fit] = args; this.#fit = fit ?? this.#fit; this.canvas = canvas; } this.projection = new OrthographicProjection('xy|bottom-left', { width: this.width, height: this.height, fit: this.#fit, }); this.stage = new Stage2D(this.projection); const material = new SpriteMaterial({ map: new Texture() }); this.sprite = new Sprite(material); this.sprite.scale.set(this.width, this.height, 1); this.scene.add(this.sprite); } makeTexture() { if (this.texture) { this.texture.dispose(); } this.#textureFactory ||= new TextureFactory(this.renderer, ['nearest', 'flipy', 'srgb']); this.texture = this.#textureFactory.create(this.canvas); return this.texture; } updateTexture() { if (this.needsUpdate) { this.sprite.material.map = this.makeTexture(); this.sprite.material.needsUpdate = true; this.needsUpdate = false; } } setContainerSize(width, height) { this.stage.resize(width, height); } setCanvasSize(width, height) { if (this.width === width && this.height === height) return; this.canvas.width = width; this.canvas.height = height; this.sprite.scale.set(width, height, 1); const viewSpecs = this.projection.viewSpecs; viewSpecs.width = width; viewSpecs.height = height; this.stage.update(true); } render() { if (this.width !== this.#lastWidth || this.height !== this.#lastHeight) { this.dispatchEvent('resize'); this.#lastWidth = this.width; this.#lastHeight = this.height; } this.dispatchEvent('render'); this.updateTexture(); this.stage.renderFrame(this.renderer, 0, 0, 0); } dispatchEvent(eventName) { emit(this, eventName, this); } } //# sourceMappingURL=Canvas2DStage.js.map