add text scaling, kerning
This commit is contained in:
parent
dda980b100
commit
c6dd4c304c
2 changed files with 48 additions and 20 deletions
|
|
@ -451,8 +451,9 @@ function canvasInMesh(w, h, textAlign, textBaseline, color, size) {
|
|||
*/
|
||||
let text3d = new Text3D({
|
||||
chars: '0123456789-XY',
|
||||
atlasCharSize: 64,
|
||||
kerning: 0.5, // Tighter spacing than default
|
||||
charSize: 64,
|
||||
kerning: 0.6,
|
||||
scaleX: 0.7,
|
||||
fontFamily: "'Russo One', sans-serif"
|
||||
});
|
||||
|
||||
|
|
@ -504,7 +505,6 @@ function updateRulers() {
|
|||
for (let i = 0; i <= ruler.x2; i += grid.unitMajor) {
|
||||
const value = (i * factor).round(1).toString();
|
||||
const label = text3d.createLabel(value, labelSize, rulerColor, 'center');
|
||||
|
||||
label.position.set(ruler.x2 - i, -h - labelSize * 2, zp);
|
||||
label.rotation.x = Math.PI;
|
||||
view.add(label);
|
||||
|
|
@ -513,7 +513,6 @@ function updateRulers() {
|
|||
for (let i = 0; i >= ruler.x1; i -= grid.unitMajor) {
|
||||
const value = (i * factor).round(1).toString();
|
||||
const label = text3d.createLabel(value, labelSize, rulerColor, 'center');
|
||||
|
||||
label.position.set(ruler.xo + i - w, -h - labelSize * 2, zp);
|
||||
label.rotation.x = Math.PI;
|
||||
view.add(label);
|
||||
|
|
@ -521,7 +520,6 @@ function updateRulers() {
|
|||
for (let i = 0; i <= ruler.x2; i += grid.unitMajor) {
|
||||
const value = (i * factor).round(1).toString();
|
||||
const label = text3d.createLabel(value, labelSize, rulerColor, 'center');
|
||||
|
||||
label.position.set(ruler.xo + i - w, -h - labelSize * 2, zp);
|
||||
label.rotation.x = Math.PI;
|
||||
view.add(label);
|
||||
|
|
@ -544,7 +542,6 @@ function updateRulers() {
|
|||
for (let i = 0; i >= ruler.y1; i -= grid.unitMajor) {
|
||||
const value = (i * factor).round(1).toString();
|
||||
const label = text3d.createLabel(value, labelSize, rulerColor, 'right');
|
||||
|
||||
label.position.set(-w - labelSize * 2 - 5, -h + ruler.yo + i, zp);
|
||||
label.rotation.x = Math.PI;
|
||||
view.add(label);
|
||||
|
|
@ -552,7 +549,6 @@ function updateRulers() {
|
|||
for (let i = 0; i <= ruler.y2; i += grid.unitMajor) {
|
||||
const value = (i * factor).round(1).toString();
|
||||
const label = text3d.createLabel(value, labelSize, rulerColor, 'right');
|
||||
|
||||
label.position.set(-w - labelSize * 2 - 5, -h + ruler.yo + i, zp);
|
||||
label.rotation.x = Math.PI;
|
||||
view.add(label);
|
||||
|
|
|
|||
|
|
@ -12,20 +12,22 @@ class Text3D {
|
|||
* Create a 3D text renderer.
|
||||
* @param {object} options - Configuration options
|
||||
* @param {string} options.chars - Characters to include in atlas (default: '0123456789-XY')
|
||||
* @param {number} options.atlasCharSize - Size of each character in atlas texture (default: 64)
|
||||
* @param {number} options.charSize - Size of each character in atlas texture (default: 64)
|
||||
* @param {number} options.kerning - Character spacing multiplier (default: 0.5, lower = tighter)
|
||||
* @param {string} options.fontFamily - CSS font family string (default: 'Russo One, sans-serif')
|
||||
* @param {number} options.scaleX - Default horizontal scale (default: 1.0)
|
||||
* @param {number} options.scaleY - Default vertical scale (default: 1.0)
|
||||
* @param {string} options.fontFamily - CSS font family string (default: 'sans-serif')
|
||||
*/
|
||||
constructor(options = {}) {
|
||||
this.chars = options.chars || '0123456789-XY';
|
||||
this.atlasCharSize = options.atlasCharSize || 64;
|
||||
this.charSize = options.charSize || 64;
|
||||
this.kerning = options.kerning !== undefined ? options.kerning : 0.5;
|
||||
this.fontFamily = options.fontFamily || "'Russo One', sans-serif";
|
||||
|
||||
this.scaleX = options.scaleX !== undefined ? options.scaleX : 1.0;
|
||||
this.scaleY = options.scaleY !== undefined ? options.scaleY : 1.0;
|
||||
this.fontFamily = options.fontFamily || "sans-serif";
|
||||
this.atlas = null;
|
||||
this.geometries = {}; // Cached geometries per character
|
||||
this.material = null; // Shared material for all characters
|
||||
|
||||
this._initialize();
|
||||
}
|
||||
|
||||
|
|
@ -46,7 +48,7 @@ class Text3D {
|
|||
_createAtlas() {
|
||||
const canvas = document.createElement('canvas');
|
||||
const ctx = canvas.getContext('2d');
|
||||
const charSize = this.atlasCharSize;
|
||||
const charSize = this.charSize;
|
||||
|
||||
canvas.width = charSize * this.chars.length;
|
||||
canvas.height = charSize;
|
||||
|
|
@ -131,13 +133,17 @@ class Text3D {
|
|||
* @param {string|number} color - Text color (CSS string or hex number)
|
||||
* @param {string} align - Horizontal alignment ('left', 'center', 'right')
|
||||
* @param {number} kerning - Optional kerning override for this label
|
||||
* @param {number} scaleX - Optional horizontal scale override for this label
|
||||
* @param {number} scaleY - Optional vertical scale override for this label
|
||||
* @returns {THREE.Group} Group containing character meshes
|
||||
*/
|
||||
createLabel(text, size, color = 0x333333, align = 'center', kerning) {
|
||||
createLabel(text, size, color = 0x333333, align = 'center', kerning, scaleX, scaleY) {
|
||||
const group = new THREE.Group();
|
||||
const spacing = kerning !== undefined ? kerning : this.kerning;
|
||||
const charWidth = size * spacing;
|
||||
const totalWidth = text.length * charWidth;
|
||||
const sx = scaleX !== undefined ? scaleX : this.scaleX;
|
||||
const sy = scaleY !== undefined ? scaleY : this.scaleY;
|
||||
const charSpacing = size * spacing * sx; // Distance between character centers (account for width scale)
|
||||
const totalWidth = text.length * charSpacing;
|
||||
|
||||
// Convert CSS color string to THREE.Color if needed
|
||||
let threeColor = color;
|
||||
|
|
@ -171,9 +177,9 @@ class Text3D {
|
|||
|
||||
const mesh = new THREE.Mesh(geometry, material);
|
||||
|
||||
// Scale and position the unit-sized geometry
|
||||
mesh.scale.set(charWidth, size, 1);
|
||||
mesh.position.x = startX + i * charWidth + charWidth / 2;
|
||||
// Apply size and scale
|
||||
mesh.scale.set(size * sx, size * sy, 1);
|
||||
mesh.position.x = startX + i * charSpacing + charSpacing / 2;
|
||||
|
||||
group.add(mesh);
|
||||
}
|
||||
|
|
@ -189,6 +195,32 @@ class Text3D {
|
|||
this.kerning = kerning;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update horizontal scale for future labels.
|
||||
* @param {number} scaleX - New horizontal scale value
|
||||
*/
|
||||
setScaleX(scaleX) {
|
||||
this.scaleX = scaleX;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update vertical scale for future labels.
|
||||
* @param {number} scaleY - New vertical scale value
|
||||
*/
|
||||
setScaleY(scaleY) {
|
||||
this.scaleY = scaleY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update both scales for future labels.
|
||||
* @param {number} scaleX - New horizontal scale value
|
||||
* @param {number} scaleY - New vertical scale value
|
||||
*/
|
||||
setScale(scaleX, scaleY) {
|
||||
this.scaleX = scaleX;
|
||||
this.scaleY = scaleY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean up resources.
|
||||
*/
|
||||
|
|
|
|||
Loading…
Reference in a new issue