OpenLayers: 如何在不应该时阻止单击导致选择?

huangapple go评论40阅读模式
英文:

OpenLayers: How can I stop a click from causing a selection when it shouldn't be?

问题

以下是代码部分的中文翻译:

function createRectangle(polygons, layerName) {
  const features = [];

  for (const [i, polygon] of polygons.entries()) {
    const feature = {
      type: "Feature",
      geometry: {
        type: "Polygon",
        coordinates: polygon
      },
      properties: {
        id: `${layerName}${i} 个`,
        layerName
      }
    };

    features.push(feature);
  }

  const json = {
    type: "FeatureCollection",
    features
  };

  return json;
}

function createPoints(points, groupName) {
  const features = [];

  for (const [i, point] of points.entries()) {
    const feature = {
      type: "Feature",
      geometry: {
        type: "Point",
        coordinates: point
      },
      properties: {
        id: `${groupName}${i} 个`,
        groupName
      }
    };

    features.push(feature);
  }

  const json = {
    type: "FeatureCollection",
    features
  };

  return json;
}

const thePoints = createPoints(
  [
    [50, 33],
    [50, 33],
    [50, 33],
    [50, 33]
  ],
  "thePoints"
);

const styles = {
  Point: new ol.style.Style({
    image: new ol.style.Circle({
      radius: 7,
      fill: new ol.style.Fill({ color: "red" })
    }),
    stroke: new ol.style.Stroke({
      color: "hsla(0, 50%, 100%, 1.0)",
      width: 5
    }),
    fill: new ol.style.Fill({
      color: "hsla(0, 50%, 50%, 1.0)"
    })
  }),
  Polygon: new ol.style.Style({
    stroke: new ol.style.Stroke({
      color: "hsla(0, 50%, 100%, 1.0)",
      width: 5
    }),
    fill: new ol.style.Fill({
      color: "hsla(0, 50%, 50%, 1.0)"
    })
  })
};

const styleFunction = function (feature) {
  const featureType = feature.getGeometry().getType();
  return styles[featureType];
};

const vectorSource = new ol.source.Vector({
  features: new ol.format.GeoJSON({
    featureProjection: "EPSG:4326"
  }).readFeatures(thePoints)
});

const cluster = new ol.source.Cluster({
  distance: 30,
  minDistance: 10,
  source: vectorSource
});

const styleCache = {};
const vectorLayer = new ol.layer.Vector({
  source: cluster,
  style: function (feature) {
    const size = feature.get("features").length;
    let style = styleCache[size];
    if (!style) {
      style = new ol.style.Style({
        image: new ol.style.Circle({
          radius: 10,
          stroke: new ol.style.Stroke({
            color: "#fff"
          }),
          fill: new ol.style.Fill({
            color: "#3399CC"
          })
        }),
        text: new ol.style.Text({
          text: size.toString(),
          fill: new ol.style.Fill({
            color: "#fff"
          })
        })
      });
      styleCache[size] = style;
    }
    return style;
  },
  zIndex: 5,
  properties: {
    name: "big"
  }
});

const rectangles = createRectangle(
  [
    [
      [
        [-120, -75],
        [-120, 75],
        [45, 75],
        [45, -75]
      ]
    ]
  ],
  "rectangle"
);

const rectangleSource = new ol.source.Vector({
  features: new ol.format.GeoJSON({
    featureProjection: "EPSG:4326"
  }).readFeatures(rectangles)
});

const rectangleLayer = new ol.layer.Vector({
  source: rectangleSource,
  style: styleFunction,
  zIndex: 5
});

const map = new ol.Map({
  target: "map",
  layers: [
    new ol.layer.Tile({
      source: new ol.source.OSM()
    }),
    vectorLayer,
    rectangleLayer
  ],
  view: new ol.View({
    projection: "EPSG:4326",
    center: [179, 0],
    zoom: 1
  })
});

map.on("click", (e) => {
  vectorLayer.getFeatures(e.pixel).then((clickedFeatures) => {
    if (clickedFeatures.length) {
      // 获取聚类坐标
      const features = clickedFeatures[0].get("features");
      if (features.length > 1) {
        e.stopPropagation();

        const extent = ol.extent.boundingExtent(
          features.map((r) => r.getGeometry().getCoordinates())
        );
        const extentSize = ol.extent.getSize(extent);
        const isSmallExtent = extentSize[0] === 0 && extentSize[1] === 0;

        console.log("isSmallExtent", isSmallExtent);

        if (isSmallExtent) {
          const viewport = map.getViewport();
          const boundingRect = viewport.getBoundingClientRect();

          console.log("boundingRect", boundingRect);

          const centerPoint = [
            (boundingRect.left + boundingRect.right) / 2,
            (boundingRect.top + boundingRect.bottom) / 2
          ];

          console.log("centerPoint", centerPoint);

          map
            .getView()
            .centerOn(ol.extent.getCenter(extent), map.getSize(), centerPoint);
        } else {
          map
            .getView()
            .fit(extent, { duration: 1000, padding: [50, 50, 50, 50] });
        }
      }
    }
  });
});

const selected = new ol.style.Style({
  fill: new ol.style.Fill({
    color: "hsla(270, 50%, 50%, .1)"
  }),
  stroke: new ol.style.Stroke({
    color: "hsla(270, 50%, 50%, 1)",
    width: 5
  })
});

const selectSingleClick = new ol.interaction.Select({
  style: (feature) => {
    const color = "hsla(270, 50%, 50%, .1)";
    selected.getFill().setColor(color);
    return selected;
  },
  layers: [rectangleLayer],
  condition: function (e) {
    return (
      ol.events.condition.singleClick(e) &&
      map.getFeaturesAtPixel(e.pixel, {
        layerFilter: function (l) {
          return l.getZIndex() > vectorLayer.getZIndex();
        }
      }).length === 0
    );
  }
});

selectSingleClick.on("select", function (e) {
  console.log("selectSingleClick onSelect");
});

map.addInteraction(selectSingleClick);
#map {
  height: 512px;
  width: 1024px;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/openlayers/7.3.0/ol.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/openlayers/7.3.

<details>
<summary>英文:</summary>

To reproduce, click on the blue marker containing the text `4`. Because this is a cluster marker and all of the markers it is clustering are at the same coordinate, it does not make sense to try to zoom in. Instead of zooming in, I center the map on the marker.

However, this click on the 4 marker, is causing a click on the big rectangle to the left, which results in a Select being triggered for the rectangle. This, of course, should not happen.

I have tried telling the event to not propagate if I am doing the centering operation, but that is not helping.

What do I need to change so the Select is not triggered?


&lt;!-- begin snippet: js hide: false console: true babel: false --&gt;

&lt;!-- language: lang-js --&gt;

    function createRectangle(polygons, layerName) {
      const features = [];

      for (const [i, polygon] of polygons.entries()) {
        const feature = {
          type: &quot;Feature&quot;,
          geometry: {
            type: &quot;Polygon&quot;,
            coordinates: polygon
          },
          properties: {
            id: `${layerName} index ${i}`,
            layerName
          }
        };

        features.push(feature);
      }

      const json = {
        type: &quot;FeatureCollection&quot;,
        features
      };

      return json;
    }

    function createPoints(points, groupName) {
      const features = [];

      for (const [i, point] of points.entries()) {
        const feature = {
          type: &quot;Feature&quot;,
          geometry: {
            type: &quot;Point&quot;,
            coordinates: point
          },
          properties: {
            id: `${groupName} index ${i}`,
            groupName
          }
        };

        features.push(feature);
      }

      const json = {
        type: &quot;FeatureCollection&quot;,
        features
      };

      return json;
    }

    const thePoints = createPoints(
      [
        [50, 33],
        [50, 33],
        [50, 33],
        [50, 33]
      ],
      &quot;thePoints&quot;
    );

    const styles = {
      Point: new ol.style.Style({
        image: new ol.style.Circle({
          radius: 7,
          fill: new ol.style.Fill({ color: &quot;red&quot; })
        }),
        stroke: new ol.style.Stroke({
          color: &quot;hsla(0, 50%, 100%, 1.0)&quot;,
          width: 5
        }),
        fill: new ol.style.Fill({
          color: &quot;hsla(0, 50%, 50%, 1.0)&quot;
        })
      }),
      Polygon: new ol.style.Style({
        stroke: new ol.style.Stroke({
          color: &quot;hsla(0, 50%, 100%, 1.0)&quot;,
          width: 5
        }),
        fill: new ol.style.Fill({
          color: &quot;hsla(0, 50%, 50%, 1.0)&quot;
        })
      })
    };

    const styleFunction = function (feature) {
      const featureType = feature.getGeometry().getType();
      return styles[featureType];
    };

    const vectorSource = new ol.source.Vector({
      features: new ol.format.GeoJSON({
        featureProjection: &quot;EPSG:4326&quot; // 4326 3857
      }).readFeatures(thePoints)
    });

    const cluster = new ol.source.Cluster({
      distance: 30,
      minDistance: 10,
      source: vectorSource
    });

    const styleCache = {};
    const vectorLayer = new ol.layer.Vector({
      source: cluster,
      style: function (feature) {
        const size = feature.get(&quot;features&quot;).length;
        let style = styleCache[size];
        if (!style) {
          style = new ol.style.Style({
            image: new ol.style.Circle({
              radius: 10,
              stroke: new ol.style.Stroke({
                color: &quot;#fff&quot;
              }),
              fill: new ol.style.Fill({
                color: &quot;#3399CC&quot;
              })
            }),
            text: new ol.style.Text({
              text: size.toString(),
              fill: new ol.style.Fill({
                color: &quot;#fff&quot;
              })
            })
          });
          styleCache[size] = style;
        }
        return style;
      },
      zIndex: 5,
      properties: {
        name: &quot;big&quot;
      }
    });

    const rectangles = createRectangle(
      [
        [
          [
            [-120, -75],
            [-120, 75],
            [45, 75],
            [45, -75]
          ]
        ]
      ],
      &quot;rectangle&quot;
    );

    const rectangleSource = new ol.source.Vector({
      features: new ol.format.GeoJSON({
        featureProjection: &quot;EPSG:4326&quot; // 4326 3857
      }).readFeatures(rectangles)
    });

    const rectangleLayer = new ol.layer.Vector({
      source: rectangleSource,
      style: styleFunction,
      zIndex: 5
    });

    const map = new ol.Map({
      target: &quot;map&quot;,
      layers: [
        new ol.layer.Tile({
          source: new ol.source.OSM()
        }),
        vectorLayer,
        rectangleLayer
      ],
      view: new ol.View({
        projection: &quot;EPSG:4326&quot;,
        center: [179, 0],
        zoom: 1
      })
    });

    map.on(&quot;click&quot;, (e) =&gt; {
      vectorLayer.getFeatures(e.pixel).then((clickedFeatures) =&gt; {
        if (clickedFeatures.length) {
          // Get clustered Coordinates
          const features = clickedFeatures[0].get(&quot;features&quot;);
          if (features.length &gt; 1) {
            e.stopPropagation();

            const extent = ol.extent.boundingExtent(
              features.map((r) =&gt; r.getGeometry().getCoordinates())
            );
            const extentSize = ol.extent.getSize(extent);
            const isSmallExtent = extentSize[0] === 0 &amp;&amp; extentSize[1] === 0;

            console.log(&quot;isSmallExtent&quot;, isSmallExtent);

            if (isSmallExtent) {
              const viewport = map.getViewport();
              const boundingRect = viewport.getBoundingClientRect();

              console.log(&quot;boundingRect&quot;, boundingRect);

              const centerPoint = [
                (boundingRect.left + boundingRect.right) / 2,
                (boundingRect.top + boundingRect.bottom) / 2
              ];

              console.log(&quot;centerPoint&quot;, centerPoint);

              map
                .getView()
                .centerOn(ol.extent.getCenter(extent), map.getSize(), centerPoint);
            } else {
              map
                .getView()
                .fit(extent, { duration: 1000, padding: [50, 50, 50, 50] });
            }
          }
        }
      });
    });

    const selected = new ol.style.Style({
      fill: new ol.style.Fill({
        color: &quot;hsla(270, 50%, 50%, .1)&quot;
      }),
      stroke: new ol.style.Stroke({
        color: &quot;hsla(270, 50%, 50%, 1)&quot;,
        width: 5
      })
    });

    const selectSingleClick = new ol.interaction.Select({
      style: (feature) =&gt; {
        const color = &quot;hsla(270, 50%, 50%, .1)&quot;;
        selected.getFill().setColor(color);
        return selected;
      },
      layers: [rectangleLayer],
      condition: function (e) {
        return (
          ol.events.condition.singleClick(e) &amp;&amp;
          map.getFeaturesAtPixel(e.pixel, {
            layerFilter: function (l) {
              return l.getZIndex() &gt; vectorLayer.getZIndex();
            }
          }).length === 0
        );
      }
    });

    selectSingleClick.on(&quot;select&quot;, function (e) {
      console.log(&quot;selectSingleClick onSelect&quot;);
    });

    map.addInteraction(selectSingleClick);


&lt;!-- language: lang-css --&gt;

    #map {
      height: 512px;
      width: 1024px;
    }


&lt;!-- language: lang-html --&gt;

    &lt;link href=&quot;https://cdnjs.cloudflare.com/ajax/libs/openlayers/7.3.0/ol.min.css&quot; rel=&quot;stylesheet&quot; /&gt;
    &lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/openlayers/7.3.0/dist/ol.min.js&quot;&gt;&lt;/script&gt;

    &lt;div id=&quot;map&quot;&gt;&lt;/div&gt;

&lt;!-- end snippet --&gt;



</details>


# 答案1
**得分**: 0

以下是代码部分的翻译:

```javascript
You could simply deactivate the select interaction for the duration of a single click (which fires 500ms after the click to ensure it is not a double click)

selectSingleClick.setActive(false);
setTimeout(() => { selectSingleClick.setActive(true); }, 600);
The use of `setTimeout` could be avoided by using a `clickHandled` boolean set only when a map `click` causes some action, and its value being tested in the select condition:

let clickHandled = false;
map.on("click", (e) => {
  vectorLayer.getFeatures(e.pixel).then((clickedFeatures) => {
    clickHandled = false;
    if (clickedFeatures.length) {
      // Get clustered Coordinates
      const features = clickedFeatures[0].get("features");
      clickHandled = true;

      const extent = ol.extent.boundingExtent(
        features.map((r) => r.getGeometry().getCoordinates())
      );
      const extentSize = ol.extent.getSize(extent);
      const isSmallExtent = extentSize[0] === 0 && extentSize[1] === 0;

      console.log("isSmallExtent", isSmallExtent);

      if (isSmallExtent) {
        const viewport = map.getViewport();
        const boundingRect = viewport.getBoundingClientRect();

        console.log("boundingRect", boundingRect);

        const centerPoint = [
          (boundingRect.left + boundingRect.right) / 2,
          (boundingRect.top + boundingRect.bottom) / 2
        ];

        console.log("centerPoint", centerPoint);

        map
          .getView()
          .centerOn(ol.extent.getCenter(extent), map.getSize(), centerPoint);
      } else {
        map
          .getView()
          .fit(extent, { duration: 1000, padding: [50, 50, 50, 50] });
      }
    }
  });
});

这是你要求的翻译,没有其他内容。

英文:

You could simply deactivate the select interaction for the duration of a single click (which fires 500ms after the click to ensure it is not a double click)

    selectSingleClick.setActive(false);
setTimeout(() =&gt; { selectSingleClick.setActive(true); }, 600);

<!-- begin snippet: js hide: false console: true babel: null -->

<!-- language: lang-js -->

function createRectangle(polygons, layerName) {
const features = [];
for (const [i, polygon] of polygons.entries()) {
const feature = {
type: &quot;Feature&quot;,
geometry: {
type: &quot;Polygon&quot;,
coordinates: polygon
},
properties: {
id: `${layerName} index ${i}`,
layerName
}
};
features.push(feature);
}
const json = {
type: &quot;FeatureCollection&quot;,
features
};
return json;
}
function createPoints(points, groupName) {
const features = [];
for (const [i, point] of points.entries()) {
const feature = {
type: &quot;Feature&quot;,
geometry: {
type: &quot;Point&quot;,
coordinates: point
},
properties: {
id: `${groupName} index ${i}`,
groupName
}
};
features.push(feature);
}
const json = {
type: &quot;FeatureCollection&quot;,
features
};
return json;
}
const thePoints = createPoints(
[
[50, 33],
[50, 33],
[50, 33],
[50, 33]
],
&quot;thePoints&quot;
);
const styles = {
Point: new ol.style.Style({
image: new ol.style.Circle({
radius: 7,
fill: new ol.style.Fill({ color: &quot;red&quot; })
}),
stroke: new ol.style.Stroke({
color: &quot;hsla(0, 50%, 100%, 1.0)&quot;,
width: 5
}),
fill: new ol.style.Fill({
color: &quot;hsla(0, 50%, 50%, 1.0)&quot;
})
}),
Polygon: new ol.style.Style({
stroke: new ol.style.Stroke({
color: &quot;hsla(0, 50%, 100%, 1.0)&quot;,
width: 5
}),
fill: new ol.style.Fill({
color: &quot;hsla(0, 50%, 50%, 1.0)&quot;
})
})
};
const styleFunction = function (feature) {
const featureType = feature.getGeometry().getType();
return styles[featureType];
};
const vectorSource = new ol.source.Vector({
features: new ol.format.GeoJSON({
featureProjection: &quot;EPSG:4326&quot; // 4326 3857
}).readFeatures(thePoints)
});
const cluster = new ol.source.Cluster({
distance: 30,
minDistance: 10,
source: vectorSource
});
const styleCache = {};
const vectorLayer = new ol.layer.Vector({
source: cluster,
style: function (feature) {
const size = feature.get(&quot;features&quot;).length;
let style = styleCache[size];
if (!style) {
style = new ol.style.Style({
image: new ol.style.Circle({
radius: 10,
stroke: new ol.style.Stroke({
color: &quot;#fff&quot;
}),
fill: new ol.style.Fill({
color: &quot;#3399CC&quot;
})
}),
text: new ol.style.Text({
text: size.toString(),
fill: new ol.style.Fill({
color: &quot;#fff&quot;
})
})
});
styleCache[size] = style;
}
return style;
},
zIndex: 5,
properties: {
name: &quot;big&quot;
}
});
const rectangles = createRectangle(
[
[
[
[-120, -75],
[-120, 75],
[45, 75],
[45, -75]
]
]
],
&quot;rectangle&quot;
);
const rectangleSource = new ol.source.Vector({
features: new ol.format.GeoJSON({
featureProjection: &quot;EPSG:4326&quot; // 4326 3857
}).readFeatures(rectangles)
});
const rectangleLayer = new ol.layer.Vector({
source: rectangleSource,
style: styleFunction,
zIndex: 5
});
const map = new ol.Map({
target: &quot;map&quot;,
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
}),
vectorLayer,
rectangleLayer
],
view: new ol.View({
projection: &quot;EPSG:4326&quot;,
center: [179, 0],
zoom: 1
})
});
let selectSingleClick;
map.on(&quot;click&quot;, (e) =&gt; {
vectorLayer.getFeatures(e.pixel).then((clickedFeatures) =&gt; {
if (clickedFeatures.length) {
// Get clustered Coordinates
const features = clickedFeatures[0].get(&quot;features&quot;);
if (features.length &gt; 1) {
selectSingleClick.setActive(false);
setTimeout(() =&gt; { selectSingleClick.setActive(true); }, 600);
const extent = ol.extent.boundingExtent(
features.map((r) =&gt; r.getGeometry().getCoordinates())
);
const extentSize = ol.extent.getSize(extent);
const isSmallExtent = extentSize[0] === 0 &amp;&amp; extentSize[1] === 0;
console.log(&quot;isSmallExtent&quot;, isSmallExtent);
if (isSmallExtent) {
const viewport = map.getViewport();
const boundingRect = viewport.getBoundingClientRect();
console.log(&quot;boundingRect&quot;, boundingRect);
const centerPoint = [
(boundingRect.left + boundingRect.right) / 2,
(boundingRect.top + boundingRect.bottom) / 2
];
console.log(&quot;centerPoint&quot;, centerPoint);
map
.getView()
.centerOn(ol.extent.getCenter(extent), map.getSize(), centerPoint);
} else {
map
.getView()
.fit(extent, { duration: 1000, padding: [50, 50, 50, 50] });
}
}
}
});
});
const selected = new ol.style.Style({
fill: new ol.style.Fill({
color: &quot;hsla(270, 50%, 50%, .1)&quot;
}),
stroke: new ol.style.Stroke({
color: &quot;hsla(270, 50%, 50%, 1)&quot;,
width: 5
})
});
selectSingleClick = new ol.interaction.Select({
style: (feature) =&gt; {
const color = &quot;hsla(270, 50%, 50%, .1)&quot;;
selected.getFill().setColor(color);
return selected;
},
layers: [rectangleLayer],
condition: function (e) {
return (
ol.events.condition.singleClick(e) &amp;&amp;
map.getFeaturesAtPixel(e.pixel, {
layerFilter: function (l) {
return l.getZIndex() &gt; vectorLayer.getZIndex();
}
}).length === 0
);
}
});
selectSingleClick.on(&quot;select&quot;, function (e) {
console.log(&quot;selectSingleClick onSelect&quot;);
});
map.addInteraction(selectSingleClick);

<!-- language: lang-css -->

#map {
height: 512px;
width: 1024px;
}

<!-- language: lang-html -->

&lt;link href=&quot;https://cdnjs.cloudflare.com/ajax/libs/openlayers/7.3.0/ol.min.css&quot; rel=&quot;stylesheet&quot; /&gt;
&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/openlayers/7.3.0/dist/ol.min.js&quot;&gt;&lt;/script&gt;
&lt;div id=&quot;map&quot;&gt;&lt;/div&gt;

<!-- end snippet -->

The use of setTimeout could be avoided by using a clickHandled boolean set only when a map click causes some action, and its value being tested in the select condition:

<!-- begin snippet: js hide: true console: true babel: false -->

<!-- language: lang-js -->

function createRectangle(polygons, layerName) {
const features = [];
for (const [i, polygon] of polygons.entries()) {
const feature = {
type: &quot;Feature&quot;,
geometry: {
type: &quot;Polygon&quot;,
coordinates: polygon
},
properties: {
id: `${layerName} index ${i}`,
layerName
}
};
features.push(feature);
}
const json = {
type: &quot;FeatureCollection&quot;,
features
};
return json;
}
function createPoints(points, groupName) {
const features = [];
for (const [i, point] of points.entries()) {
const feature = {
type: &quot;Feature&quot;,
geometry: {
type: &quot;Point&quot;,
coordinates: point
},
properties: {
id: `${groupName} index ${i}`,
groupName
}
};
features.push(feature);
}
const json = {
type: &quot;FeatureCollection&quot;,
features
};
return json;
}
const thePoints = createPoints(
[
[50, 33],
[50, 33],
[50, 33],
[50, 33]
],
&quot;thePoints&quot;
);
const styles = {
Point: new ol.style.Style({
image: new ol.style.Circle({
radius: 7,
fill: new ol.style.Fill({ color: &quot;red&quot; })
}),
stroke: new ol.style.Stroke({
color: &quot;hsla(0, 50%, 100%, 1.0)&quot;,
width: 5
}),
fill: new ol.style.Fill({
color: &quot;hsla(0, 50%, 50%, 1.0)&quot;
})
}),
Polygon: new ol.style.Style({
stroke: new ol.style.Stroke({
color: &quot;hsla(0, 50%, 100%, 1.0)&quot;,
width: 5
}),
fill: new ol.style.Fill({
color: &quot;hsla(0, 50%, 50%, 1.0)&quot;
})
})
};
const styleFunction = function (feature) {
const featureType = feature.getGeometry().getType();
return styles[featureType];
};
const vectorSource = new ol.source.Vector({
features: new ol.format.GeoJSON({
featureProjection: &quot;EPSG:4326&quot; // 4326 3857
}).readFeatures(thePoints)
});
const cluster = new ol.source.Cluster({
distance: 30,
minDistance: 10,
source: vectorSource
});
const styleCache = {};
const vectorLayer = new ol.layer.Vector({
source: cluster,
style: function (feature) {
const size = feature.get(&quot;features&quot;).length;
let style = styleCache[size];
if (!style) {
style = new ol.style.Style({
image: new ol.style.Circle({
radius: 10,
stroke: new ol.style.Stroke({
color: &quot;#fff&quot;
}),
fill: new ol.style.Fill({
color: &quot;#3399CC&quot;
})
}),
text: new ol.style.Text({
text: size.toString(),
fill: new ol.style.Fill({
color: &quot;#fff&quot;
})
})
});
styleCache[size] = style;
}
return style;
},
zIndex: 5,
properties: {
name: &quot;big&quot;
}
});
const rectangles = createRectangle(
[
[
[
[-120, -75],
[-120, 75],
[45, 75],
[45, -75]
]
]
],
&quot;rectangle&quot;
);
const rectangleSource = new ol.source.Vector({
features: new ol.format.GeoJSON({
featureProjection: &quot;EPSG:4326&quot; // 4326 3857
}).readFeatures(rectangles)
});
const rectangleLayer = new ol.layer.Vector({
source: rectangleSource,
style: styleFunction,
zIndex: 5
});
const map = new ol.Map({
target: &quot;map&quot;,
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
}),
vectorLayer,
rectangleLayer
],
view: new ol.View({
projection: &quot;EPSG:4326&quot;,
center: [179, 0],
zoom: 1
})
});
let clickHandled = false;
map.on(&quot;click&quot;, (e) =&gt; {
vectorLayer.getFeatures(e.pixel).then((clickedFeatures) =&gt; {
clickHandled = false;
if (clickedFeatures.length) {
// Get clustered Coordinates
const features = clickedFeatures[0].get(&quot;features&quot;);
if (features.length &gt; 1) {
clickHandled = true;
const extent = ol.extent.boundingExtent(
features.map((r) =&gt; r.getGeometry().getCoordinates())
);
const extentSize = ol.extent.getSize(extent);
const isSmallExtent = extentSize[0] === 0 &amp;&amp; extentSize[1] === 0;
console.log(&quot;isSmallExtent&quot;, isSmallExtent);
if (isSmallExtent) {
const viewport = map.getViewport();
const boundingRect = viewport.getBoundingClientRect();
console.log(&quot;boundingRect&quot;, boundingRect);
const centerPoint = [
(boundingRect.left + boundingRect.right) / 2,
(boundingRect.top + boundingRect.bottom) / 2
];
console.log(&quot;centerPoint&quot;, centerPoint);
map
.getView()
.centerOn(ol.extent.getCenter(extent), map.getSize(), centerPoint);
} else {
map
.getView()
.fit(extent, { duration: 1000, padding: [50, 50, 50, 50] });
}
}
}
});
});
const selected = new ol.style.Style({
fill: new ol.style.Fill({
color: &quot;hsla(270, 50%, 50%, .1)&quot;
}),
stroke: new ol.style.Stroke({
color: &quot;hsla(270, 50%, 50%, 1)&quot;,
width: 5
})
});
selectSingleClick = new ol.interaction.Select({
style: (feature) =&gt; {
const color = &quot;hsla(270, 50%, 50%, .1)&quot;;
selected.getFill().setColor(color);
return selected;
},
layers: [rectangleLayer],
condition: function (e) {
return (
!clickHandled &amp;&amp;
ol.events.condition.singleClick(e) &amp;&amp;
map.getFeaturesAtPixel(e.pixel, {
layerFilter: function (l) {
return l.getZIndex() &gt; vectorLayer.getZIndex();
}
}).length === 0
);
}
});
selectSingleClick.on(&quot;select&quot;, function (e) {
console.log(&quot;selectSingleClick onSelect&quot;);
});
map.addInteraction(selectSingleClick);

<!-- language: lang-css -->

#map {
height: 512px;
width: 1024px;
}

<!-- language: lang-html -->

&lt;link href=&quot;https://cdnjs.cloudflare.com/ajax/libs/openlayers/7.3.0/ol.min.css&quot; rel=&quot;stylesheet&quot; /&gt;
&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/openlayers/7.3.0/dist/ol.min.js&quot;&gt;&lt;/script&gt;
&lt;div id=&quot;map&quot;&gt;&lt;/div&gt;

<!-- end snippet -->

huangapple
  • 本文由 发表于 2023年4月7日 05:38:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/75953968.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定