fertig-classic-games/public/src/ui/TextInput.js

66 lines
2.3 KiB
JavaScript

import * as Phaser from 'phaser';
// DOM-overlay text input. Positions a real <input> element above the canvas
// using the scene's scale so it lines up with where you'd draw it in Phaser.
export class TextInput {
constructor(scene, x, y, options = {}) {
this.scene = scene;
this.gameX = x;
this.gameY = y;
this.width = options.width ?? 360;
this.height = options.height ?? 48;
this.layer = document.getElementById('dom-layer');
const isTextarea = options.multiline === true;
this.el = document.createElement(isTextarea ? 'textarea' : 'input');
if (!isTextarea) this.el.type = options.type ?? 'text';
if (options.placeholder) this.el.placeholder = options.placeholder;
if (options.value !== undefined) this.el.value = options.value;
if (options.maxLength) this.el.maxLength = options.maxLength;
if (options.autocomplete) this.el.autocomplete = options.autocomplete;
this.el.style.position = 'absolute';
this.el.style.boxSizing = 'border-box';
this.layer.appendChild(this.el);
this.reposition = this.reposition.bind(this);
this.scene.scale.on('resize', this.reposition);
this.reposition();
this.scene.events.once(Phaser.Scenes.Events.SHUTDOWN, () => this.destroy());
this.scene.events.once(Phaser.Scenes.Events.DESTROY, () => this.destroy());
}
reposition() {
const cam = this.scene.cameras.main;
const zoom = this.scene.scale.displayScale; // {x, y} canvas-to-css scale
const canvas = this.scene.scale.canvas;
const rect = canvas.getBoundingClientRect();
const cssX = rect.left + (this.gameX - this.width / 2) / zoom.x;
const cssY = rect.top + (this.gameY - this.height / 2) / zoom.y;
const cssW = this.width / zoom.x;
const cssH = this.height / zoom.y;
this.el.style.left = `${cssX}px`;
this.el.style.top = `${cssY}px`;
this.el.style.width = `${cssW}px`;
this.el.style.height = `${cssH}px`;
this.el.style.fontSize = `${20 / zoom.y}px`;
// Avoid unused-variable lint complaints
void cam;
}
get value() { return this.el.value; }
set value(v) { this.el.value = v; }
focus() { this.el.focus(); }
on(event, handler) {
this.el.addEventListener(event, handler);
return this;
}
destroy() {
this.scene.scale.off('resize', this.reposition);
this.el.remove();
}
}