openlayers关于clusters介绍

效果展示

初始化地图

Javascript 复制代码
<template>
  <div id="map" class="map"></div>
</template>

<script>
import Map from "ol/Map.js";
import View from "ol/View.js";
import { centerPoint } from "@/utils/showPage.js";
import { gaodeMapLayer } from "@/utils/MapLayer.js";
import { clusters, clusterCircleStyle, clusterCircles } from "@/utils/cluster";
import { createEmpty, extend, getHeight, getWidth } from "ol/extent.js";
export default {
  name: "cluster",
  data() {
    return {
      map: null
    };
  },
  mounted() {
    const map = new Map({
      layers: [gaodeMapLayer, clusters, clusterCircles],
      target: "map",
      view: new View({
        center: centerPoint,
        zoom: 11,
        minZoom: 2,
        maxZoom: 30,
        projection: "EPSG:4326",
        rotation: 0,
      }),
    });
  },
};
</script>

<style scoped>
.map {
  width: 100%;
  height: 900px;
}
</style>

图层详解

  • 公共方法和样式

    Javascript 复制代码
     function gasPointType() {
       let customPoint = config.CUSTOM_POINT.val,
         GAS_POINT_TYPE = config.GAS_POINT_TYPE.children;
       GAS_POINT_TYPE.forEach((item) => {
         item.type = item.val.typeId.value;
       });
       return [
         ...GAS_POINT_TYPE,
         { type: customPoint.typeId.value, val: customPoint },
       ];
     }
     function getICon(properties) {
       let typeId = properties.typeId || "1",
         allPoint = gasPointType();
       return allPoint.find((i) => i.type == typeId).val;
     }
     function clusterMemberStyle(clusterMember) {
       let properties = clusterMember.getProperties();
       let item = getICon(properties);
       return new Style({
         geometry: clusterMember.getGeometry(),
         image: new Icon({
           rotation: 0,
           src: item.iconUrl.value,
           anchorXUnits: "fraction",
           imgSize: [item.width.value, item.height.value],
         }),
       });
     }
     function generatePointsCircle(count, clusterCenter, resolution) {
       const circumference =
         circleDistanceMultiplier * circleFootSeparation * (2 + count);
       let legLength = circumference / (Math.PI * 2); 
       const angleStep = (Math.PI * 2) / count;
       const res = [];
       let angle;
       legLength = Math.max(legLength, 35) * resolution;
       for (let i = 0; i < count; ++i) {
    
         angle = circleStartAngle + i * angleStep;
         res.push([
           clusterCenter[0] + legLength * Math.cos(angle),
           clusterCenter[1] + legLength * Math.sin(angle),
         ]);
       }
    
       return res;
     }
  • clusters图层

    Javascript 复制代码
      const vectorSource = new VectorSource({
        features: new GeoJSON().readFeatures({
          type: devList.type,
          features: _devList,
        }),
      });
    
      const clusterSource = new Cluster({
        distance: 35,
        source: vectorSource,
      });
      }
      function clusterStyle(feature) {
        const size = feature.get("features").length;
        if (size > 1) {
          return [
            new Style({
              image: outerCircle,
            }),
            new Style({
              image: innerCircle,
              text: new Text({
                text: size.toString(),
                fill: textFill,
                stroke: textStroke,
              }),
            }),
          ];
        }
        const originalFeature = feature.get("features")[0];
        return clusterMemberStyle(originalFeature);
      }
    
      const clusters = new VectorLayer({
        source: clusterSource,
        style: clusterStyle,
      });
  • clusterCircles图层

    Javascript 复制代码
       const clusterCircles = new VectorLayer({
         source: clusterSource,
         style: clusterCircleStyle,
       });
    
       function clusterCircleStyle(
         cluster,
         resolution,
         clickFeature,
         clickResolution
       ) {
         if (cluster !== clickFeature || resolution !== clickResolution) {
           return null;
         }
         const clusterMembers = cluster.get("features");
         const centerCoordinates = cluster.getGeometry().getCoordinates();
         return generatePointsCircle(
           clusterMembers.length,
           cluster.getGeometry().getCoordinates(),
           resolution
         ).reduce((styles, coordinates, i) => {
           const point = new Point(coordinates);
           const line = new LineString([centerCoordinates, coordinates]);
           styles.unshift(
             new Style({
               geometry: line,
               stroke: convexHullStroke,
             })
           );
           styles.push(
             clusterMemberStyle(
               new Feature({
                 ...clusterMembers[i].getProperties(),
                 geometry: point,
               })
             )
           );
           return styles;
         }, []);
       }

地图pointermove和click

Javascript 复制代码
  map.on("pointermove", (event) => {
      clusters.getFeatures(event.pixel).then((features) => {
        map.getTargetElement().style.cursor =
          features[0] && features[0].get("features").length > 1
            ? "pointer"
            : "";
      });
    });

    map.on("click", (event) => {
      clusters.getFeatures(event.pixel).then((features) => {
        if (features.length > 0) {
          const clusterMembers = features[0].get("features");
          if (clusterMembers.length > 1) {
            // Calculate the extent of the cluster members.
            const extent = createEmpty();
            clusterMembers.forEach((feature) =>
              extend(extent, feature.getGeometry().getExtent())
            );
            const view = map.getView();
            const resolution = map.getView().getResolution();
            if (
              view.getZoom() === view.getMaxZoom() ||
              (getWidth(extent) < resolution && getHeight(extent) < resolution)
            ) {
              // Show an expanded view of the cluster members.
              let clickFeature = features[0];
              let clickResolution = resolution;
              clusterCircles.setStyle((cluster, resolution) => {
                clusterCircleStyle(
                  cluster,
                  resolution,
                  clickFeature,
                  clickResolution
                );
              });
            } else {
              // Zoom to the extent of the cluster members.
              view.fit(extent, { duration: 500, padding: [50, 50, 50, 50] });
            }
          }
        }
      });
    });
相关推荐
Mintopia1 小时前
🧱 用三维点亮前端宇宙:构建你自己的 Three.js 组件库
前端·javascript·three.js
故事与九1 小时前
vue3使用vue-pdf-embed实现前端PDF在线预览
前端·vue.js·pdf
Mintopia2 小时前
🚀 顶点-面碰撞检测之诗:用牛顿法追寻命运的交点
前端·javascript·计算机图形学
wb1892 小时前
企业WEB应用服务器TOMCAT
运维·前端·笔记·tomcat·云计算
烛阴2 小时前
解锁 Gulp 的潜力:高级技巧与工作流优化
前端·javascript
Entropy-Lee3 小时前
JavaScript 语句和函数
开发语言·前端·javascript
Wcowin4 小时前
MkDocs文档日期插件【推荐】
前端·mkdocs
xw55 小时前
免费的个人网站托管-Cloudflare
服务器·前端
网安Ruler5 小时前
Web开发-PHP应用&Cookie脆弱&Session固定&Token唯一&身份验证&数据库通讯
前端·数据库·网络安全·php·渗透·红队
!win !5 小时前
免费的个人网站托管-Cloudflare
服务器·前端·开发工具