Всплывающие окна с открытыми слоями в React не следуют за масштабом карты - PullRequest
0 голосов
/ 14 февраля 2020

Я пытаюсь кодировать модифицированную версию этого примера .

Использование ванили Javascript все работает нормально, но сейчас я пытаюсь переместить его в React, и всплывающее окно не следует карте, когда я увеличиваю или уменьшаю карту. Я предполагаю, что всплывающее окно не связано с наложением карты, но оно полностью отсоединено от него, и это должно быть проблемой, но я не знаю, как это исправить:

The generated html

Это мой код:

import 'ol/ol.css';
import React, { Component } from "react";
import ReactDOM from 'react-dom';
import Map from 'ol/Map';
import View from 'ol/View';
import Overlay from 'ol/Overlay';
import { Tile as TileLayer, Vector as VectorLayer } from 'ol/layer';
import { OSM, Vector as VectorSource } from 'ol/source';
import { Circle as CircleStyle, Icon, Fill, Stroke, Style, Text } from 'ol/style';
import GeoJSON from 'ol/format/GeoJSON';
import * as olExtent from 'ol/extent';
import $ from 'jquery';
import 'bootstrap';
import markerLogo from './marker.png';


class PublicMap extends Component {
  constructor(props) {
    super(props);

    var shapeDisciplinare = this.props.geoJson;

    var iconStyle = new Style({
      image: new Icon({
        anchor: [0.5, 46],
        anchorXUnits: 'fraction',
        anchorYUnits: 'pixels',
        src: markerLogo
      }),
      text: new Text({
        font: '12px Calibri,sans-serif',
        fill: new Fill({ color: '#000' }),
        stroke: new Stroke({
          color: '#fff', width: 2
        })
      })
    });


    var getStyles = function (feature) {
      var myStyle = {
        'Point': iconStyle,
        'Polygon': new Style({
          stroke: new Stroke({
            color: 'blue',
            width: 3
          }),
          fill: new Fill({
            color: 'rgba(0, 0, 255, 0.1)'
          }),
          text: new Text({
            font: '12px Calibri,sans-serif',
            fill: new Fill({ color: '#000' }),
            stroke: new Stroke({
              color: '#fff', width: 2
            }),
            text: feature.getProperties().denominazione
          })
        })
      };
      return [myStyle[feature.getGeometry().getType()]];

    };

    var raster = new TileLayer({
      source: new OSM()
    });

    var source = new VectorSource();
    var vector = new VectorLayer({
      source: source,
      style: new Style({
        fill: new Fill({
          color: 'rgba(255, 255, 255, 0.2)'
        }),
        stroke: new Stroke({
          color: '#ffcc33',
          width: 2
        }),
        image: new CircleStyle({
          radius: 7,
          fill: new Fill({
            color: '#ffcc33'
          })
        })
      })
    });
    vector.setZIndex(1);

    this.olmap = new Map({
      layers: [raster, vector],
      target: null,
      view: new View({
        center: [-11000000, 4600000],
        zoom: 4
      })
    });

    var reader = new GeoJSON({
      defaultDataProjection: 'EPSG:3857',
      Projection: 'EPSG:3857'
    });

    var projector = {
      dataProjection: 'EPSG:4326',
      featureProjection: 'EPSG:3857'
    };

    let shapeDisciplinareJson = JSON.parse(shapeDisciplinare);
    var vectorSource = new VectorSource({
      features: reader.readFeatures(shapeDisciplinareJson, projector)
    });

    var vectorLayer = new VectorLayer({
      source: vectorSource,
      style: getStyles
    });

    this.state = { vs: vectorSource, vl: vectorLayer };
  }

  componentDidMount() {

    this.olmap.setTarget("map");
    var extent = olExtent.createEmpty();
    extent = olExtent.extend(extent, this.state.vs.getExtent());
    this.olmap.addLayer(this.state.vl);
    this.olmap.getView().fit(extent, this.olmap.getSize());
    this.olmap.getView().setZoom(8);

    var element = document.getElementById('popup');
    this.popup = new Overlay({
      element: ReactDOM.findDOMNode(this).querySelector('#popup'),
      positioning: 'bottom-center',
      stopEvent: false,
      offset: [0, -50]
    });

    // display popup on click
    this.olmap.on('click', (evt) => {
      var feature = this.olmap.forEachFeatureAtPixel(evt.pixel,
        (feature) => {
          return feature;
        });
      if (feature) {
        var coordinates = feature.getGeometry().getCoordinates();
        //if lenght is 2, then is a gps location, otherwise a shape
        if (coordinates.length === 2) {
          this.popup.setOffset([0, -50]);
          this.popup.setPosition(coordinates);
        } else {
          this.popup.setOffset([0, 0]);
          this.popup.setPosition(evt.coordinate);
        }
        this.olmap.addOverlay(this.popup);
        $(element).popover({
          'placement': 'top',
          'html': true,
          'content': feature.getProperties().denominazione
        });
        $(element).attr('data-content', feature.getProperties().denominazione);
        $(element).popover('show');
      } else {
        $(element).popover('hide');
      }

    });

    // change mouse cursor when over marker
    this.olmap.on('pointermove', (e) => {
      if (e.dragging) {
        $(element).popover('hide');
        return;
      }
      var pixel = this.olmap.getEventPixel(e.originalEvent);
      var hit = this.olmap.hasFeatureAtPixel(pixel);
      this.olmap.getTargetElement().style.cursor = hit ? 'pointer' : '';
    });


  }

  componentWillUnmount() {
    this.map.setTarget(null);
  }

  render() {
    return (
      <div id="map" style={{ width: "100%", height: "360px" }}>
        <div id="popup"></div>
      </div>
    );
  }
}

export default PublicMap;
...