UNPKG

@thewtex/vtk.js-esm

Version:

Visualization Toolkit for the Web

219 lines (172 loc) 8.04 kB
import macro from '../../macro.js'; import vtkCompositeMouseManipulator from './CompositeMouseManipulator.js'; // vtkMouseRangeManipulator methods // ---------------------------------------------------------------------------- function vtkMouseRangeManipulator(publicAPI, model) { // Set our className model.classHierarchy.push('vtkMouseRangeManipulator'); // Keep track of delta that is below the value // of one step to progressively increment it var incrementalDelta = new Map(); // Internal methods //------------------------------------------------------------------------- function scaleDeltaToRange(listener, normalizedDelta) { return normalizedDelta * ((listener.max - listener.min) / (listener.step + 1)); } //------------------------------------------------------------------------- function processDelta(listener, delta) { var oldValue = listener.getValue(); // Apply scale and cached delta to current delta var newDelta = delta * listener.scale + incrementalDelta.get(listener); var value = oldValue + newDelta; // Compute new value based on step var difference = value - listener.min; var stepsToDifference = Math.round(difference / listener.step); value = listener.min + listener.step * stepsToDifference; value = Math.max(value, listener.min); value = Math.min(value, listener.max); if (value !== oldValue) { // Update value listener.setValue(value); incrementalDelta.set(listener, 0); } else if (value === listener.min && newDelta < 0 || value === listener.max && newDelta > 0) { // Do not allow incremental delta to go past range incrementalDelta.set(listener, 0); } else { // Store delta for the next iteration incrementalDelta.set(listener, newDelta); } } // Public API methods // min:number = minimum allowable value // max:number = maximum allowable value // step:number = value per step -- smaller = more steps over a given distance, larger = fewer steps over a given distance // getValue:fn = function that returns current value // setValue:fn = function to set value // scale:number = scale value is applied to mouse event to allow users accelerate or decelerate delta without emitting more events //------------------------------------------------------------------------- publicAPI.setHorizontalListener = function (min, max, step, getValue, setValue) { var scale = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 1; var getFn = Number.isFinite(getValue) ? function () { return getValue; } : getValue; model.horizontalListener = { min: min, max: max, step: step, getValue: getFn, setValue: setValue, scale: scale }; incrementalDelta.set(model.horizontalListener, 0); publicAPI.modified(); }; //------------------------------------------------------------------------- publicAPI.setVerticalListener = function (min, max, step, getValue, setValue) { var scale = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 1; var getFn = Number.isFinite(getValue) ? function () { return getValue; } : getValue; model.verticalListener = { min: min, max: max, step: step, getValue: getFn, setValue: setValue, scale: scale }; incrementalDelta.set(model.verticalListener, 0); publicAPI.modified(); }; //------------------------------------------------------------------------- publicAPI.setScrollListener = function (min, max, step, getValue, setValue) { var scale = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 1; var getFn = Number.isFinite(getValue) ? function () { return getValue; } : getValue; model.scrollListener = { min: min, max: max, step: step, getValue: getFn, setValue: setValue, scale: scale }; incrementalDelta.set(model.scrollListener, 0); publicAPI.modified(); }; //------------------------------------------------------------------------- publicAPI.removeHorizontalListener = function () { if (model.verticalListener) { incrementalDelta.delete(model.verticalListener); delete model.verticalListener; publicAPI.modified(); } }; //------------------------------------------------------------------------- publicAPI.removeVerticalListener = function () { if (model.horizontalListener) { incrementalDelta.delete(model.horizontalListener); delete model.horizontalListener; publicAPI.modified(); } }; //------------------------------------------------------------------------- publicAPI.removeScrollListener = function () { if (model.scrollListener) { incrementalDelta.delete(model.scrollListener); delete model.scrollListener; publicAPI.modified(); } }; //------------------------------------------------------------------------- publicAPI.removeAllListeners = function () { publicAPI.removeHorizontalListener(); publicAPI.removeVerticalListener(); publicAPI.removeScrollListener(); }; //------------------------------------------------------------------------- publicAPI.onButtonDown = function (interactor, renderer, position) { model.previousPosition = position; var glRenderWindow = interactor.getView(); // Ratio is the dom size vs renderwindow size var ratio = glRenderWindow.getContainerSize()[0] / glRenderWindow.getSize()[0]; // Get proper pixel range used by viewport in rw size space var size = glRenderWindow.getViewportSize(renderer); // rescale size to match mouse event position model.containerSize = size.map(function (v) { return v * ratio; }); }; //------------------------------------------------------------------------- publicAPI.onMouseMove = function (interactor, renderer, position) { if (!model.verticalListener && !model.horizontalListener) { return; } if (!position) { return; } if (model.horizontalListener) { var dxNorm = (position.x - model.previousPosition.x) / model.containerSize[0]; var dx = scaleDeltaToRange(model.horizontalListener, dxNorm); processDelta(model.horizontalListener, dx); } if (model.verticalListener) { var dyNorm = (position.y - model.previousPosition.y) / model.containerSize[1]; var dy = scaleDeltaToRange(model.verticalListener, dyNorm); processDelta(model.verticalListener, dy); } model.previousPosition = position; }; //------------------------------------------------------------------------- publicAPI.onScroll = function (interactor, renderer, delta) { if (!model.scrollListener || !delta) { return; } processDelta(model.scrollListener, delta * model.scrollListener.step); }; publicAPI.onStartScroll = publicAPI.onScroll; } // ---------------------------------------------------------------------------- // Object factory // ---------------------------------------------------------------------------- var DEFAULT_VALUES = { horizontalListener: null, verticalListener: null, scrollListener: null }; // ---------------------------------------------------------------------------- function extend(publicAPI, model) { var initialValues = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; Object.assign(model, DEFAULT_VALUES, initialValues); // Inheritance macro.obj(publicAPI, model); vtkCompositeMouseManipulator.extend(publicAPI, model, initialValues); // Object specific methods vtkMouseRangeManipulator(publicAPI, model); } // ---------------------------------------------------------------------------- var newInstance = macro.newInstance(extend, 'vtkMouseRangeManipulator'); // ---------------------------------------------------------------------------- var vtkMouseRangeManipulator$1 = { newInstance: newInstance, extend: extend }; export default vtkMouseRangeManipulator$1; export { extend, newInstance };