|
@@ -11,7 +11,7 @@
|
|
|
*/
|
|
|
|
|
|
import { Path, withLeaflet } from 'react-leaflet';
|
|
|
-import { CircleMarker, GeoJSON, Icon, LayerGroup, Marker, Polygon, Polyline } from 'leaflet';
|
|
|
+import { CircleMarker, DivIcon, GeoJSON, Icon, LayerGroup, Marker, Polygon, Polyline } from 'leaflet';
|
|
|
import deepEqual from 'fast-deep-equal';
|
|
|
import PubSub from 'pubsub-js';
|
|
|
|
|
@@ -37,6 +37,21 @@ const MyIcon = Icon.extend({
|
|
|
*/
|
|
|
class StyledLayer extends Path {
|
|
|
createLeafletElement(props) {
|
|
|
+ if(window.CONFIG.map_zoom_control_marker){
|
|
|
+ //clone data
|
|
|
+ this.cahedFeatures = JSON.parse(JSON.stringify(props.data.features));
|
|
|
+
|
|
|
+ //sub event
|
|
|
+ PubSub.subscribe("map.zoom.changed", (msg, data) => {
|
|
|
+ this.leafletElement.clearLayers();
|
|
|
+ this.props.data.features = this._filterData(data.zoom);
|
|
|
+ this._populateLayer(this.leafletElement, this.props);
|
|
|
+ this._sortFeaturesZIndex(this.leafletElement);
|
|
|
+ })
|
|
|
+
|
|
|
+ //filter data
|
|
|
+ props.data.features = this._filterData(props.leaflet.map.getZoom())
|
|
|
+ }
|
|
|
// Add some defaults
|
|
|
const thatStyler = props.styler.getFeatureStyle.bind(props.styler);
|
|
|
const myprops = Object.assign({}, {
|
|
@@ -65,7 +80,20 @@ class StyledLayer extends Path {
|
|
|
this._sortFeaturesZIndex(this.leafletElement);
|
|
|
}
|
|
|
|
|
|
+ componentWillUnmount(){
|
|
|
+ this.leafletElement.clearLayers();
|
|
|
+
|
|
|
+ PubSub.unsubscribe("map.zoom.changed")
|
|
|
+ }
|
|
|
+
|
|
|
updateLeafletElement(fromProps, toProps) {
|
|
|
+ if(window.CONFIG.map_zoom_control_marker){
|
|
|
+ //clone data
|
|
|
+ this.cahedFeatures = JSON.parse(JSON.stringify(toProps.data.features));
|
|
|
+
|
|
|
+ //filter data
|
|
|
+ toProps.data.features = this._filterData(toProps.leaflet.map.getZoom())
|
|
|
+ }
|
|
|
// Add style property according to styler
|
|
|
if(!toProps.style) {
|
|
|
toProps = Object.assign({}, toProps, { style: toProps.styler.getFeatureStyle.bind(toProps.styler) });
|
|
@@ -91,6 +119,67 @@ class StyledLayer extends Path {
|
|
|
this._sortFeaturesZIndex(this.leafletElement);
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * filter data by zoom
|
|
|
+ * @private
|
|
|
+ */
|
|
|
+ _filterData(zoom) {
|
|
|
+ //zoom>=20 show all markers
|
|
|
+ //zoom==19 show half markers
|
|
|
+ //zoom==18 hide all text markers
|
|
|
+ //zoom<=17 hide al markers
|
|
|
+
|
|
|
+ //clone data
|
|
|
+ let pp = JSON.parse(JSON.stringify(this.cahedFeatures));
|
|
|
+
|
|
|
+ if (zoom === 19) {
|
|
|
+ pp.map(f => {
|
|
|
+ let ft = f;
|
|
|
+ if(ft.properties.tags.show_type && ft.properties.tags.poi_no){
|
|
|
+ if(ft.properties.tags.poi_no % 2 !== 0){
|
|
|
+ ft.properties.tags.show_type = "none"
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(ft.id.startsWith("node/")){
|
|
|
+ if(ft.properties.tags.poi_no % 2 !== 0){
|
|
|
+ ft.geometry.coordinates[0] = 20000
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return ft;
|
|
|
+ });
|
|
|
+ } else if (zoom === 18) {
|
|
|
+ pp.map(f => {
|
|
|
+ let ft = f;
|
|
|
+ if(ft.properties.tags.show_type){
|
|
|
+ if(ft.properties.tags.poi_no % 4 !== 0){
|
|
|
+ ft.properties.tags.show_type = "none"
|
|
|
+ }
|
|
|
+ if(ft.properties.tags.show_type === "text"){
|
|
|
+ ft.properties.tags.show_type = "none"
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(ft.id.startsWith("node/")){
|
|
|
+ if(ft.properties.tags.poi_no % 4 !== 0){
|
|
|
+ ft.geometry.coordinates[0] = 20000
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return ft;
|
|
|
+ });
|
|
|
+ } else if (zoom <= 17) {
|
|
|
+ pp.map(f => {
|
|
|
+ let ft = f;
|
|
|
+ if(ft.properties.tags.show_type){
|
|
|
+ ft.properties.tags.show_type = "none"
|
|
|
+ }
|
|
|
+ if(ft.id.startsWith("node/")){
|
|
|
+ ft.geometry.coordinates[0] = 20000
|
|
|
+ }
|
|
|
+ return ft;
|
|
|
+ });
|
|
|
+ }
|
|
|
+ return pp
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* Sort features by size and type
|
|
|
* @private
|
|
@@ -121,7 +210,39 @@ class StyledLayer extends Path {
|
|
|
|
|
|
this._featureIcons = new LayerGroup();
|
|
|
|
|
|
- const featuresWithIcons = layer.getLayers().filter(l => l.options && l.options.iconImage && (!this.props.selection || l.feature.id !== this.props.selection.id));
|
|
|
+ const layers = layer.getLayers();
|
|
|
+
|
|
|
+ const featuresWithTexts = layers.filter(l => {
|
|
|
+ return l.feature
|
|
|
+ && l.feature.properties
|
|
|
+ && l.feature.properties.tags
|
|
|
+ && l.feature.properties.tags.show_type !== "none"
|
|
|
+ && (l.feature.properties.tags.name !== "" && l.feature.properties.tags.name !== "卫生间")
|
|
|
+ && l.feature.properties.tags.area_type !== "7"
|
|
|
+ && l.feature.geometry
|
|
|
+ && l.feature.geometry.type
|
|
|
+ && (l.feature.geometry.type === "MultiPolygon" || l.feature.geometry.type === "Polygon")
|
|
|
+ && (!this.props.selection || l.feature.id !== this.props.selection.id)
|
|
|
+ })
|
|
|
+ const textWidth = 500;
|
|
|
+ const textHeight = 20;
|
|
|
+ featuresWithTexts.forEach(l => {
|
|
|
+ const coords = l.getLatLng ? l.getLatLng() : (l.getBounds ? l.getBounds().getCenter() : null);
|
|
|
+
|
|
|
+ if(coords) {
|
|
|
+ let div = this._createNameMarkerByType(l.feature.properties.tags.name, l.feature.properties.tags.show_type);
|
|
|
+ let icon = new DivIcon({
|
|
|
+ iconSize: [textWidth, textHeight],
|
|
|
+ html: div,
|
|
|
+ className: "area_name_marker"
|
|
|
+ });
|
|
|
+
|
|
|
+ let marker = new Marker(coords, { icon: icon, interactive: false });
|
|
|
+ this._featureIcons.addLayer(marker);
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ const featuresWithIcons = layers.filter(l => l.options && l.options.iconImage && (!this.props.selection || l.feature.id !== this.props.selection.id));
|
|
|
const iconSize = 20;
|
|
|
|
|
|
featuresWithIcons.forEach(l => {
|
|
@@ -147,6 +268,107 @@ class StyledLayer extends Path {
|
|
|
layer.addLayer(this._featureIcons);
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Name marker create by type
|
|
|
+ * @private
|
|
|
+ */
|
|
|
+ _createNameMarkerByType(name, type)
|
|
|
+ {
|
|
|
+ let src;
|
|
|
+ switch (type) {
|
|
|
+ case "none":
|
|
|
+ return null;
|
|
|
+ case "text":
|
|
|
+ return this._createDivIcon(name);
|
|
|
+ case "icon_text":
|
|
|
+ src = window.EDITOR_URL + "img/icons/shop_music.png";
|
|
|
+ return this._createImageDivIcon(src, name, false);
|
|
|
+ case "icon_text_border":
|
|
|
+ src = window.EDITOR_URL + "img/icons/shop_music.png";
|
|
|
+ return this._createImageDivIcon(src, name);
|
|
|
+
|
|
|
+ default:
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Create divIcon elememnt
|
|
|
+ * @private
|
|
|
+ */
|
|
|
+ _createDivIcon(name)
|
|
|
+ {
|
|
|
+ let div = document.createElement('div');
|
|
|
+ div.style.backgroundColor = "rgba(0, 0, 0, 0)";
|
|
|
+ div.style.pointerEvents = "none";
|
|
|
+ div.style.verticalAlign = "middle";
|
|
|
+ div.style.textAlign = "center";
|
|
|
+ div.style.color = "rgb(135, 36, 6)";
|
|
|
+ div.style.textShadow = "1px 0px 0px #fff, -1px 0px 0px #fff, 0px 1px 0px #fff, 0px -1px 0px #fff";
|
|
|
+ div.innerText = name;
|
|
|
+
|
|
|
+ return div;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Create divIcon elememnt with img
|
|
|
+ * @private
|
|
|
+ */
|
|
|
+ _createImageDivIcon(src, name, bordered = true)
|
|
|
+ {
|
|
|
+ let divOut = document.createElement('div');
|
|
|
+ divOut.style.verticalAlign = "middle";
|
|
|
+ divOut.style.textAlign = "center";
|
|
|
+
|
|
|
+ let divMid = document.createElement('div');
|
|
|
+ divMid.style.width = "auto";
|
|
|
+ divMid.style.display = "inline-block";
|
|
|
+ divMid.style.verticalAlign = "middle";
|
|
|
+ divMid.style.textAlign = "left";
|
|
|
+ divMid.style.textIndent = "3px";
|
|
|
+ divMid.style.pointerEvents = "none";
|
|
|
+ divMid.style.paddingRight = "5px";
|
|
|
+ divMid.style.color = "rgb(135, 36, 6)";
|
|
|
+ divMid.style.textShadow = "1px 0px 0px #fff, -1px 0px 0px #fff, 0px 1px 0px #fff, 0px -1px 0px #fff";
|
|
|
+ // divMid.style.paddingBottom = "2px";
|
|
|
+ if(bordered){
|
|
|
+ divMid.style.backgroundColor = "beige";
|
|
|
+ divMid.style.border = "solid";
|
|
|
+ divMid.style.borderColor = "black";
|
|
|
+ divMid.style.borderWidth = "1px";
|
|
|
+ divMid.style.borderRadius = "8px";
|
|
|
+ }
|
|
|
+ divMid.innerText = name;
|
|
|
+
|
|
|
+ let divIn = document.createElement('div');
|
|
|
+ divIn.style.backgroundColor = "white";
|
|
|
+ divIn.style.height = "20px";
|
|
|
+ divIn.style.width = "20px";
|
|
|
+ divIn.style.verticalAlign = "middle";
|
|
|
+ divIn.style.textAlign = "left";
|
|
|
+ divIn.style.pointerEvents = "none";
|
|
|
+ divIn.style.marginLeft = "-5px";
|
|
|
+ divIn.style.marginTop = "-1px";
|
|
|
+ divIn.style.border = "solid";
|
|
|
+ divIn.style.borderColor = "black";
|
|
|
+ divIn.style.borderWidth = "1.5px";
|
|
|
+ divIn.style.borderRadius = "12px";
|
|
|
+ divIn.style.float = "left";
|
|
|
+
|
|
|
+ let img = document.createElement('img');
|
|
|
+ img.src = src;
|
|
|
+ img.style.pointerEvents = "none";
|
|
|
+ img.style.height = "16px";
|
|
|
+ img.style.width = "16px";
|
|
|
+ img.style.marginLeft = "-2px";
|
|
|
+ img.style.marginTop = "-2px";
|
|
|
+
|
|
|
+ divOut.append(divMid);
|
|
|
+ divMid.append(divIn);
|
|
|
+ divIn.append(img);
|
|
|
+ return divOut;
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* Load content into the leaflet layer
|
|
|
* @private
|