1. 放大缩小地图实现聚合分散效果

2. 实现聚合分散代码(核心查看 addCluster 和 clusterStyle 方法)
mounted :初始化一些数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | mounted() { let clusterData = { 成都市: { center: { lng: 104.061902, lat: 30.609503 } }, 广安市: { center: { lng: 106.619126, lat: 30.474142 } }, 绵阳市: { center: { lng: 104.673612, lat: 31.492565 } }, 雅安市: { center: { lng: 103.031653, lat: 30.018895 } }, 自贡市: { center: { lng: 104.797794, lat: 29.368322 } }, 宜宾市: { center: { lng: 104.610964, lat: 28.781347 } }, 内江市: { center: { lng: 105.064555, lat: 29.581632 } } }; let points = [ { name: "成都市", value: 85 }, { name: "绵阳市", value: 36 }, { name: "广安市", value: 50 }, { name: "雅安市", value: 555 }, { name: "自贡市", value: 55 }, { name: "宜宾市", value: 666 }, { name: "内江市", value: 777 } ]; // 实现聚合分散方法 this.addCluster(clusterData, points, true); } |
addCluster 方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | // 设置聚合分散效果 addCluster(clusterData, points, clearup) { let source = new VectorSource(); let clusterSource = new Cluster({ distance: parseInt(20, 10), // 设置聚合多少范围间距会聚合 source: source }); let layer = new VectorLayer({ source: clusterSource, style: this.clusterStyle.call(this) }); this.map.addLayer(layer); for (const key in clusterData) { points.forEach(e => { if (e.name == key) { let point = fromLonLat([ clusterData[key].center.lng, clusterData[key].center.lat ]); var f = new Feature({ geometry: new Point(point) }); f.set("name", e.name); // 设置name值 f.set("value", e.value); // 设置vaue值 f.set("type", "cluster"); source.addFeature(f); layer.getSource().addFeatures(f); } }); } }, |
clusterStyle 方法,详细说明看注释
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | // 设置聚合分散的图标样式 clusterStyle() { return (feature, solution) => { var total = 0; feature.get("features").forEach((value, index) => { // 通过value.get("属性名") 获取设置的值 total += value.get("value"); // 获取累加的数值 }); var style = new Style({ image: new CircleStyle({ radius: 15, //设置圆角大小 stroke: new Stroke({ color: "blue" //设置园stroke颜色 }), fill: new Fill({ color: "rgba(24,144,255,100)" //设置填充颜色 }) }), text: new Text({ text: total.toString(), // 文字显示的数值 fill: new Fill({ color: "#FFF" // 文字显示的颜色 }) }) }); return style; }; }, |
3. 完整代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 | <template> <div id="app"> <div id="Map" ref="map"></div> </div> </template> <script> import "ol/ol.css"; import TileLayer from "ol/layer/Tile"; import VectorLayer from "ol/layer/Vector"; import VectorSource from "ol/source/Vector"; import XYZ from "ol/source/XYZ"; import { Map, View, Feature, ol } from "ol"; import { Style, Stroke, Fill, Icon, Text, Circle as CircleStyle } from "ol/style"; import { Polygon, Point } from "ol/geom"; import { defaults as defaultControls } from "ol/control"; import { Cluster } from "ol/source"; import { fromLonLat } from "ol/proj"; import areaGeo from "@/geoJson/sichuan.json"; export default { data() { return { map: null }; }, methods: { /** * 初始化地图 */ initMap() { this.map = new Map({ target: "Map", controls: defaultControls({ zoom: true }).extend([]), layers: [ new TileLayer({ source: new XYZ({ url: "http://map.geoq.cn/ArcGIS/rest/services/ChinaOnlineStreetPurplishBlue/MapServer/tile/{z}/{y}/{x}" }) }) ], view: new View({ // projection: "EPSG:4326", center: fromLonLat([104.065735, 30.659462]), zoom: 6.5, maxZoom: 19, minZoom: 3 }) }); }, /** * 设置区域 */ addArea(geo = []) { if (geo.length == 0) { return false; } let features = []; geo.forEach(g => { let lineData = g.features[0]; let routeFeature = ""; if (lineData.geometry.type == "MultiPolygon") { routeFeature = new Feature({ geometry: new MultiPolygon( lineData.geometry.coordinates ).transform("EPSG:4326", "EPSG:3857") }); } else if (lineData.geometry.type == "Polygon") { routeFeature = new Feature({ geometry: new Polygon( lineData.geometry.coordinates ).transform("EPSG:4326", "EPSG:3857") }); } routeFeature.setStyle( new Style({ fill: new Fill({ color: "#4e98f444" }), stroke: new Stroke({ width: 3, color: [71, 137, 227, 1] }) }) ); features.push(routeFeature); }); // 设置图层 let routeLayer = new VectorLayer({ source: new VectorSource({ features: features }) }); // 添加图层 this.map.addLayer(routeLayer); }, addCluster(clusterData, points, clearup) { let source = new VectorSource(); let clusterSource = new Cluster({ distance: parseInt(20, 10), source: source }); let layer = new VectorLayer({ source: clusterSource, style: this.clusterStyle.call(this) }); this.map.addLayer(layer); for (const key in clusterData) { points.forEach(e => { if (e.name == key) { let point = fromLonLat([ clusterData[key].center.lng, clusterData[key].center.lat ]); var f = new Feature({ geometry: new Point(point) }); f.set("name", e.name); f.set("value", e.value); f.set("type", "cluster"); source.addFeature(f); layer.getSource().addFeatures(f); } }); } }, clusterStyle() { return (feature, solution) => { var total = 0; feature.get("features").forEach((value, index) => { total += value.get("value"); }); var style = new Style({ image: new CircleStyle({ radius: 15, stroke: new Stroke({ color: "blue" }), fill: new Fill({ color: "rgba(24,144,255,100)" }) }), text: new Text({ text: total.toString(), fill: new Fill({ color: "#FFF" }) }) }); return style; }; }, /** * 鼠标悬浮改变图标样式 */ pointerMove() { let _that = this; this.map.on("pointermove", function(evt) { _that.map.getTargetElement().style.cursor = _that.map.hasFeatureAtPixel( evt.pixel ) ? "pointer" : ""; }); } }, mounted() { this.initMap(); this.addArea(areaGeo); this.pointerMove(); let clusterData = { 成都市: { center: { lng: 104.061902, lat: 30.609503 } }, 广安市: { center: { lng: 106.619126, lat: 30.474142 } }, 绵阳市: { center: { lng: 104.673612, lat: 31.492565 } }, 雅安市: { center: { lng: 103.031653, lat: 30.018895 } }, 自贡市: { center: { lng: 104.797794, lat: 29.368322 } }, 宜宾市: { center: { lng: 104.610964, lat: 28.781347 } }, 内江市: { center: { lng: 105.064555, lat: 29.581632 } } }; let points = [ { name: "成都市", value: 85 }, { name: "绵阳市", value: 36 }, { name: "广安市", value: 50 }, { name: "雅安市", value: 555 }, { name: "自贡市", value: 55 }, { name: "宜宾市", value: 666 }, { name: "内江市", value: 777 } ]; this.addCluster(clusterData, points, true); } }; </script> <style lang="scss" scoped> // 此处非核心,已经删除 </style> |