我正在尝试编写此示例的修改版本。
使用 vanilla Javascript 一切正常,但现在我试图将其移动到 React 并且当我放大或缩小地图时弹出窗口不跟随地图。我想弹出窗口没有链接到地图叠加层,但它完全断开了它,这应该是问题,但我不知道如何解决它:
这是我的代码:
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;