mai3-phaser-sdk
Version:
A UI component library based on the Phaser game engine
289 lines (288 loc) • 12.3 kB
JavaScript
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
import Phaser from 'phaser';
import { Container } from './Container';
import { Label } from './Label';
var TextBox = /** @class */ (function (_super) {
__extends(TextBox, _super);
function TextBox(scene, config) {
var _a, _b, _c;
var _this = _super.call(this, scene, config, 'TextBox') || this;
_this.charWidths = [];
_this.isSelecting = false;
_this._config = config;
_this.isFocus = false;
_this.maxWidth = (_a = config.width) !== null && _a !== void 0 ? _a : 100;
_this.label = new Label(scene, config);
_this.label.Text = (_b = config.text) !== null && _b !== void 0 ? _b : '';
_this.label.setPosition(0, 0);
_this.addChildAt(_this.label, 0);
_this.cursor = scene.make.text({
style: {
color: '#383838',
fontSize: (_c = config.textStyle) === null || _c === void 0 ? void 0 : _c.fontSize
}
});
_this.cursor.text = "|";
_this.cursor.setOrigin(0);
_this.cursor.x = _this.label.TextWidth;
_this.cursor.y = (_this.label.RealHeight - _this.cursor.displayHeight) / 2;
_this.cursor.setVisible(false);
_this.addChildAt(_this.cursor, 1);
_this.selection = scene.add.rectangle(0, 0, 0, 0, 0xEE6363, 0.5);
_this.selection.setOrigin(0);
_this.selection.y = _this.cursor.y;
_this.selection.height = _this.cursor.displayHeight;
_this.addChildAt(_this.selection, 1);
_this.setEventInteractive();
_this.on('pointerover', _this.handleOver, _this);
_this.on('pointerout', _this.handleOut, _this);
_this.on('pointerup', _this.handlePointerUp, _this);
_this.on('pointerdown', _this.handlePointerDown, _this);
_this.on('pointermove', _this.handlePointerMove, _this);
if (scene.input.keyboard) {
scene.input.keyboard.on('keyup', _this.handleKeyup, _this);
}
_this.createHiddenInput();
return _this;
}
TextBox.prototype.handleKeyup = function (event) {
if (!this.isFocus)
return;
if (event.key === 'ArrowLeft' || event.key === 'ArrowRight' || event.key === 'Backspace') {
this.handleMoveCursor();
}
};
TextBox.prototype.getCursorPosition = function () {
var _a, _b;
return (_b = (_a = this.hiddenInput) === null || _a === void 0 ? void 0 : _a.selectionStart) !== null && _b !== void 0 ? _b : 0;
};
TextBox.prototype.createHiddenInput = function () {
var _this = this;
this.hiddenInput = document.createElement('input');
this.hiddenInput.type = 'text';
this.hiddenInput.style.position = 'absolute';
this.hiddenInput.style.opacity = '0';
this.hiddenInput.style.pointerEvents = 'none';
this.hiddenInput.style.zIndex = '-1';
this.hiddenInput.style.top = '-1000px'; // 将隐藏输入框移到屏幕外
this.hiddenInput.value = this.label.Text;
document.body.appendChild(this.hiddenInput);
this.hiddenInput.addEventListener('input', function () {
var _a, _b;
var newText = (_b = (_a = _this.hiddenInput) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : '';
if (_this.getTextWidth(newText) <= _this.maxWidth) {
_this.label.Text = newText;
_this.updateCursorPosition();
}
else {
_this.hiddenInput.value = _this.label.Text;
}
_this.updateSelectionAfterInput();
});
};
TextBox.prototype.getTextWidth = function (text) {
var _a;
if (!TextBox.measureCanvas) {
TextBox.measureCanvas = (_a = this.scene.game.canvas) !== null && _a !== void 0 ? _a : document.createElement('canvas');
TextBox.measureContext = TextBox.measureCanvas.getContext('2d');
}
var context = TextBox.measureContext;
if (!context) {
console.error('无法获取2D上下文');
return 0;
}
var fontSize = this.label.Label.style.fontSize || '16px';
var fontFamily = this.label.Label.style.fontFamily || 'Arial';
context.font = "".concat(fontSize, " ").concat(fontFamily);
return context.measureText(text).width;
};
TextBox.prototype.updateSelectionAfterInput = function () {
var _a;
if (this.hiddenInput) {
var cursorPosition = (_a = this.hiddenInput.selectionStart) !== null && _a !== void 0 ? _a : 0;
this.selectionStart = cursorPosition;
this.selectionEnd = cursorPosition;
this.selection.width = 0;
this.selection.setVisible(false);
this.updateCursorPosition();
this.cursor.setVisible(true);
}
};
TextBox.prototype.handleOver = function () {
this.scene.input.setDefaultCursor('text');
};
TextBox.prototype.handleOut = function () {
this.scene.input.setDefaultCursor('default');
};
TextBox.prototype.handlePointerDown = function (pointer) {
var _a;
this.isFocus = true;
(_a = this.hiddenInput) === null || _a === void 0 ? void 0 : _a.focus();
var worldPoint = this.getLabelWorldPoint();
var cursorX = pointer.x - worldPoint.x;
if (cursorX > this.label.TextWidth) {
cursorX = this.label.TextWidth;
}
this.cursor.x = cursorX;
this.cursor.setVisible(true);
this.selection.width = 0;
this.selection.setVisible(false);
this.setDomCursorPosition();
this.setNativeCursorPosition();
this.selection.x = this.cursor.x;
this.selectionStart = this.getCursorPosition();
this.selectionEnd = this.selectionStart;
this.isSelecting = true;
this.addTimerEvent();
};
TextBox.prototype.handlePointerMove = function (pointer) {
if (!this.isSelecting)
return;
var worldPoint = this.getLabelWorldPoint();
var cursorX = pointer.x - worldPoint.x;
if (cursorX > this.label.TextWidth) {
cursorX = this.label.TextWidth;
}
if (cursorX < 0) {
cursorX = 0;
}
this.selectionEnd = this.getCharacterIndexAtPosition(cursorX);
this.updateSelection();
};
TextBox.prototype.handlePointerUp = function () {
this.isSelecting = false;
if (this.selectionStart === this.selectionEnd) {
this.selection.setVisible(false);
}
};
TextBox.prototype.updateCursorPosition = function () {
var _a, _b;
var cursorPosition = (_b = (_a = this.hiddenInput) === null || _a === void 0 ? void 0 : _a.selectionStart) !== null && _b !== void 0 ? _b : 0;
this.cursor.x = this.getCharacterXPosition(cursorPosition);
};
TextBox.prototype.updateSelection = function () {
var _a;
if (this.selectionStart === undefined || this.selectionEnd === undefined)
return;
var start = Math.min(this.selectionStart, this.selectionEnd);
var end = Math.max(this.selectionStart, this.selectionEnd);
var startX = this.getCharacterXPosition(start);
var endX = this.getCharacterXPosition(end);
this.selection.x = startX;
this.selection.width = endX - startX;
this.selection.setVisible(true);
this.cursor.x = endX;
this.cursor.setVisible(true);
(_a = this.hiddenInput) === null || _a === void 0 ? void 0 : _a.setSelectionRange(start, end);
};
TextBox.prototype.handleMoveCursor = function () {
this.setNativeCursorPosition();
};
TextBox.prototype.setDomCursorPosition = function () {
var _a;
if (this.cursor.x > this.label.TextWidth) {
this.cursor.x = this.label.TextWidth;
}
var characterIndex = this.getCharacterIndexAtPosition(this.cursor.x);
(_a = this.hiddenInput) === null || _a === void 0 ? void 0 : _a.setSelectionRange(characterIndex, characterIndex);
};
TextBox.prototype.setNativeCursorPosition = function () {
var characterIndex = this.getCursorPosition();
var characterX = this.getCharacterXPosition(characterIndex);
this.cursor.x = characterX;
this.cursor.setVisible(true);
};
TextBox.prototype.getCharacterIndexAtPosition = function (x) {
var _a;
this.charWidths = this.getCharacterWidths();
var accumulatedWidth = 0;
for (var i = 0; i < this.label.Text.length; i++) {
accumulatedWidth += (_a = this.charWidths[i]) !== null && _a !== void 0 ? _a : 0;
if (x < accumulatedWidth) {
return i;
}
}
return this.label.Text.length;
};
TextBox.prototype.getCharacterWidths = function () {
var _a, _b;
if (!TextBox.measureCanvas) {
TextBox.measureCanvas = document.createElement('canvas');
TextBox.measureContext = TextBox.measureCanvas.getContext('2d');
}
var context = TextBox.measureContext;
if (!context) {
console.error('无法获取2D上下文');
return [];
}
var fontSize = this.label.Label.style.fontSize || '16px';
var fontFamily = this.label.Label.style.fontFamily || 'Arial';
context.font = "".concat(fontSize, " ").concat(fontFamily);
var charWidths = [];
var text = (_b = (_a = this.hiddenInput) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : '';
for (var i = 0; i < text.length; i++) {
var char = text[i];
var charWidth = context.measureText(char).width;
charWidths.push(charWidth);
}
return charWidths;
};
TextBox.prototype.getCharacterXPosition = function (index) {
var _a;
var charWidths = this.getCharacterWidths();
index = Math.min(index, charWidths.length);
var x = 0;
for (var i = 0; i < index; i++) {
x += (_a = charWidths[i]) !== null && _a !== void 0 ? _a : 0;
}
return x;
};
TextBox.prototype.addTimerEvent = function () {
var _this = this;
if (this.timerEvent)
return;
this.timerEvent = this.scene.time.addEvent({
delay: 800,
callback: function () {
_this.cursor.visible = !_this.cursor.visible;
},
callbackScope: this,
loop: true
});
};
TextBox.prototype.getLabelWorldPoint = function () {
var worldPoint = new Phaser.Math.Vector2();
var transformMatrix = this.label.getWorldTransformMatrix();
transformMatrix.transformPoint(this.label.x, this.label.y, worldPoint);
return worldPoint;
};
TextBox.prototype.destroy = function (fromScene) {
var _a, _b;
this.label.destroy(fromScene);
this.cursor.destroy(fromScene);
(_a = this.timerEvent) === null || _a === void 0 ? void 0 : _a.remove();
(_b = this.timerEvent) === null || _b === void 0 ? void 0 : _b.destroy();
if (this.hiddenInput) {
this.hiddenInput.remove();
}
_super.prototype.destroy.call(this, fromScene);
};
TextBox.measureCanvas = null;
TextBox.measureContext = null;
return TextBox;
}(Container));
export { TextBox };