<template>
|
<el-container>
|
<selectColor :select-color.sync="selectColor" :min-color="minColor" @changeRender="changeRender" />
|
<themeCom @styleChange="changeStyle" />
|
<el-main style="margin: 0px; padding: 0px">
|
<div id="aMap" :style="{ height: windowHeight - 50 + 'px' }" />
|
</el-main>
|
</el-container>
|
</template>
|
<script>
|
const markerContent = `
|
|
<div class="custom-content-marker" onclick="showContent()">
|
<img src="//a.amap.com/jsapi_demos/static/demo-center/icons/dir-via-marker.png">
|
</div>`
|
import selectColor from './components/selectColor.vue'
|
import themeCom from './components/theme.vue'
|
export default {
|
name: 'AMap',
|
components: {
|
selectColor,
|
themeCom
|
},
|
data() {
|
return {
|
circleMarker: [],
|
recordValue: [], // 记录绘制过的文字
|
adcode: 410000, // 中心行政code
|
currentCodeObj: '', // 中心行政code
|
map: null, // 地图实例化
|
districtExplorer: null, // 渲染行政区域实例化
|
windowHeight: document.documentElement.clientHeight,
|
selectColor: '#FF0000',
|
minColor: '',
|
provinceData: [
|
{
|
'name': '郑州市',
|
'value': '8.99'
|
},
|
{
|
'name': '开封市',
|
'value': '22.84'
|
},
|
{
|
'name': '洛阳市',
|
'value': '48.96'
|
},
|
{
|
'name': '平顶山市',
|
'value': '79.49'
|
},
|
{
|
'name': '安阳市',
|
'value': '37.82'
|
},
|
{
|
'name': '鹤壁市',
|
'value': '27.55'
|
},
|
{
|
'name': '新乡市',
|
'value': '90.76'
|
},
|
{
|
'name': '焦作市',
|
'value': '72.26'
|
},
|
{
|
'name': '濮阳市',
|
'value': '14.03'
|
},
|
{
|
'name': '许昌市',
|
'value': '32.93'
|
},
|
{
|
'name': '漯河市',
|
'value': '57.85'
|
},
|
{
|
'name': '三门峡市',
|
'value': '85.35'
|
},
|
{
|
'name': '南阳市',
|
'value': '99.59'
|
},
|
{
|
'name': '商丘市',
|
'value': '45.33'
|
},
|
{
|
'name': '信阳市',
|
'value': '69.38'
|
},
|
{
|
'name': '周口市',
|
'value': '65.45'
|
},
|
{
|
'name': '驻马店市',
|
'value': '90.25'
|
},
|
{
|
'name': '济源市',
|
'value': '88.85'
|
}
|
],
|
style: 'dark',
|
marker: [],
|
infoWindow: [],
|
// marker: [],
|
regionData: {
|
type: 'FeatureCollection',
|
features: [
|
{
|
type: 'Feature',
|
geometry: {
|
type: 'Polygon',
|
coordinates: [
|
[
|
[113.576491, 34.744435],
|
[113.605331, 34.768129],
|
[113.712447, 34.74782],
|
[113.673995, 34.66823],
|
[113.601211, 34.687994],
|
[113.573745, 34.705495],
|
[113.570998, 34.725249]
|
]
|
]
|
},
|
properties: {}
|
}
|
]
|
}
|
}
|
},
|
mounted() {
|
const vm = this
|
vm.loadMap()
|
},
|
methods: {
|
changeStyle(e) {
|
this.style = e
|
this.loadMap()
|
},
|
changeRender() {
|
this.loadMap()
|
},
|
loadMap() {
|
const vm = this
|
vm.map = new AMap.Map('aMap', {
|
viewMode: '2D', // 默认使用 2D 模式,如果希望使用带有俯仰角的 3D 模式,请设置 viewMode: '3D'
|
zoom: 11, // 初始化地图层级
|
center: [113.681999, 34.762029], // 初始化地图中心点
|
mapStyle: 'amap://styles/' + this.style
|
})
|
vm.fillCityOrTown()
|
},
|
// 加载河南省市县
|
fillCityOrTown() {
|
const vm = this
|
AMapUI.loadUI(['geo/DistrictExplorer'], function(DistrictExplorer) {
|
// 启动页面
|
vm.initPage(DistrictExplorer)
|
})
|
},
|
initPage(DistrictExplorer) {
|
const vm = this
|
// 创建一个实例
|
vm.districtExplorer = new DistrictExplorer({
|
eventSupport: true, // 打开事件支持
|
map: vm.map // 关联的地图实例
|
})
|
// 配置点击事件
|
vm.districtExplorer.on('featureClick', function(e, feature) {
|
var props = feature.properties
|
// 如果存在子节点
|
vm.recordValue.map(item => {
|
item.setMap(null)
|
})
|
|
vm.recordValue = []
|
vm.circleMarker.map(item => {
|
// item.setMap(null)
|
vm.map.remove(item)
|
})
|
vm.circleMarker = []
|
if (feature.properties.level === 'district') {
|
setTimeout(() => {
|
vm.drawMarker(feature.properties.center)
|
}, 500)
|
vm.initData()
|
}
|
// if (props.childrenNum > 0) {
|
// 切换聚焦区域
|
vm.switch2AreaNode(props.adcode)
|
// }
|
})
|
// 外部区域被点击
|
vm.districtExplorer.on('outsideClick', function(e) {
|
vm.districtExplorer.locatePosition(e.originalEvent.lnglat, function(_error, routeFeatures) {
|
vm.recordValue.map(item => {
|
item.setMap(null)
|
})
|
vm.recordValue = []
|
vm.infoWindow.forEach(element => {
|
element.close(vm.map)
|
})
|
vm.marker.forEach(element => {
|
element.setMap(null)
|
})
|
vm.circleMarker.map(item => {
|
// item.setMap(null)
|
vm.map.remove(item)
|
})
|
vm.circleMarker = []
|
if (routeFeatures && routeFeatures.length > 1) {
|
// 切换到省级区域
|
vm.switch2AreaNode(routeFeatures[1].properties.adcode)
|
} else {
|
// 切换到全国
|
vm.switch2AreaNode(100000)
|
}
|
}, {
|
levelLimit: 2
|
})
|
})
|
var adcode = vm.adcode // 全国的区划编码
|
vm.districtExplorer.loadAreaNode(adcode, function(error, areaNode) {
|
if (error) {
|
console.error(error)
|
return
|
}
|
// 绘制载入的区划节点
|
vm.renderAreaNode(areaNode)
|
})
|
},
|
initData(){
|
for (let i = 0; i < this.regionData.features.length; i++) {
|
let item = this.regionData.features[i];
|
if(item.geometry.type=='Polygon'){
|
let arr = item.geometry.coordinates
|
let polygon = new AMap.Polygon({
|
path: arr,
|
fillColor: '#ccebc5',
|
strokeOpacity: 1,
|
fillOpacity: 0.2,//背景透明度
|
strokeColor: '#2b8cbe',
|
strokeWeight: 2,
|
strokeStyle: 'dashed',
|
strokeDasharray: [5, 5],
|
});
|
this.map.add(polygon);
|
}
|
}
|
},
|
getMathRandom() {
|
return (Math.random() * 101).toFixed(2)
|
},
|
adjustColor(color, range) {
|
let newColor = '#'
|
for (let i = 0; i < 3; i++) {
|
const hxStr = color.substr(i * 2 + 1, 2)
|
let val = parseInt(hxStr, 16)
|
val += range
|
if (val < 0) val = 0
|
else if (val > 255) val = 255
|
newColor += val.toString(16).padStart(2, '0')
|
}
|
this.$emit('minColor', newColor)
|
return newColor
|
},
|
renderAreaNode(areaNode) {
|
const vm = this
|
vm.map.setBounds(areaNode.getBounds(), null, null, true)
|
// 清除已有的绘制内容
|
vm.districtExplorer.clearFeaturePolygons()
|
var colors = ['#3366cc', '#dc3912', '#ff9900', '#109618', '#990099', '#0099c6', '#dd4477', '#66aa00']
|
// 绘制子区域
|
// const arr = []
|
vm.districtExplorer.renderSubFeatures(areaNode, function(feature, i) {
|
// arr.push({
|
// name: feature.properties.name, value: vm.getMathRandom()
|
// })
|
// console.log(feature.adcode) // 行政区的areacode
|
var fillColor = colors[i % colors.length]
|
var strokeColor = colors[colors.length - 1 - i % colors.length]
|
const value = vm.provinceData.find(item => item.name === feature.properties.name)
|
const color = vm.adjustColor(vm.selectColor, 200)
|
const colorValue = vm.getColorBetween(value.value, 0, 100, color, vm.selectColor)
|
const fontStyle = {
|
'background-color': 'rgba(0,0,0,0)',
|
'border-width': 0,
|
'font-size': '10px',
|
color: '#fff',
|
'text-align': 'center'
|
}
|
// 定义Text类
|
const text1 = new AMap.Text({
|
text: feature.properties.name,
|
position: new AMap.LngLat(feature.properties.center[0], feature.properties.center[1]),
|
style: fontStyle
|
})
|
// 创建圆形点标记 CircleMarker 实例
|
const circleMarker = new AMap.CircleMarker({
|
center: new AMap.LngLat(feature.properties.center[0], feature.properties.center[1]),
|
radius: 4, // 3D视图下,CircleMarker半径不要超过64px
|
strokeColor: 'white',
|
strokeWeight: 2,
|
strokeOpacity: 1,
|
fillColor: 'green',
|
fillOpacity: 1,
|
zIndex: 100000,
|
bubble: true,
|
cursor: 'pointer',
|
clickable: true
|
})
|
vm.recordValue.push(text1)
|
vm.circleMarker.push(circleMarker)
|
vm.map.add(text1)
|
vm.map.add(circleMarker)
|
return {
|
cursor: 'default',
|
bubble: true,
|
strokeColor: strokeColor, // 线颜色
|
strokeOpacity: 1, // 线透明度
|
strokeWeight: 1, // 线宽
|
fillColor: colorValue, // 填充色
|
fillOpacity: 1 // 填充透明度
|
}
|
})
|
// 绘制父区域
|
vm.districtExplorer.renderParentFeature(areaNode, {
|
cursor: 'default',
|
bubble: true,
|
strokeColor: 'black', // 线颜色
|
strokeOpacity: 1, // 线透明度
|
strokeWeight: 1, // 线宽
|
fillColor: areaNode.getSubFeatures().length ? null : colors[0], // 填充色
|
fillOpacity: 0.35 // 填充透明度
|
})
|
// vm.
|
|
vm.map.setFitView(vm.districtExplorer.getAllFeaturePolygons())
|
},
|
// 刷新页面
|
switch2AreaNode(adcode, callback) {
|
const vm = this
|
if (vm.currentCodeObj && ('' + vm.currentCodeObj.getAdcode() === '' + adcode)) {
|
return
|
}
|
vm.loadAreaNode(adcode, function(error, areaNode) {
|
if (error) {
|
if (callback) {
|
callback(error)
|
}
|
return
|
}
|
vm.adcode = window.currentAreaNode = areaNode.adcode
|
vm.currentCodeObj = window.currentAreaNode = areaNode
|
// 设置当前使用的定位用节点
|
vm.districtExplorer.setAreaNodesForLocating([vm.currentCodeObj])
|
vm.refreshAreaNode(areaNode)
|
if (callback) {
|
callback(null, areaNode)
|
}
|
})
|
},
|
// 刷新区域边界
|
loadAreaNode(adcode, callback) {
|
const vm = this
|
vm.districtExplorer.loadAreaNode(adcode, function(error, areaNode) {
|
if (error) {
|
if (callback) {
|
callback(error)
|
}
|
return
|
}
|
if (callback) {
|
callback(null, areaNode)
|
}
|
})
|
},
|
refreshAreaNode(areaNode) {
|
this.districtExplorer.setHoverFeature(null)
|
this.renderAreaPolygons(areaNode)
|
},
|
// 绘制某个区域的边界
|
renderAreaPolygons(areaNode) {
|
const vm = this
|
// 更新地图视野
|
vm.map.setBounds(areaNode.getBounds(), null, null, true)
|
// 清除已有的绘制内容
|
vm.districtExplorer.clearFeaturePolygons()
|
var colors = ['#3366cc', '#dc3912', '#ff9900', '#109618', '#990099', '#0099c6', '#dd4477', '#66aa00']
|
// 绘制子区域
|
vm.districtExplorer.renderSubFeatures(areaNode, function(feature, i) {
|
var fillColor = colors[i % colors.length]
|
var strokeColor = colors[colors.length - 1 - i % colors.length]
|
const fontStyle = {
|
'background-color': 'rgba(0,0,0,0)',
|
'border-width': 0,
|
'text-align': 'center',
|
'font-size': '14px',
|
color: '#fff'
|
}
|
const text1 = new AMap.Text({
|
text: feature.properties.name,
|
position: new AMap.LngLat(feature.properties.center[0], feature.properties.center[1]),
|
style: fontStyle
|
})
|
vm.recordValue.push(text1)
|
|
vm.map.add(text1)
|
|
const value = vm.provinceData.find(item => item.name === feature.properties.name)
|
if (value && value.value) {
|
const color = vm.adjustColor(vm.selectColor, 200)
|
fillColor = vm.getColorBetween(value.value, 0, 100, color, vm.selectColor)
|
}
|
// 创建圆形点标记 CircleMarker 实例
|
const circleMarker = new AMap.CircleMarker({
|
center: new AMap.LngLat(feature.properties.center[0], feature.properties.center[1]),
|
radius: 4, // 3D视图下,CircleMarker半径不要超过64px
|
strokeColor: 'white',
|
strokeWeight: 2,
|
strokeOpacity: 1,
|
fillColor: 'green',
|
fillOpacity: 1,
|
zIndex: 100000,
|
bubble: true,
|
cursor: 'pointer',
|
clickable: true
|
})
|
vm.circleMarker.push(circleMarker)
|
vm.map.add(circleMarker)
|
return {
|
cursor: 'default',
|
bubble: true,
|
strokeColor: strokeColor, // 线颜色
|
strokeOpacity: 1, // 线透明度
|
strokeWeight: 1, // 线宽
|
fillColor: fillColor, // 填充色
|
fillOpacity: 1 // 填充透明度
|
}
|
})
|
|
// 绘制父区域
|
vm.districtExplorer.renderParentFeature(areaNode, {
|
cursor: 'default',
|
bubble: true,
|
strokeColor: 'black', // 线颜色
|
strokeOpacity: 1, // 线透明度
|
strokeWeight: 1, // 线宽
|
fillColor: areaNode.getSubFeatures().length ? null : colors[0], // 填充色
|
fillOpacity: 0.35 // 填充透明度
|
})
|
},
|
// 根据值返回颜色
|
getColorBetween(value, minValue, maxValue, minColor, maxColor) {
|
// 将颜色转换为RGB
|
function hexToRgb(hex) {
|
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex)
|
return result ? {
|
r: parseInt(result[1], 16),
|
g: parseInt(result[2], 16),
|
b: parseInt(result[3], 16)
|
} : null
|
}
|
|
// 将RGB转换为十六进制颜色
|
function rgbToHex(r, g, b) {
|
return '#' + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1)
|
}
|
|
// 将颜色的每个分量进行插值
|
function interpolateColor(start, end, factor) {
|
return Math.round(start + (end - start) * factor)
|
}
|
|
// 确保值在最小值和最大值之间
|
value = Math.max(minValue, Math.min(value, maxValue))
|
|
// 计算因子,将值范围映射到0到1之间
|
const factor = (value - minValue) / (maxValue - minValue)
|
|
// 获取两种颜色的RGB值
|
const minRgb = hexToRgb(minColor)
|
const maxRgb = hexToRgb(maxColor)
|
// 根据因子插值RGB分量
|
const r = interpolateColor(minRgb.r, maxRgb.r, factor)
|
const g = interpolateColor(minRgb.g, maxRgb.g, factor)
|
const b = interpolateColor(minRgb.b, maxRgb.b, factor)
|
|
// 将RGB转换为十六进制颜色并返回
|
return rgbToHex(r, g, b)
|
},
|
// 绘制标点
|
// 绘制标点
|
drawMarker(positionArg) {
|
var content = [
|
'<div><b>这是个提示文字</b>',
|
'地址:郑州市金水区花园路</div>'
|
]
|
const position = new AMap.LngLat(positionArg[0], positionArg[1]) // Marker 经纬度
|
// 创建 infoWindow 实例
|
|
function getImageUrl(url) {
|
console.log(`../../assets/icon/${url}.png`)
|
const path = new URL(`../../assets/icon/${url}.png`, import.meta.url)
|
return path.href
|
}
|
|
for (let a = 0; a < 4; a++) {
|
const icon = new AMap.Icon({
|
size: new AMap.Size(20, 20), // 图标尺寸
|
image: getImageUrl(`icon${a + 1}`), // 图标的URL
|
imageSize: new AMap.Size(20, 20) // 图标所用图片的大小
|
})
|
const position = new AMap.LngLat(positionArg[0] - 0.02 * a, positionArg[1]) // Marker 经纬度
|
const infoWindow = new AMap.InfoWindow({
|
content: content.join('<br>'), // 传入字符串拼接的 DOM 元素
|
anchor: 'top-center',
|
position: position
|
// offset: [10, 40]
|
})
|
this.infoWindow.push(infoWindow)
|
const marker = new AMap.Marker({
|
position: position,
|
// content: markerContent, // 将 html 传给 content
|
// icon: '',
|
icon: icon,
|
offset: new AMap.Pixel(-10, -30) // 以 icon 的 [center bottom] 为原点
|
})
|
this.map.add(marker)
|
this.marker.push(marker)
|
marker.on('click', () => {
|
infoWindow.open(this.map)
|
})
|
}
|
}
|
}
|
}
|
</script>
|
|
<style scoped>
|
.aMap {
|
width: 100vw;
|
height: 100vh;
|
}
|
</style>
|