@acransac/vtk.js
Version:
Visualization Toolkit for the Web
196 lines (171 loc) • 5.86 kB
JavaScript
/* eslint-disable import/prefer-default-export */
/* eslint-disable import/no-extraneous-dependencies */
import 'vtk.js/Sources/favicon';
import vtkFullScreenRenderWindow from 'vtk.js/Sources/Rendering/Misc/FullScreenRenderWindow';
import vtkHttpSceneLoader from 'vtk.js/Sources/IO/Core/HttpSceneLoader';
import DataAccessHelper from 'vtk.js/Sources/IO/Core/DataAccessHelper';
import vtkURLExtract from 'vtk.js/Sources/Common/Core/URLExtract';
import vtkOBJReader from 'vtk.js/Sources/IO/Misc/OBJReader';
import vtkMapper from 'vtk.js/Sources/Rendering/Core/Mapper';
import vtkActor from 'vtk.js/Sources/Rendering/Core/Actor';
import controlWidget from './SceneControllerWidget';
import style from './SceneLoader.module.css';
const iOS = /iPad|iPhone|iPod/.test(window.navigator.platform);
let autoInit = true;
let widgetCreated = false;
// Add class to body if iOS device --------------------------------------------
if (iOS) {
document.querySelector('body').classList.add('is-ios-device');
}
function emptyContainer(container) {
while (container.firstChild) {
container.removeChild(container.firstChild);
}
}
function downloadZipFile(url) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.onreadystatechange = (e) => {
if (xhr.readyState === 4) {
if (xhr.status === 200 || xhr.status === 0) {
resolve(xhr.response);
} else {
reject(xhr, e);
}
}
};
// Make request
xhr.open('GET', url, true);
xhr.responseType = 'arraybuffer';
xhr.send();
});
}
export function load(container, options) {
autoInit = false;
emptyContainer(container);
const fullScreenRenderer = vtkFullScreenRenderWindow.newInstance();
const renderer = fullScreenRenderer.getRenderer();
const renderWindow = fullScreenRenderer.getRenderWindow();
function onReady(sceneImporter) {
sceneImporter.onReady(() => {
renderWindow.render();
// Add UI to dynamically change rendering settings
if (!widgetCreated) {
widgetCreated = true;
controlWidget(
document.querySelector('body'),
sceneImporter.getScene(),
renderWindow.render
);
}
});
window.addEventListener('dblclick', () => {
sceneImporter.resetScene();
renderWindow.render();
});
}
if (options.url) {
const sceneImporter = vtkHttpSceneLoader.newInstance({ renderer });
sceneImporter.setUrl(options.url);
onReady(sceneImporter);
} else if (options.fileURL) {
downloadZipFile(options.fileURL).then((zipContent) => {
const dataAccessHelper = DataAccessHelper.get('zip', {
zipContent,
callback: (zip) => {
const sceneImporter = vtkHttpSceneLoader.newInstance({
renderer,
dataAccessHelper,
});
sceneImporter.setUrl('index.json');
onReady(sceneImporter);
},
});
});
} else if (options.file) {
if (options.ext === 'obj') {
const scene = [];
const reader = new FileReader();
reader.onload = function onLoad(e) {
const objReader = vtkOBJReader.newInstance();
objReader.parse(reader.result);
const nbOutputs = objReader.getNumberOfOutputPorts();
for (let idx = 0; idx < nbOutputs; idx++) {
const source = objReader.getOutputData(idx);
const mapper = vtkMapper.newInstance();
const actor = vtkActor.newInstance();
actor.setMapper(mapper);
mapper.setInputData(source);
renderer.addActor(actor);
scene.push({
name: source.get('name').name,
source,
mapper,
actor,
});
}
onReady({
getScene() {
return scene;
},
resetScene() {
renderer.resetCamera();
},
onReady(fn) {
renderer.resetCamera();
renderWindow.render();
fn();
},
});
};
reader.readAsText(options.file);
} else {
const dataAccessHelper = DataAccessHelper.get('zip', {
zipContent: options.file,
callback: (zip) => {
const sceneImporter = vtkHttpSceneLoader.newInstance({
renderer,
dataAccessHelper,
});
sceneImporter.setUrl('index.json');
onReady(sceneImporter);
},
});
}
}
}
export function initLocalFileLoader(container) {
autoInit = false;
const exampleContainer = document.querySelector('.content');
const rootBody = document.querySelector('body');
const myContainer = container || exampleContainer || rootBody;
const fileSelector = document.createElement('input');
fileSelector.setAttribute('type', 'file');
fileSelector.setAttribute('class', style.bigFileDrop);
myContainer.appendChild(fileSelector);
myContainer.setAttribute('class', style.fullScreen);
function handleFile(e) {
const files = this.files;
if (files.length === 1) {
myContainer.removeChild(fileSelector);
const ext = files[0].name.split('.').slice(-1)[0];
load(myContainer, { file: files[0], ext });
}
}
fileSelector.onchange = handleFile;
}
// Look at URL an see if we should load a file
// ?fileURL=https://data.kitware.com/api/v1/item/587003d08d777f05f44a5c98/download?contentDisposition=inline
const userParams = vtkURLExtract.extractURLParameters();
if (userParams.url || userParams.fileURL) {
const exampleContainer = document.querySelector('.content');
const rootBody = document.querySelector('body');
const myContainer = exampleContainer || rootBody;
load(myContainer, userParams);
}
// Auto setup if no method get called within 100ms
setTimeout(() => {
if (autoInit) {
initLocalFileLoader();
}
}, 100);