Source: custom-plugins/plugin-pointer.js

/** @module */

import VectorLayer from 'ol/layer/Vector'
import VectorSource from 'ol/source/Vector'
import Feature from 'ol/Feature'
import Point from 'ol/geom/Point'
import Style from 'ol/style/Style'
import Stroke from 'ol/style/Stroke'
import Circle from 'ol/style/Circle'
import { getImageXY, image2world } from '@dataforsyningen/saul'
import { state } from '../state/index.js'
import { configuration } from "../modules/configuration";


/**
 * Creates an Openlayers layer with a pointer marker.
 * @returns An Openlayers layer with a pointer marker.
 */
function generatePointerLayer() {
  const source = new VectorSource({
    features: [new Feature(new Point([-9999, -9999]))]
  })
  const colorSetting = configuration.COLOR_SETTINGS.pointerColor
  const style = new Style({
    image: new Circle({
      radius: 4,
      stroke: new Stroke({
        color: colorSetting, // advarsel
        width: 2
      })
    }),
    zIndex: Infinity
  })
  const layer = new VectorLayer({
    source: source,
    style: style,
    title: 'Pointer'
  })
  layer.setZIndex(10)
  return layer
}

/**
 * Updates the pointer for the map to the given position.
 * @param {ol.Map} map The map to update. The map needs to previously have added a pointer layer generated using
 * the generatePointerLayer function.
 * @param {number[]} position The position in the maps coordinates.
 */
function updatePointer(map, position) {
  const layer = map.getLayers().getArray().find((pLayer) => {
    return pLayer.get('title') === 'Pointer'
  })
  const source = layer.getSource()
  source.getFeatures()[0].getGeometry().setCoordinates(position)
}

/**
 * Adds a pointerLayer to a viewport.
 * @param {*} viewport The viewport.
 */
function addPointerLayerToViewport(viewport) {
  /**
   * Similar to the zoom sync problem above, we can not get the exact Z value based on the image coordinates.
   * We use the coord_world Z coordinate again.
   */
  viewport.map.addLayer(generatePointerLayer())
  viewport.map.on('pointermove', event => {
    const coord = image2world(viewport.item, event.coordinate[0], event.coordinate[1], viewport.coord_world[2] = 0)
    state.setPointerPosition = {point: coord}
  })
}

/**
 * Function for updating a viewport pointer.
 */
function updateViewportPointer(viewport, coord, itemkey) {
  if (!coord || !itemkey || !viewport || !state.items[itemkey]) {
    return
  }
  if (state.pointerItemkey === itemkey) {
    updatePointer(viewport.map, [-9999, -9999])
  } else {
    const position = getImageXY(state.items[itemkey], coord[0], coord[1], state.view.kote)
    updatePointer(viewport.map, position)
  }
}

/**
 * Adds a pointerLayer to a map.
 * @param {ol.Map} map The map.
 */
function addPointerLayerToMap(map) {
  map.addLayer(generatePointerLayer())
  map.on('pointermove', event => {
    /**
     * It is too expensive to get the Z value for every point, so we use the most recent value stored from
     * zoom sync instead.
     */
    const coord = [event.coordinate[0], event.coordinate[1], state.view.kote || 0]
    window.dispatchEvent(new CustomEvent("updatePointer", { detail: { coord: coord, map: map } }))
  })
}

/**
 * Gets a function for updating the map pointer.
 * @param {ol.Map} map The map.
 * @returns {function} The map pointer update function.
 */
function getUpdateMapPointerFunction(map) {
  return event => {
    if (event.detail.map === map) {
      updatePointer(map, [-9999, -9999])
    } else {
      const coord = event.detail.coord
      updatePointer(map, [coord[0], coord[1]])
    }
  }
}

export {
  updatePointer,
  generatePointerLayer,
  addPointerLayerToViewport,
  updateViewportPointer,
  addPointerLayerToMap,
  getUpdateMapPointerFunction
}