Skip to content

Bundler Integration

Modern web development rely on package manager to bring project dependencies. This section covers how published releases can be used within a JavaScript project.

Project setup

In the simple example we are going to use Vite with Vanilla JavaScript. The full code is available for reference here.

json
{
  "name": "modern-app",
  "private": true,
  "version": "1.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "preview": "vite preview"
  },
  "devDependencies": {
    "vite": "^6.3.5"
  },
  "dependencies": {
    "@kitware/vtk-wasm": "latest"
  }
}
html
<!doctype html>
<html lang="en">

<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Standalone VTK.wasm example</title>
</head>

<body>
    <div id="app">
        <canvas tabindex="-1" onclick="focus()"></canvas>
    </div>
    <script type="module" src="/src/main.js"></script>
</body>

</html>
js
import "./style.css";
import { createNamespace } from "@kitware/vtk-wasm/vtk";
import { buildWASMScene } from "./example";

const VTK_WASM_TARBALL_URL = "https://gitlab.kitware.com/api/v4/projects/13/packages/generic/vtk-wasm32-emscripten/9.5.20251215/vtk-9.5.20251215-wasm32-emscripten.tar.gz";
createNamespace(VTK_WASM_TARBALL_URL).then((vtk) => {
  buildWASMScene(vtk, "#app > canvas", "This scene passes the VTK.wasm bundle from GitLab registry to createNamespace()");
});
js
export async function buildWASMScene(vtk, canvasSelector = "#vtk-wasm-window", titleText = "Sample VTK.wasm scene") {

  function createSharedTextProperty() {
    const textProperty = vtk.vtkTextProperty({ fontSize: 22 });
    return textProperty;
  }

  async function createLookupTable(scalarRange) {
    const lut = vtk.vtkColorTransferFunction();
    await lut.setColorSpaceToHSV();
    const colorSeries = vtk.vtkColorSeries({ colorScheme: 16 });
    const numColors = await colorSeries.getNumberOfColors();
    const scalarDiff = (scalarRange[1] - scalarRange[0]) / numColors;
    for (let i = 0; i < numColors; i++) {
      const color = await colorSeries.getColor(i);
      const t = scalarRange[0] + i * scalarDiff;
      lut.addRGBPoint(
        t,
        color[0] / 255,
        color[1] / 255,
        color[2] / 255,
      );
    }
    await lut.build();
    return lut;
  }

  async function createTitleTextActor(titleText, textProperty) {
    const textActor = vtk.vtkTextActor({ input: titleText, textProperty });
    const position = await textActor.getPositionCoordinate();
    await position.setCoordinateSystemToNormalizedViewport();
    return textActor;
  }

  // Create a VTK source. Output has a point data array named "Scalars" whose range is [0, PI].
  const shapes = vtk.vtkPartitionedDataSetCollectionSource({ numberOfShapes: 2 });
  const lut = await createLookupTable([0.0, Math.PI]);

  const mapper = vtk.vtkCompositePolyDataMapper({ lookupTable: lut });
  await mapper.setInputConnection(await shapes.getOutputPort());
  const actor = vtk.vtkActor({ mapper, scale: [0.1, 0.1, 0.1] });
  actor.property.edgeVisibility = true;
  actor.property.edgeColor = [0.2, 0.2, 0.2];

  const textProperty = createSharedTextProperty();

  // Create an actor that displays the title.
  const titleTextActor = await createTitleTextActor(titleText, textProperty);

  // Setup rendering part
  const renderer = vtk.vtkRenderer({ background: [0.384314, 0.364706, 0.352941] });
  await renderer.addActor(actor);
  await renderer.addActor(titleTextActor);
  await renderer.resetCamera();

  // Create a RenderWindow and bind it to a canvas in the DOM
  const renderWindow = vtk.vtkRenderWindow({ canvasSelector });
  await renderWindow.addRenderer(renderer);
  const interactor = vtk.vtkRenderWindowInteractor({
    canvasSelector,
    renderWindow,
  });
  await interactor.interactorStyle.setCurrentStyleToTrackballCamera();

  // Create camera widget
  const cameraOrientation = vtk.vtkCameraOrientationWidget({ interactor, parentRenderer: renderer });
  cameraOrientation.enabled = true;

  // Display the scalar bar at the bottom with a horizontal orientation
  const scalarBarActor = vtk.vtkScalarBarActor({
    lookupTable: lut,
    title: "Scalars",
    titleTextProperty: textProperty,
    labelTextProperty: textProperty,
    annotationTextProperty: textProperty,
    unconstrainedFontSize: true,
  });
  const scalarBar = vtk.vtkScalarBarWidget({ scalarBarActor, interactor, defaultRenderer: renderer });
  const scalarBarRepresentation = await scalarBar.getRepresentation();
  await scalarBarRepresentation.setOrientation(0); // 1: vertical, 0: horizontal
  const lowerLeftPosition = await scalarBarRepresentation.getPositionCoordinate();
  await lowerLeftPosition.setValue([0.1, 0.05]);
  scalarBar.enabled = true;

  // Trigger render and start interactor
  await interactor.start();
}
css
:root {
  font-family: system-ui, Avenir, Helvetica, Arial, sans-serif;
  line-height: 1.5;
  font-weight: 400;

  color-scheme: light dark;
  color: rgba(255, 255, 255, 0.87);
  background-color: #242424;

  font-synthesis: none;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

body {
  margin: 0;
  height: 100vh;
}

@media (prefers-color-scheme: light) {
  :root {
    color: #213547;
    background-color: #ffffff;
  }
}
bash
npm install
npm run build

Here, the VTK.wasm bundle is downloaded in the browser directly from the Gitlab package registry. See the src/main.js file for the relevant code.

Result

Full Screen Viewer