UNPKG

@terrestris/ol-util

Version:

A set of helper classes for working with openLayers

93 lines (84 loc) 3.06 kB
import _isFunction from 'lodash/isFunction'; import _isNil from 'lodash/isNil'; import OlFeature from 'ol/Feature'; import OlGeometry from 'ol/geom/Geometry'; import OlLayerVector from 'ol/layer/Vector'; import OlMap from 'ol/Map'; import { unByKey } from 'ol/Observable'; import { getVectorContext } from 'ol/render'; import OlSourceVector from 'ol/source/Vector'; import OlStyle from 'ol/style/Style'; /** * This class provides some static methods which might be helpful when working * with digitize functions to animate features. * * @class AnimateUtil */ class AnimateUtil { /** * Moves / translates an `OlFeature` to the given `pixel` delta * in the end with given `duration` in ms, using the given style. * * @param {import("ol/Map").default} map An OlMap. * @param {import("ol/layer/Vector").default<import("ol/source/Vector").default>} layer A vector layer to receive a * postrender event. * @param {import("ol/Feature").default} featureToMove The feature to move. * @param {number} duration The duration in ms for the moving to complete. * @param {number} pixel Delta of pixels to move the feature. * @param {import("ol/style/Style").default} [style] The style to use when moving the feature. * * @return {Promise<import("ol/Feature").default>} Promise of the moved feature. */ static moveFeature( map: OlMap, layer: OlLayerVector<OlSourceVector>, featureToMove: OlFeature<OlGeometry>, duration: number, pixel: number, style: OlStyle ): Promise<OlFeature<OlGeometry>> { return new Promise(resolve => { const geometry = featureToMove.getGeometry(); if (_isNil(geometry)) { throw new Error('Feature has no geometry.'); } const start = Date.now(); const resolution = map.getView().getResolution() ?? 0; const totalDisplacement = pixel * resolution; const expectedFrames = duration / 1000 * 60; let actualFrames = 0; const deltaX = totalDisplacement / expectedFrames; const deltaY = totalDisplacement / expectedFrames; /** * Moves the feature `pixel` right and `pixel` up. * @ignore */ const listenerKey = layer.on('postrender', (event) => { const vectorContext = getVectorContext(event); const frameState = event.frameState; if (!frameState) { return; } const elapsed = frameState.time - start; geometry.translate(deltaX, deltaY); if (style) { if (_isFunction(style)) { vectorContext.setStyle(style(featureToMove)); } else { vectorContext.setStyle(style); } } vectorContext.drawGeometry(geometry); if (elapsed > duration || actualFrames >= expectedFrames) { unByKey(listenerKey); resolve(featureToMove); } // tell OpenLayers to continue postrender animation frameState.animate = true; actualFrames++; map.render(); }); }); } } export default AnimateUtil;