skin3d
Version:
Skin3d is a lightweight JS library that renders any Minecraft skin as a smooth, interactive 3D model you can drop straight into a webpage.
163 lines • 6.14 kB
JavaScript
/**
* @file Nametag.ts
* @description This file defines the NameTagObject class for creating Minecraft-style name tags.
* @author Cosmic-fi
* @license MIT
*/
import { CanvasTexture, NearestFilter, Sprite, SpriteMaterial } from "three";
/**
* A Minecraft name tag, i.e. a text label with background.
*/
export class NameTagObject extends Sprite {
constructor(text = "", options = {}) {
const material = new SpriteMaterial({
transparent: true,
alphaTest: 1e-5,
});
super(material);
/**
* A promise that is resolved after the name tag is fully painted.
*
* This will be a resolved promise, if
* {@link NameTagOptions.repaintAfterLoaded} is `false`, or
* the desired font is available when the `NameTagObject` is created.
*
* If {@link NameTagOptions.repaintAfterLoaded} is `true`, and
* the desired font hasn't been loaded when the `NameTagObject` is created,
* the name tag will be painted with the fallback font first, and then
* repainted with the desired font after it's loaded. This promise is
* resolved after repainting is done.
*/
Object.defineProperty(this, "painted", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "text", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "font", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "margin", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "textStyle", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "backgroundStyle", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "height", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "textMaterial", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
this.textMaterial = material;
this.text = text;
this.font = options.font === undefined ? "48px Minecraft" : options.font;
this.margin = options.margin === undefined ? [5, 10, 5, 10] : options.margin;
this.textStyle = options.textStyle === undefined ? "white" : options.textStyle;
this.backgroundStyle = options.backgroundStyle === undefined ? "rgba(0,0,0,.25)" : options.backgroundStyle;
this.height = options.height === undefined ? 4.0 : options.height;
const repaintAfterLoaded = options.repaintAfterLoaded === undefined ? true : options.repaintAfterLoaded;
if (repaintAfterLoaded && !document.fonts.check(this.font, this.text)) {
this.paint();
this.painted = this.loadAndPaint();
}
else {
this.paint();
this.painted = Promise.resolve();
}
}
/**
* Set the text of the name tag.
* @param newText The new text.
*/
async loadAndPaint() {
await document.fonts.load(this.font, this.text);
this.paint();
}
/**
* Paint the name tag.
* This method creates a canvas, draws the text and background,
* and applies it as a texture to the sprite.
* @private
*/
paint() {
const canvas = document.createElement("canvas");
/**
* Measure the text size
*
* @remarks
* We need to create the canvas and get the context first,
* because some browsers (e.g., Safari) require a canvas to measure text.
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Advanced_text_metrics}
*/
let ctx = canvas.getContext("2d");
ctx.font = this.font;
const metrics = ctx.measureText(this.text);
/**
* Resize the canvas to fit the text with margins
*/
canvas.width = this.margin[3] + metrics.actualBoundingBoxLeft + metrics.actualBoundingBoxRight + this.margin[1];
canvas.height =
this.margin[0] + metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent + this.margin[2];
/**
* Draw the background and text
* @remarks
* We need to get the context again after resizing the canvas,
* because resizing clears the canvas and resets the context.
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Optimizing_canvas#resizing_the_canvas
*/
ctx = canvas.getContext("2d");
ctx.font = this.font;
/**
* Draw the background
*/
ctx.fillStyle = this.backgroundStyle;
ctx.fillRect(0, 0, canvas.width, canvas.height);
/**
* Draw the text
*/
ctx.fillStyle = this.textStyle;
ctx.fillText(this.text, this.margin[3] + metrics.actualBoundingBoxLeft, this.margin[0] + metrics.actualBoundingBoxAscent);
/**
* Create the texture and apply it to the sprite
*/
const texture = new CanvasTexture(canvas);
texture.magFilter = NearestFilter;
texture.minFilter = NearestFilter;
this.textMaterial.map = texture;
this.textMaterial.needsUpdate = true;
/**
* Adjust the scale of the sprite to maintain aspect ratio
*/
this.scale.x = (canvas.width / canvas.height) * this.height;
this.scale.y = this.height;
}
}
//# sourceMappingURL=Nametag.js.map