【openlayer】 聚合


以下代码与业务场景关联较深,实现方案可参考

http://t.csdn.cn/4SPGr

直接上代码

<template>
    <div id="map" ref="map"></div>
</template>

<script>
// mapRef   :自己封装的  全局 map 通用方法,代码在文末
import * as mapRef from './mapUtils'


// 设置当前组件地图小组件  样式参数   结合 formatDatas
let entityImg = {
    "heatmap": {
        noSelect: require("@/assets/images/analysis/map-company.png"),
        selected: require("@/assets/images/analysis/map-company-selected.png"),
    },
}
let textFill = {
    noSelect: {
        fill: "rgba(255,255,255,0)",
        bgFill: "rgba(255,255,255,0)",
        strokeFill: "rgba(255,255,255,0)",
    },
    selected: {
        fill: "#FFF18D",
        bgFill: "#665C13",
        strokeFill: "#FFF18D",
    }
}

export default {
    data() {
        return {
            areaMap: null,
            hotLayer: null,
            mainLayer: null,
            datas: [
                {
                    id: '',
                    name: '',
                    code: '',
                    Longitude: '',
                    Latitude: '',
                    img: '',
                }
            ],
            metaList: []
        }
    },
    methods: {
        initMap() {
            let _this = this;
            let _Url = 'YOU MAP SERVER URL'  //  地图服务地址
            this.areaMap = new ol.Map({
                target: _this.$refs.map,
                view: new ol.View({
                    center: [Longitude, Latitude],               //地图中心点
                    projection: 'EPSG:4326',                    //  坐标系
                    maxExtent: [106.43, 29.13, 107.0, 29.77],   //限制可视区域
                    zoom: 11,                                   // 缩放等级
                    minZoom: 8,
                    maxZoom: 15,
                }),
                controls: ol.control.defaults().extend([
                ]),
            })

            // 添加聚合图层
            this.cluster()


        },

        // 对数据追加数据   结合mapRef  。createMakerFeature 使用
        formatDatas(info) {
            info["position"] = [info?.Longitude, info?.Latitude];
            info["entity"] = {
                img: entityImg[info.code][info.selectStatus]
            };
            info["text"] = {
                name: info?.name,
                ...textFill[info.selectStatus]
            }
        },
        cluster() {

            if (data && data?.length > 0) {
                this.metaList = data ?? []
                var source = new ol.source.Vector();
                this.metaList.forEach(item => {
                    item.id = item.id;
                    item.name = item?.name;
                    item.code = 'heatmap';
                    item.selectStatus = "noSelect";
                    item.selectStatus = "noSelect";
                    this.formatDatas(item);
                    //添加点
                    if (item.Longitude && item.Latitude) {
                        source.addFeature(mapRef.createMakerFeature(item))
                    }
                })

                this.cluster = new ol.source.Cluster({
                    source: source,
                    distance: 100
                })
                this.mainLayer = new ol.layer.Vector({
                    source: this.cluster,
                    style: function (feature, resolution) {
                        let size = feature.get('features').length;
                        let zoom = (_this.areaMap.getView().getZoom()) / 10 * 0.5
                        if (zoom < 0.55) {
                            zoom = 0.55
                        }
                        if (size == 1) {
                            return new ol.style.Style({
                                image: new ol.style.Icon({
                                    scale: zoom,
                                    anchor: [0.5, 0.5],
                                    src: require("@/assets/images/analysis/map-company.png")
                                })
                            })
                        }
                        else {
                            // 根据场景计算 缩放等级,以及图标的缩放等级
                            let radius = (size + 40) > 80 ? 80 : (size + 40)
                            let scale = (((size + 40) > 80 ? 80 : (size + 40) / 100 > 1 ? 0.65 : (size + 40) / 100) < 0.3 ? 0.3 : (size + 40) / 100)
                            return new ol.style.Style({
                                cursor: 'pointer',
                                image: new ol.style.Icon({
                                    scale: '1',
                                    src: require("@/assets/images/analysis/map-jh.png")
                                }),
                                text: new ol.style.Text({
                                    textAlign: 'center', //对齐方式
                                    textBaseline: 'middle', //文本基线
                                    offsetY: -14, // Y轴偏置
                                    font: (radius / 2) + 'px PangMenZhengDao',
                                    text: size.toString(),
                                    fill: new ol.style.Fill({
                                        color: 'white'
                                    })
                                })
                            })
                        }
                    }
                });


                // 添加缩放监听事件
                var select_move = new ol.interaction.Select({
                    condition: ol.events.condition.pointerMove,//设置监听事件

                    style: function (feature, resolution) {
                        let size = feature.get('features').length;
                        let zoom = (_this.areaMap.getView().getZoom()) / 10 * 0.7
                        if (zoom < 0.55) {
                            zoom = 0.55
                        }
                        if (size == 1) {
                            let ids = feature.get('features')[0].get("id")
                            let target = _this.metaList.find(item => item.id == ids);

                            return new ol.style.Style({
                                text: new ol.style.Text({
                                    text: target.name,
                                    textAlign: 'center', //对齐方式
                                    textBaseline: 'middle', //文本基线
                                    font: 'normal 16px 微软雅黑', //字体样式
                                    offsetY: -50, // Y轴偏置
                                    // offsetX : 30,
                                    fill: new ol.style.Fill({
                                        //填充样式
                                        color: '#FFFFFF',
                                    }),
                                    backgroundFill: new ol.style.Fill({
                                        // 填充背景
                                        color: 'rgba(97,126,155,0.88)',
                                    }),
                                    backgroundStroke: new ol.style.Stroke({
                                        color: '#617E9B',
                                        width: 2,
                                    }),
                                    padding: [6, 10, 3, 10],
                                }),
                                image: new ol.style.Icon({
                                    scale: zoom,
                                    anchor: [0.5, 0.5],
                                    src: require("@/assets/images/analysis/map-company-selected.png")
                                })
                            })
                        } else {
                            _this.areaMap.getTargetElement().style.cursor = 'pointer'
                            let radius = (size + 40) > 80 ? 80 : (size + 40)
                            let scale = (((size + 40) > 80 ? 80 : (size + 40) / 100 > 1 ? 0.65 : (size + 40) / 100) < 0.3 ? 0.3 : (size + 40) / 100)
                            return new ol.style.Style({
                                cursor: 'pointer',
                                image: new ol.style.Icon({
                                    scale: scale,
                                    src: require("@/assets/images/analysis/map-jh-selected.png")
                                }),
                                text: new ol.style.Text({
                                    font: (radius / 2) + 'px PangMenZhengDao',
                                    text: size.toString(),
                                    textAlign: 'center', //对齐方式
                                    textBaseline: 'middle', //文本基线
                                    offsetY: -14, // Y轴偏置
                                    fill: new ol.style.Fill({
                                        color: 'white'
                                    })
                                })
                            })
                        }
                    },

                });
                _this.areaMap.addInteraction(select_move)

                _this.areaMap.addLayer(_this.mainLayer);
            }
        }
    },
}
</script>

mapRef.js

部分代码如下:
export function createMakerFeature (info,feature) {
  let {id, position, circle, entity, arrow, text, cover, progress} = info;
  position = position.map(item => parseFloat(item));
  if(!feature){
    feature = new ol.Feature({
      id,
      geometry : new ol.geom.Point(position),
    })
  }
  let styles = [];
  if (circle?.img) {
    styles.push(
      new ol.style.Style({
        image: new ol.style.Icon({
          anchor: [0.5,0.5],      //设置图标偏移
          scale: 1,      // 图标缩小显示
          opacity: 1,    //透明度
          src: circle.img,     //图片路径
        })
      })
    )
  }
  if (entity?.img) {
    styles.push(
      new ol.style.Style({
        image: new ol.style.Icon({
          // color: 'red',
          anchor: entity.anchor || [0.5, 0.7],      //设置图标偏移
          scale: 1,      // 图标缩小显示
          opacity: 1,    //透明度
          src: entity.img,     //图片路径
        })
      })
    )
  }
  if (arrow?.img) {
    styles.push(
      new ol.style.Style({
        image: new ol.style.Icon({
          anchor: [0.5,2.4],      //设置图标偏移
          scale: 1,      // 图标缩小显示
          opacity: 1,    //透明度
          src: arrow.img,     //图片路径
        })
      })
    )
  }
  if (text?.name) {
    styles.push(
      new ol.style.Style({
        text : new ol.style.Text({
          text : text.name,
          textAlign: 'center',     //对齐方式
          textBaseline: 'middle',    //文本基线
          font: 'normal 14px 微软雅黑',     //字体样式
          offsetY: -70,    // Y轴偏置
          // offsetX : 30,
          fill: new ol.style.Fill({        //填充样式
            color: text.fill
          }),
          backgroundFill: new ol.style.Fill({      // 填充背景
            color: text.bgFill
          }),
          backgroundStroke : new ol.style.Stroke({
            color : text.strokeFill,
            width : 2
          }),
          padding: [5, 10, 2, 10],
        })
      })
    )
  }
  if (cover?.img) {
    styles.push(
      new ol.style.Style({
        image: new ol.style.Icon({
          anchor: [0.5,0.8],      //设置图标偏移
          scale: 1,      // 图标缩小显示
          opacity: 1,    //透明度
          src: cover.img,     //图片路径
        })
      })
    )
  }
  if (progress?.img) {
    styles.push(
      new ol.style.Style({
        image: new ol.style.Icon({
          anchor: [0.5,6],      //设置图标偏移
          scale: 1,      // 图标缩小显示
          opacity: 1,    //透明度
          src: progress.img,     //图片路径
        })
      })
    )
  }
  feature.setStyle(styles)
  return feature;
}

效果如下,图文并不关联

项目原因,效果图无法上传,自行替代样式

声明:yopaopao|版权所有,违者必究|如未注明,均为原创|本网站采用BY-NC-SA协议进行授权

转载:转载请注明原文链接 - 【openlayer】 聚合


正如我心中爱你美丽 又怎能嘴上装四大皆空