@kitware/vtk.js
Version:
Visualization Toolkit for the Web
134 lines (118 loc) • 4.61 kB
JavaScript
import { m as macro } from '../../macros2.js';
import vtkPlaneSource from '../../Filters/Sources/PlaneSource.js';
import vtkTexture from './Texture.js';
import vtkActor2D from './Actor2D.js';
import vtkMapper2D from './Mapper2D.js';
import vtkTextProperty from './TextProperty.js';
import ImageHelper from '../../Common/Core/ImageHelper.js';
import { X as floatRGB2HexCode } from '../../Common/Core/Math/index.js';
// ----------------------------------------------------------------------------
// vtkTextActor methods
// ----------------------------------------------------------------------------
function vtkTextActor(publicAPI, model) {
// Set our className
model.classHierarchy.push('vtkTextActor');
publicAPI.makeProperty = vtkTextProperty.newInstance;
const texture = vtkTexture.newInstance({
resizable: true
});
const canvas = new OffscreenCanvas(1, 1);
const mapper = vtkMapper2D.newInstance();
const plane = vtkPlaneSource.newInstance({
xResolution: 1,
yResolution: 1
});
function createImageData(text) {
const fontSizeScale = publicAPI.getProperty().getFontSizeScale();
const fontStyle = publicAPI.getProperty().getFontStyle();
const fontFamily = publicAPI.getProperty().getFontFamily();
const fontColor = publicAPI.getProperty().getFontColor();
const shadowColor = publicAPI.getProperty().getShadowColor();
const shadowOffset = publicAPI.getProperty().getShadowOffset();
const shadowBlur = publicAPI.getProperty().getShadowBlur();
const resolution = publicAPI.getProperty().getResolution();
const backgroundColor = publicAPI.getProperty().getBackgroundColor();
const dpr = Math.max(window.devicePixelRatio || 1, 1);
const ctx = canvas.getContext('2d');
// Set the text properties to measure
const textSize = fontSizeScale(resolution) * dpr;
ctx.font = `${fontStyle} ${textSize}px "${fontFamily}"`;
ctx.textBaseline = 'middle';
ctx.textAlign = 'center';
// Measure the text
const metrics = ctx.measureText(text);
const textWidth = metrics.width / dpr;
const {
actualBoundingBoxLeft,
actualBoundingBoxRight,
actualBoundingBoxAscent,
actualBoundingBoxDescent
} = metrics;
const hAdjustment = (actualBoundingBoxLeft - actualBoundingBoxRight) / 2;
const vAdjustment = (actualBoundingBoxAscent - actualBoundingBoxDescent) / 2;
const textHeight = textSize / dpr - vAdjustment;
// Update canvas size to fit text and ensure it is at least 1x1 pixel
const width = Math.max(Math.round(textWidth * dpr), 1);
const height = Math.max(Math.round(textHeight * dpr), 1);
canvas.width = width;
canvas.height = height;
// Vertical flip
ctx.translate(0, height);
ctx.scale(1, -1);
// Clear the canvas
ctx.clearRect(0, 0, width, height);
if (backgroundColor) {
ctx.fillStyle = floatRGB2HexCode(backgroundColor);
ctx.fillRect(0, 0, width, height);
}
// Reset context after resize and prepare for rendering
ctx.imageSmoothingEnabled = true;
ctx.imageSmoothingQuality = 'high';
ctx.font = `${fontStyle} ${textSize}px "${fontFamily}"`;
ctx.fillStyle = floatRGB2HexCode(fontColor);
ctx.textBaseline = 'middle';
ctx.textAlign = 'center';
// Set shadow
if (shadowColor) {
ctx.shadowColor = floatRGB2HexCode(shadowColor);
ctx.shadowOffsetX = shadowOffset[0];
ctx.shadowOffsetY = shadowOffset[1];
ctx.shadowBlur = shadowBlur;
}
// Draw the text
ctx.fillText(text, width / 2 + hAdjustment, height / 2 + vAdjustment);
// Update plane dimensions to match text size
plane.set({
point1: [width, 0, 0],
point2: [0, height, 0]
});
return ImageHelper.canvasToImageData(canvas);
}
mapper.setInputConnection(plane.getOutputPort());
publicAPI.setMapper(mapper);
publicAPI.addTexture(texture);
model._onInputChanged = (_publicAPI, _model, value) => {
const image = createImageData(value);
texture.setInputData(image, 0);
};
}
// Default property values
const DEFAULT_VALUES = {
mapper: null,
property: null
};
function extend(publicAPI, model, initialValues = {}) {
Object.assign(model, DEFAULT_VALUES, initialValues);
// Inheritance
vtkActor2D.extend(publicAPI, model, initialValues);
// Build VTK API
macro.setGet(publicAPI, model, ['input']);
// Object methods
vtkTextActor(publicAPI, model);
}
const newInstance = macro.newInstance(extend, 'vtkTextActor');
var vtkTextActor$1 = {
newInstance,
extend
};
export { vtkTextActor$1 as default, extend, newInstance };