UNPKG

@kitware/vtk.js

Version:

Visualization Toolkit for the Web

157 lines (136 loc) 5.19 kB
import { m as macro } from '../../macros2.js'; const { vtkErrorMacro } = macro; // ---------------------------------------------------------------------------- const getRemoteFileSize = url => // This function only works if the server provides a 'Content-Length'. // For some reason, the 'Content-Length' header does not appear to be // given for CORS HEAD requests on firefox. So this will not work on // firefox if the images do not have the same origin as the html file. // TODO: figure out how to make this work for CORS requests on firefox. new Promise((resolve, reject) => { const xhr = new XMLHttpRequest(); xhr.open('HEAD', url, true); xhr.onreadystatechange = () => { if (xhr.readyState === 4) { if (xhr.status === 200) { const size = xhr.getResponseHeader('Content-Length'); resolve(size); } else { console.log('Failed to get remote file size of', url); reject(xhr); } } }; xhr.send(); }); // ---------------------------------------------------------------------------- // vtkTextureLODsDownloader methods // ---------------------------------------------------------------------------- function vtkTextureLODsDownloader(publicAPI, model) { // Set our className model.classHierarchy.push('vtkTextureLODsDownloader'); const internal = { downloadStack: [] }; //-------------------------------------------------------------------------- publicAPI.startDownloads = () => { if (!model.texture) { vtkErrorMacro('Texture was not set.'); return; } if (!model.files || model.files.length === 0) { vtkErrorMacro('No files set.'); return; } let baseUrl = model.baseUrl; if (baseUrl && !baseUrl.endsWith('/')) { baseUrl += '/'; } // Create the download stack internal.downloadStack = []; model.files.forEach(file => internal.downloadStack.push(`${baseUrl}${file}`)); const downloadNextTexture = () => { if (internal.downloadStack.length === 0) { return; } // For later use const asyncDownloadNextTexture = () => { setTimeout(downloadNextTexture, model.waitTimeBetweenDownloads); }; const img = new Image(); if (model.crossOrigin) { img.crossOrigin = model.crossOrigin; } const url = internal.downloadStack.shift(); getRemoteFileSize(url).then(size => { if (!size || size / 1024 > model.maxTextureLODSize) { if (!size) { console.log('Failed to get image size'); } else { console.log('Skipping image', url, ', because it is larger', 'than the max texture size:', model.maxTextureLODSize, 'KiB'); } asyncDownloadNextTexture(); return; } img.src = url; // Decode the image asynchronously in an attempt to prevent a // freeze during rendering. // In theory, this should help, but my profiling indicates that // it does not help much... maybe it is running in the main // thread anyways? img.decode().then(() => { model.texture.setImage(img); if (model.stepFinishedCallback) { model.stepFinishedCallback(); } asyncDownloadNextTexture(); }).catch(encodingError => { console.log('Failed to decode image:', img.src); console.log('Error is:', encodingError); asyncDownloadNextTexture(); }); }).catch(xhr => { console.log('Failed to get size of:', url); console.log('status was:', xhr.status); console.log('statusText was:', xhr.statusText); asyncDownloadNextTexture(); }); }; setTimeout(downloadNextTexture, model.waitTimeToStart); }; } // ---------------------------------------------------------------------------- // Object factory // ---------------------------------------------------------------------------- const DEFAULT_VALUES = { baseUrl: '', files: [], texture: null, crossOrigin: undefined, // The max texture LOD file size in KiB maxTextureLODSize: 50000, stepFinishedCallback: null, // These are in milliseconds waitTimeToStart: 4000, waitTimeBetweenDownloads: 0 }; // ---------------------------------------------------------------------------- function extend(publicAPI, model) { let initialValues = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; Object.assign(model, DEFAULT_VALUES, initialValues); macro.obj(publicAPI, model); // Create get-set macros macro.setGet(publicAPI, model, ['baseUrl', 'files', 'texture', 'crossOrigin', 'maxTextureLODSize', 'stepFinishedCallback', 'waitTimeToStart', 'waitTimeBetweenDownloads']); // Object specific methods vtkTextureLODsDownloader(publicAPI, model); } // ---------------------------------------------------------------------------- const newInstance = macro.newInstance(extend, 'vtkTextureLODsDownloader'); // ---------------------------------------------------------------------------- var vtkTextureLODsDownloader$1 = { newInstance, extend }; export { vtkTextureLODsDownloader$1 as default, extend, newInstance };