我无法在Autodesk Forge Viewer中显示文本精灵。
我创建了一个示例项目ForgeTextSprite,它在加载的模型下显示一个罗盘玫瑰。虽然罗盘的度数显示正常,但不显示基数(N、S、E、W)的文本。
文本精灵。下面的ts文件已从三个spritetext转换为Typescript。我注释掉了三的用法。LinearFilter,因为它似乎不存在于Forge viewer中。
// Converted to Typescript from https://github.com/vasturiano/three-spritetext.
//
// Commented out usage to THREE.LinearFilter as that doesn't seem to be present in the
// Forge viewer.
export default class TextSprite extends THREE.Sprite {
_text: string;
_textHeight: number;
_color: string;
_backgroundColor: string;
_padding: number;
_borderWidth: number;
_borderColor: string;
_strokeWidth: number;
_strokeColor: string;
_fontFace: string;
_fontSize: number;
_fontWeight: string;
_canvas: HTMLCanvasElement;
_texture: THREE.Texture;
constructor(text = '', textHeight = 10, color = 'rgba(255, 255, 255, 1)') {
super(new THREE.SpriteMaterial({ map: new THREE.Texture() }));
this._text = `${text}`;
this._textHeight = textHeight;
this._color = color;
this._backgroundColor = ''; // no background color
this._padding = 0;
this._borderWidth = 0;
this._borderColor = 'blue';
this._strokeWidth = 0;
this._strokeColor = 'green';
this._fontFace = 'Arial';
this._fontSize = 90; // defines text resolution
this._fontWeight = 'normal';
this._canvas = document.createElement('canvas');
if (this.material instanceof THREE.SpriteMaterial) {
this._texture = this.material.map;
}
// this._texture.minFilter = three.LinearFilter;
this._genCanvas();
}
get text() { return this._text; }
set text(text) { this._text = text; this._genCanvas(); }
get textHeight() { return this._textHeight; }
set textHeight(textHeight) { this._textHeight = textHeight; this._genCanvas(); }
get color() { return this._color; }
set color(color) { this._color = color; this._genCanvas(); }
get backgroundColor() { return this._backgroundColor; }
set backgroundColor(color) { this._backgroundColor = color; this._genCanvas(); }
get padding() { return this._padding; }
set padding(padding) { this._padding = padding; this._genCanvas(); }
get borderWidth() { return this._borderWidth; }
set borderWidth(borderWidth) { this._borderWidth = borderWidth; this._genCanvas(); }
get borderColor() { return this._borderColor; }
set borderColor(borderColor) { this._borderColor = borderColor; this._genCanvas(); }
get fontFace() { return this._fontFace; }
set fontFace(fontFace) { this._fontFace = fontFace; this._genCanvas(); }
get fontSize() { return this._fontSize; }
set fontSize(fontSize) { this._fontSize = fontSize; this._genCanvas(); }
get fontWeight() { return this._fontWeight; }
set fontWeight(fontWeight) { this._fontWeight = fontWeight; this._genCanvas(); }
get strokeWidth() { return this._strokeWidth; }
set strokeWidth(strokeWidth) { this._strokeWidth = strokeWidth; this._genCanvas(); }
get strokeColor() { return this._strokeColor; }
set strokeColor(strokeColor) { this._strokeColor = strokeColor; this._genCanvas(); }
_genCanvas() {
const canvas = this._canvas;
const ctx = canvas.getContext('2d');
const border = [this.borderWidth, this.borderWidth]; // x,y border
const relBorder = border.map(b => b * this.fontSize * 0.1); // border in canvas units
const padding = [this.padding, this.padding]; // x,y padding
const relPadding = padding.map(p => p * this.fontSize * 0.1); // padding in canvas units
const lines = this.text.split('\n');
const font = `${this.fontWeight} ${this.fontSize}px ${this.fontFace}`;
ctx.font = font; // measure canvas with appropriate font
const innerWidth = Math.max(...lines.map(line => ctx.measureText(line).width));
const innerHeight = this.fontSize * lines.length;
canvas.width = innerWidth + relBorder[0] * 2 + relPadding[0] * 2;
canvas.height = innerHeight + relBorder[1] * 2 + relPadding[1] * 2;
// paint border
if (this.borderWidth) {
ctx.strokeStyle = this.borderColor;
if (relBorder[0]) {
ctx.lineWidth = relBorder[0] * 2;
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(0, canvas.height);
ctx.moveTo(canvas.width, 0);
ctx.lineTo(canvas.width, canvas.height);
ctx.stroke();
}
if (relBorder[1]) {
ctx.lineWidth = relBorder[1] * 2;
ctx.beginPath();
ctx.moveTo(relBorder[0], 0);
ctx.lineTo(canvas.width - relBorder[0], 0);
ctx.moveTo(relBorder[0], canvas.height);
ctx.lineTo(canvas.width - relBorder[0], canvas.height);
ctx.stroke();
}
}
ctx.translate(relBorder[0], relBorder[1]);
// paint background
if (this.backgroundColor) {
ctx.fillStyle = this.backgroundColor;
ctx.fillRect(0, 0, canvas.width - relBorder[0] * 2, canvas.height - relBorder[1] * 2);
}
ctx.translate(relPadding[0], relPadding[1]);
// paint text
ctx.font = font; // Set font again after canvas is resized, as context properties are reset
ctx.fillStyle = this.color;
ctx.textBaseline = 'bottom';
const drawTextStroke = this.strokeWidth > 0;
if (drawTextStroke) {
ctx.lineWidth = this.strokeWidth * this.fontSize / 10;
ctx.strokeStyle = this.strokeColor;
}
lines.forEach((line, index) => {
const lineX = (innerWidth - ctx.measureText(line).width) / 2;
const lineY = (index + 1) * this.fontSize;
drawTextStroke && ctx.strokeText(line, lineX, lineY);
ctx.fillText(line, lineX, lineY);
});
// Inject canvas into sprite
this._texture.image = canvas;
this._texture.needsUpdate = true;
const yScale = this.textHeight * lines.length + border[1] * 2 + padding[1] * 2;
this.scale.set(yScale * canvas.width / canvas.height, yScale, 0);
}
// clone(recursive?: boolean): this {
// return new SpriteText(this.text, this.textHeight, this.color).copy(this);
// }
copy(source: this, recursive?: boolean): this {
super.copy(source, recursive);
this.color = source.color;
this.backgroundColor = source.backgroundColor;
this.padding = source.padding;
this.borderWidth = source.borderWidth;
this.borderColor = source.borderColor;
this.fontFace = source.fontFace;
this.fontSize = source.fontSize;
this.fontWeight = source.fontWeight;
this.strokeWidth = source.strokeWidth;
this.strokeColor = source.strokeColor;
return this;
}
}
在ComPassRose.ts中,文本精灵被创建、翻译并旋转到适当的位置,然后添加到THREE. Group中。
import TextSprite from './TextSprite';
const markerLength = 1;
const fifthMarkerLength = 5;
const tenthMarkerLength = 10;
const ordinalMarkerLength = 15;
const color = 0x444444;
const fontSize = 4;
const halfFontSize = fontSize / 2;
const radius = 100;
const cardinalOuter = radius + 10;
export default class CompassRose {
build(): THREE.Group {
const group = new THREE.Group();
const material = new THREE.LineBasicMaterial({
color: color
});
for (let degree = 0; degree < 360; degree++) {
const lineParent = new THREE.Group();
const lineAngle = (Math.PI * degree) / 180;
lineParent.rotateX(lineAngle);
const length = this.getMarkerLength(degree);
const line = this.buildLine(radius, length, material);
lineParent.add(line);
group.add(lineParent);
}
let sprite = this.createHeadingTextSprite("N")
.translateX(cardinalOuter - fontSize)
.translateY(halfFontSize)
.rotateZ(-Math.PI / 2);
group.add(sprite);
sprite = this.createHeadingTextSprite("S")
.translateX(-cardinalOuter)
.translateY(halfFontSize)
.rotateZ(-Math.PI / 2);
group.add(sprite);
sprite = this.createHeadingTextSprite("W")
.translateY(cardinalOuter)
.translateX(-halfFontSize)
.rotateZ(-Math.PI / 2);
group.add(sprite);
sprite = this.createHeadingTextSprite("E")
.translateY(-cardinalOuter + fontSize)
.translateX(-halfFontSize)
.rotateZ(-Math.PI / 2);
group.add(sprite);
return group;
}
private getMarkerLength(degree: number) {
let length: number;
if (degree % 90 === 0) {
length = ordinalMarkerLength;
} else if (degree % 10 === 0) {
length = tenthMarkerLength;
} else if (degree % 5 === 0) {
length = fifthMarkerLength;
} else {
length = markerLength;
}
return length;
}
private buildLine(radius: number, length: number, material: THREE.Material) {
const lineGeometry = new THREE.Geometry();
lineGeometry.vertices.push(new THREE.Vector3(0, radius, 0));
lineGeometry.vertices.push(new THREE.Vector3(0, radius - length, 0));
return new THREE.Line(lineGeometry, material);
}
private createHeadingTextSprite(text: string): THREE.Sprite {
return new TextSprite(text, 10, '#888888');
}
}
浏览器控制台窗口中不显示任何错误。
请注意,Forge Viewer基于以下三个方面。js版本R71。在代码中,您似乎使用了三种类型定义。js R103,三个spritetext依赖项引用三个。JSR86。恐怕是这些版本的差异导致了文本精灵呈现的无声失败。
作为一种选择,我建议: