|
@ -4,12 +4,7 @@ |
|
|
<slot name="content" class="content"></slot> |
|
|
<slot name="content" class="content"></slot> |
|
|
<commonModal v-model="pointsState" width="800" title="聚合列表"> |
|
|
<commonModal v-model="pointsState" width="800" title="聚合列表"> |
|
|
<div class="points"> |
|
|
<div class="points"> |
|
|
<div |
|
|
<div class="item" v-for="(item, index) in points" :key="index" @click="getPoint(item.point)"> |
|
|
class="item" |
|
|
|
|
|
v-for="(item, index) in points" |
|
|
|
|
|
:key="index" |
|
|
|
|
|
@click="getPoint(item.point)" |
|
|
|
|
|
> |
|
|
|
|
|
{{ item.point[listItemKey] }} |
|
|
{{ item.point[listItemKey] }} |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
@ -90,6 +85,8 @@ export default { |
|
|
pointsState: false, |
|
|
pointsState: false, |
|
|
points: [], |
|
|
points: [], |
|
|
tags: [], |
|
|
tags: [], |
|
|
|
|
|
geojsonPath: "@/assets/geojson/town_boundaries.geojson", // GeoJSON 文件路径 |
|
|
|
|
|
polygons: [], // 乡镇边界多边形 |
|
|
}; |
|
|
}; |
|
|
}, |
|
|
}, |
|
|
props: { |
|
|
props: { |
|
@ -176,6 +173,7 @@ export default { |
|
|
} |
|
|
} |
|
|
}); |
|
|
}); |
|
|
}, |
|
|
}, |
|
|
|
|
|
|
|
|
initMap() { |
|
|
initMap() { |
|
|
const imgLayer = new AMap.TileLayer({ |
|
|
const imgLayer = new AMap.TileLayer({ |
|
|
zIndex: 0, |
|
|
zIndex: 0, |
|
@ -183,49 +181,216 @@ export default { |
|
|
`http://t0.tianditu.gov.cn/DataServer?T=img_w&tk=${this.common.mapKey}&x=${x}&y=${y}&l=${z}`, |
|
|
`http://t0.tianditu.gov.cn/DataServer?T=img_w&tk=${this.common.mapKey}&x=${x}&y=${y}&l=${z}`, |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
const district = new AMap.DistrictSearch({ |
|
|
|
|
|
subdistrict: 3, |
|
|
|
|
|
extensions: "all", |
|
|
|
|
|
level: "district", |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
district.search(this.districtLocation, (status, result) => { |
|
|
|
|
|
const bounds = result.districtList[0].boundaries; |
|
|
|
|
|
const mask = bounds.map((bound) => [bound]); |
|
|
|
|
|
const polygons = bounds.map( |
|
|
|
|
|
(bound) => |
|
|
|
|
|
new AMap.Polygon({ |
|
|
|
|
|
strokeWeight: 5, |
|
|
|
|
|
path: bound, |
|
|
|
|
|
fillOpacity: 0.8, |
|
|
|
|
|
fillColor: "rgba(67, 112, 122,0.55)", |
|
|
|
|
|
strokeColor: "#94c4ce", |
|
|
|
|
|
}) |
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
this.map = new AMap.Map("center-map", { |
|
|
this.map = new AMap.Map("center-map", { |
|
|
mask, |
|
|
layers: this.common.isSkyMap ? [imgLayer] : [new AMap.TileLayer.RoadNet()], |
|
|
layers: this.common.isSkyMap |
|
|
|
|
|
? [imgLayer] |
|
|
|
|
|
: [new AMap.TileLayer.RoadNet], |
|
|
|
|
|
zoom: this.zoom, |
|
|
zoom: this.zoom, |
|
|
zooms: [3, 16], |
|
|
zooms: [3, 16], |
|
|
scrollWheel: true, |
|
|
scrollWheel: true, |
|
|
center: that.center, |
|
|
center: this.center || [104.62, 28.77], // 宜宾翠屏区中心坐标 |
|
|
// pitch: 10, // 地图俯仰角度,有效范围 0 度- 83 度 |
|
|
viewMode: "3D", |
|
|
viewMode: "3D", // 地图模式 |
|
|
resizeEnable: true, |
|
|
resizeEnable: true, //是否监控地图容器尺寸变化 |
|
|
|
|
|
mapStyle: "amap://styles/darkblue", |
|
|
mapStyle: "amap://styles/darkblue", |
|
|
features: ["bg", "road", "building", "point"] |
|
|
features: ["bg", "road", "building", "point"], |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
this.map.on("complete", () => { |
|
|
this.map.on("complete", () => { |
|
|
|
|
|
if (this.aggregationPoint) { |
|
|
this.aggregationPoint(this.pointList); |
|
|
this.aggregationPoint(this.pointList); |
|
|
|
|
|
} |
|
|
|
|
|
this.addPoints(); // 添加点标记 |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
this.map.add(polygons); |
|
|
// 加载乡镇边界 GeoJSON |
|
|
|
|
|
this.loadGeoJSON(); |
|
|
|
|
|
|
|
|
|
|
|
// 加载翠屏区底图 |
|
|
|
|
|
this.loadCuiPingDistrict(); |
|
|
|
|
|
|
|
|
|
|
|
// 添加地图点击事件 |
|
|
|
|
|
// this.map.on('click', this.handleMapClick); |
|
|
|
|
|
}, |
|
|
|
|
|
handleMapClick(e) { |
|
|
|
|
|
const lngLat = e.lnglat; |
|
|
|
|
|
console.log('点击坐标:', lngLat); |
|
|
|
|
|
|
|
|
|
|
|
this.polygons.forEach(polygon => { |
|
|
|
|
|
const path = polygon.getPath(); |
|
|
|
|
|
const isInPolygon = AMap.GeometryUtil.isPointInRing(lngLat.toArray(), path.map(p => p.toArray())); |
|
|
|
|
|
|
|
|
|
|
|
console.log('多边形:', isInPolygon); |
|
|
|
|
|
|
|
|
|
|
|
if (isInPolygon) { |
|
|
|
|
|
const name = polygon.getExtData().name; |
|
|
|
|
|
console.log('点击:', name); |
|
|
|
|
|
this.map.setZoomAndCenter(10, lngLat); // 放大并定位到点击区域 |
|
|
|
|
|
alert(`您点击了乡镇:${name}`); |
|
|
|
|
|
} |
|
|
}); |
|
|
}); |
|
|
}, |
|
|
}, |
|
|
|
|
|
loadCuiPingDistrict() { |
|
|
|
|
|
const districtSearch = new AMap.DistrictSearch({ |
|
|
|
|
|
subdistrict: 3, // 不获取子级数据 |
|
|
|
|
|
extensions: "all", |
|
|
|
|
|
level: "district", |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
const self = this; // 保存上下文以便回调使用 |
|
|
|
|
|
districtSearch.search(this.districtLocation, function (status, result) { |
|
|
|
|
|
if (status === "complete" && result.districtList && result.districtList.length) { |
|
|
|
|
|
const district = result.districtList[0]; |
|
|
|
|
|
const boundaries = district.boundaries; |
|
|
|
|
|
|
|
|
|
|
|
if (boundaries) { |
|
|
|
|
|
// 绘制翠屏区底图 |
|
|
|
|
|
self.drawCuiPingBase(boundaries); |
|
|
|
|
|
} else { |
|
|
|
|
|
console.warn("翠屏区无边界数据"); |
|
|
|
|
|
} |
|
|
|
|
|
} else { |
|
|
|
|
|
console.error("行政区查询失败: " + status); |
|
|
|
|
|
} |
|
|
|
|
|
}); |
|
|
|
|
|
}, |
|
|
|
|
|
drawCuiPingBase(boundaries) { |
|
|
|
|
|
const mask = boundaries.map((boundary) => [boundary]); |
|
|
|
|
|
boundaries.forEach((boundary) => { |
|
|
|
|
|
const polygon = new AMap.Polygon({ |
|
|
|
|
|
path: boundary, |
|
|
|
|
|
strokeColor: "#333", // 边界线颜色 |
|
|
|
|
|
strokeWeight: 3, // 边界线宽度 |
|
|
|
|
|
fillColor: "#102C4F", // 填充颜色 |
|
|
|
|
|
fillOpacity: 0.7, // 填充透明度 |
|
|
|
|
|
}); |
|
|
|
|
|
this.map.add(polygon); |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
// 设置翠屏区为遮罩 |
|
|
|
|
|
this.map.setMask(mask); |
|
|
|
|
|
}, |
|
|
|
|
|
debounce(func, wait) { |
|
|
|
|
|
let timeout; |
|
|
|
|
|
return function (...args) { |
|
|
|
|
|
const context = this; |
|
|
|
|
|
clearTimeout(timeout); |
|
|
|
|
|
timeout = setTimeout(() => func.apply(context, args), wait); |
|
|
|
|
|
}; |
|
|
|
|
|
}, |
|
|
|
|
|
loadGeoJSON() { |
|
|
|
|
|
// 使用 require 加载 GeoJSON 文件 |
|
|
|
|
|
const geojsonData = require('@/assets/geojson/town_boundaries.geojson'); |
|
|
|
|
|
|
|
|
|
|
|
const colors = ['#33FFD450']; |
|
|
|
|
|
|
|
|
|
|
|
// 提取所有边界坐标 |
|
|
|
|
|
const boundaries = geojsonData.features.map((feature) => { |
|
|
|
|
|
const coordinates = feature.geometry.coordinates[0]; // 假设是 Polygon 类型 |
|
|
|
|
|
return coordinates[0].map((coord) => new AMap.LngLat(coord[0], coord[1])); // 转换为 AMap 坐标 |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
// this.map.setMask(boundaries); |
|
|
|
|
|
|
|
|
|
|
|
// 添加标签 |
|
|
|
|
|
geojsonData.features.forEach((feature, index) => { |
|
|
|
|
|
const { properties, geometry } = feature; |
|
|
|
|
|
const name = properties.name; // 获取乡镇名称 |
|
|
|
|
|
const coordinates = geometry.coordinates[0]; // 获取多边形的坐标 |
|
|
|
|
|
const center = this.getPolygonCenter(coordinates); // 获取多边形的中心点 |
|
|
|
|
|
console.log('多边形中心点:', center); |
|
|
|
|
|
|
|
|
|
|
|
const path = coordinates[0].map((coord) => new AMap.LngLat(coord[0], coord[1])); |
|
|
|
|
|
path.push(path[0]); // 闭合路径 |
|
|
|
|
|
|
|
|
|
|
|
// 创建多边形并设置样式 |
|
|
|
|
|
const polygon = new AMap.Polygon({ |
|
|
|
|
|
zIndex: 100, |
|
|
|
|
|
// path: coordinates[0].map((coord) => new AMap.LngLat(coord[0], coord[1])), // 转换为 AMap 坐标 |
|
|
|
|
|
path, |
|
|
|
|
|
strokeColor: colors[index % colors.length], // 边界线颜色 |
|
|
|
|
|
strokeWeight: 3, // 边界线宽度 |
|
|
|
|
|
fillColor: '#0A7EA8', // 填充颜色 |
|
|
|
|
|
fillOpacity: 0.5, // 填充透明度 |
|
|
|
|
|
bubble: true, // 允许事件冒泡 |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
// 将多边形添加到地图 |
|
|
|
|
|
polygon.setMap(this.map); |
|
|
|
|
|
|
|
|
|
|
|
if (name && center) { |
|
|
|
|
|
const labelMarker = new AMap.Marker({ |
|
|
|
|
|
position: center, |
|
|
|
|
|
zIndex: 2000, |
|
|
|
|
|
clickable: true, |
|
|
|
|
|
content: ` |
|
|
|
|
|
<div style=" |
|
|
|
|
|
font-size: 16px; |
|
|
|
|
|
font-weight: bold; |
|
|
|
|
|
color: #fff; |
|
|
|
|
|
width: max-content; |
|
|
|
|
|
"> |
|
|
|
|
|
${name} |
|
|
|
|
|
</div> |
|
|
|
|
|
`, |
|
|
|
|
|
offset: new AMap.Pixel(-25, -25), // 调整文本位置 |
|
|
|
|
|
}); |
|
|
|
|
|
// labelMarker的hover改变样式,高亮 |
|
|
|
|
|
labelMarker.on('mouseover', () => { |
|
|
|
|
|
labelMarker.setContent(` |
|
|
|
|
|
<div style=" |
|
|
|
|
|
font-size: 16px; |
|
|
|
|
|
font-weight: bold; |
|
|
|
|
|
color: #C6E1CA; |
|
|
|
|
|
width: max-content; |
|
|
|
|
|
"> |
|
|
|
|
|
${name} |
|
|
|
|
|
</div> |
|
|
|
|
|
`); |
|
|
|
|
|
}); |
|
|
|
|
|
labelMarker.on('mouseout', () => { |
|
|
|
|
|
labelMarker.setContent(` |
|
|
|
|
|
<div style=" |
|
|
|
|
|
font-size: 16px; |
|
|
|
|
|
font-weight: bold; |
|
|
|
|
|
color: #fff; |
|
|
|
|
|
width: max-content; |
|
|
|
|
|
"> |
|
|
|
|
|
${name} |
|
|
|
|
|
</div> |
|
|
|
|
|
`); |
|
|
|
|
|
}); |
|
|
|
|
|
// 使用 labelMarker.on 绑定事件 |
|
|
|
|
|
labelMarker.on('click', () => { |
|
|
|
|
|
console.log('点击:', name); |
|
|
|
|
|
}); |
|
|
|
|
|
this.map.add(labelMarker); |
|
|
|
|
|
} |
|
|
|
|
|
}); |
|
|
|
|
|
}, |
|
|
|
|
|
// 添加点标记 |
|
|
|
|
|
addPoints() { |
|
|
|
|
|
this.pointList.forEach((point) => { |
|
|
|
|
|
const marker = new AMap.Marker({ |
|
|
|
|
|
position: point.position, |
|
|
|
|
|
title: point.name, |
|
|
|
|
|
}); |
|
|
|
|
|
marker.setMap(this.map); |
|
|
|
|
|
}); |
|
|
|
|
|
}, |
|
|
|
|
|
// 计算多边形中心点 |
|
|
|
|
|
getPolygonCenter(coordinates) { |
|
|
|
|
|
if (!coordinates || !coordinates.length) return null; |
|
|
|
|
|
let [lngSum, latSum] = [0, 0]; |
|
|
|
|
|
coordinates[0].forEach((coord, index) => { |
|
|
|
|
|
if (Array.isArray(coord) && coord.length >= 2) { |
|
|
|
|
|
const [lng, lat] = coord; |
|
|
|
|
|
lngSum += lng; |
|
|
|
|
|
latSum += lat; |
|
|
|
|
|
} else { |
|
|
|
|
|
console.warn(`无效的坐标 ${index}:`, coord); // 调试信息 |
|
|
|
|
|
} |
|
|
|
|
|
}); |
|
|
|
|
|
return [lngSum / coordinates[0].length, latSum / coordinates[0].length]; |
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
aggregationPoint(pointList) { |
|
|
aggregationPoint(pointList) { |
|
|
const gridSize = 60; |
|
|
const gridSize = 60; |
|
|
const countIcon = require("@/assets/mapIcon/count.png"); |
|
|
const countIcon = require("@/assets/mapIcon/count.png"); |
|
@ -346,6 +511,9 @@ export default { |
|
|
this.$emit("currentPoint", data); |
|
|
this.$emit("currentPoint", data); |
|
|
}, |
|
|
}, |
|
|
}, |
|
|
}, |
|
|
|
|
|
mounted() { |
|
|
|
|
|
this.initMap(); |
|
|
|
|
|
}, |
|
|
}; |
|
|
}; |
|
|
</script> |
|
|
</script> |
|
|
|
|
|
|
|
|