十分钟玩转 vue3+高德地图AMap+geojson批量绘制Polygon地块数据展示【三、Geojson地图数据批量导入地图】

本章节文末,付完整代码

在public/目录新建设一个data目录,里面存放geojson数据

在这里插入图片描述
这里我提供部分json数据给大家用于练习使用:


逻辑分析和处理:

1.开始处理控制面板勾选年份的事件
触发选中后,需要做个判断,是否第一次读取 geojson 数据。 如果是第一次读取,则使用getdata方法去跑axios,获取数据。如果不是第一次加载数据,则跑showpolygon 或者 hidepolygon 方法来进行显示或者隐藏地块。

polygonarr 为地块数组
polygondata 为地块数据

var map  = shallowRef(null);
var amap = (null);
var checkobj ={}
const GetMassif = (aa:any) => {
    
    var checkarr = [] // 年,颜色,当前状态,是否加载
    checkarr= aa.split(',')
    if (checkobj[checkarr[0]]){
        
        // 不是第一次加载geojson数据
        if (checkarr[2]==1){
            showpolygon(checkarr[0])//展示地块
        }else{
            hidepolygon(checkarr[0])//隐藏地块
        }
        
    }else{

        checkarr.push("1")//存入第四个参数,是否加载
        checkobj[checkarr[0]]= checkarr
        //如果是第一次加载,则需要用axios读取数据;
        if (checkarr[2]==1){
            getdata(checkarr[0],checkarr[1]) //首次加载数据
        }

    }
    
}


//隐藏覆盖物
const hidepolygon = (year:any)=>{
    polygonarr.forEach(element => {//循环地块数组
        
        if (element.id == year){
            element.polygondata.hide()//隐藏地块
        }
    });
}
//显示覆盖物
const showpolygon = (year:any)=>{
    polygonarr.forEach(element => {
        if (element.id == year){
            element.polygondata.show()
        }
    })
}

2.走 getdata 方法直接读取arcgis 转出来的geojson 数据,我这里的数据为gps84坐标数据,需要用高德的API的convertFrom函数,转换成高德高的坐标系。

//读取geojson数据
var dataarr = []
var datalt = {}
const getdata = (year :any,color:any) =>{
    axios({
        method: 'get',
        url: 'public/data/dk'+year+'.json',
    }).then((res) => {

        datalt={
            "year":year,
            "data":res.data
        }
        dataarr.push(datalt)
        
        // 走转换数据的方法
        TransformationData(res.data,year,color)
        console.log('GeoJSON 数据加载完成')
    }).catch((msg) => {
        console.log("msg", msg)
        console.log('GeoJSON 服务请求失败')
    })

}

备注:以下为geojson数据

{
  "type": "FeatureCollection",
  "crs": { "type": "name", "properties": { "name": "EPSG:4326" } },
  "features": [
    {
      "type": "Feature",
      "id": 1,
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          [
            [108.99980896100004, 22.999783316000048, 0],
            [108.99946594000005, 22.999994280000067, 0],
            [108.99925232000004, 22.999885560000052, 0],
            [108.99980164000004, 22.999479290000068, 0],
            [109.00005341000008, 22.999633790000075, 0],
            [109.00004999100008, 22.999635879000039, 0],
            [109.00004577600004, 22.999633789000029, 0],
            [108.99980896100004, 22.999783316000048, 0]
          ]
        ]
      },
      "properties": {
        "OBJECTID": 1,
        "Name": "010101002.01.韦x圆.45130210120000142300",
        "Shape_Length": 0.0019098079207306106,
        "Shape_Area": 1.633144971052641e-7,
        "MJ": 1854.2365449356753
      }
    },
    {
      "type": "Feature",
      "id": 2,
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          [
            [109.00004999100008, 22.999635879000039, 0],
            [109.00051116900005, 22.999864578000029, 0],
            [109.00002288800005, 23.000301361000027, 0],
            [108.99945068400007, 23.000009537000039, 0],
            [108.99980896100004, 22.999783316000048, 0],
            [109.00004577600004, 22.999633789000029, 0],
            [109.00004999100008, 22.999635879000039, 0]
          ]
        ]
      },
      "properties": {
        "OBJECTID": 2,
        "Name": "010101002.02.韦x圆.45130210120000142200",
        "Shape_Length": 0.0025207201232059599,
        "Shape_Area": 3.5231640810777823e-7,
        "MJ": 4000.1159183494574
      }
    },
    {
      "type": "Feature",
      "id": 3,
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          [
            [109.31761472400007, 23.949700621000034, 0],
            [109.31761932400008, 23.949712753000028, 0],
            [109.31747588000007, 23.949779424000042, 0],
            [109.31707763700007, 23.949964523000062, 0],
            [109.31696319600007, 23.949409485000047, 0],
            [109.31746673600009, 23.949310303000061, 0],
            [109.31761472400007, 23.949700621000034, 0]
          ]
        ]
      },
      "properties": {
        "OBJECTID": 3,
        "Name": "010101034.03.覃x琼.45130210120000117200",
        "Shape_Length": 0.0021076721802698456,
        "Shape_Area": 2.7362659070145457e-7,
        "MJ": 3084.9086846522196
      }
    },
    {
      "type": "Feature",
      "id": 4,
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          [
            [109.32078552200005, 23.949838638000074, 0],
            [109.32067871100008, 23.950061798000036, 0],
            [109.32040405300006, 23.950031281000065, 0],
            [109.31993103000008, 23.949953079000068, 0],
            [109.31998443600008, 23.949731827000051, 0],
            [109.32007598900009, 23.949575424000045, 0],
            [109.32038116500007, 23.949661255000024, 0],
            [109.32078552200005, 23.949838638000074, 0]
          ]
        ]
      },
      "properties": {
        "OBJECTID": 4,
        "Name": "010101155.01.韦x蕊.45130210120000147800",
        "Shape_Length": 0.002170601077130315,
        "Shape_Area": 2.6147622846426089e-7,
        "MJ": 2947.9183812390702
      }
    },
    {
      "type": "Feature",
      "id": 650,
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          [
            [109.30503082300004, 23.985090256000035, 0],
            [109.30485641000007, 23.985118287000034, 0],
            [109.30485190600007, 23.985119011000052, 0],
            [109.30438995400004, 23.985193253000034, 0],
            [109.30430603100007, 23.984498978000033, 0],
            [109.30496978800005, 23.984447479000039, 0],
            [109.30503082300004, 23.985090256000035, 0]
          ]
        ]
      },
      "properties": {
        "OBJECTID": 650,
        "Name": "010101487.09.黄x达.45130210120000127400",
        "Shape_Length": 0.0026598417730435632,
        "Shape_Area": 4.4168718365440911e-7,
        "MJ": 4978.320637123189
      }
    }
   ]
}

3.在地块上批量添加地块,将地块数据转换成高德坐标之后,调用addpolygon方法开始画出地块;

如果只需要画1个地块,可以跳过这个方法,直接看四。


// 将GPS 84转换成高德坐标
const TransformationData = (data:any, year :any , color:any) => {

    new amap.GeoJSON({

        geoJSON: data,//这里是 geojson数据
        // 还可以自定义getMarker和getPolyline
        getPolygon: function (geojson:any, lnglats:any) {
            // 计算面积
            // var area = amap.GeometryUtil.ringArea(lnglats[0])
            
            // 用convertFrom函数,将gps 84 转高德  gcj20坐标系
            //lnglats[0] 是要转换的坐标
            amap.convertFrom(lnglats[0], "gps", function(status:any, result:any) { 
                //转换成功
                if (result.info === 'ok') {   
                    var path2 = result.locations //转换好的坐标
                    // 添加覆盖物
                    addpolygon(path2,color,year,geojson.properties)//坐标,颜色,年,其他属性

                }
            })
        }
    });
}


4.我这里定义一个polygonobj对象用来装入年和地块对象。用于区分各个年份的地块,当然你们也可以用其他类型来处理。
画完地块之后,我们对地块添加一个点击事件,用于绑定自定义属性,点击地块之后能够显示其相关信息数据。

var polygonarr = []
var polygonobj = (null)
var infoWindow=(null)
// 添加覆盖物
const addpolygon=(path2:any,color:any,year:any,properties:any)=>{
    // console.log(properties)
    polygonobj={
        "id":year,
        "polygondata":new amap.Polygon({ //添加多边形覆盖物,设置opts属性
            path: path2,//坐标,这里必须是首位相同的坐标点,才能够形成一个闭合的包围
            // fillOpacity: 1 - Math.sqrt(area / 8000000000),// 面积越大透明度越高
            fillOpacity:0.5,
            strokeColor: 'white',//线条颜色
            fillColor: color,//多边形填充颜色
            height: 0,  //是否离地绘制,默认值为0.0,等于0时贴地绘制。
            strokeWeight : 1,//轮廓线宽度
            strokeStyle: "dashed", // 轮廓线样式,实线:solid,虚线:dashed 
            strokeOpacity: 0.75, //轮廓线透明度,取值范围 [0,1] ,0表示完全透明,1表示不透明。默认为0.9
            draggable : false, //设置多边形是否可拖拽移动,默认为false
            strokeDasharray: [5, 5], //勾勒形状轮廓的虚线和间隙的样式
            extData:{//用户自定义属性,支持JavaScript API任意数据类型,如Polygon的id等
                "Name":properties.Name,
                "MJ":properties.MJ,
                "OBJECTID":properties.OBJECTID,
                "Shape_Area":properties.Shape_Area,
                "Shape_Length":properties.Shape_Length,
            },
        })
    }

    //绑定点击事件
    polygonobj.polygondata.on('click', (e:any) => {
        // console.log(e.target._opts.extData)'
        var extresult_name = e.target._opts.extData.Name.split('.')
        infoWindow = new amap.InfoWindow({
            closeWhenClickMap:true,
            content: "地块信息<hr /><Br>代码:"+extresult_name[0]+"<Br>地块序号:"+extresult_name[1]+"<Br>名字:"+extresult_name[2]+"<Br>地块编号:"+extresult_name[3]+"<Br>地块面积:"+(e.target._opts.extData.MJ).toFixed(2)+"平方米"
        })
        infoWindow.open(map, e.lnglat);
    })

    //触碰覆盖物
    // polygonobj.polygondata.on('mouseover', () => {
    //     polygon2.setOptions({
    //         fillOpacity: 0.7,
    //         fillColor: '#7bccc4'
    //     })
    // })

    //离开覆盖物
    // polygonobj.polygondata.on('mouseout', () => {
    //     polygon2.setOptions({
    //         fillOpacity: 0.5,
    //         fillColor: '#ccebc5'
    //     })
    // })

    polygonarr.push(polygonobj) // 把地块对象放进数组里面,方便后面循环读取展示。
    map.add(polygonobj.polygondata); //添加地块
    
}

最后在这里放我这边的完整代码

<template>
     <div id="container"></div>
     <div class="state-text" >{{texta}}</div>
     <div class="Console">
        <h5>控制台</h5>
        <hr>
        <div class="Console_list">
            <ul>
                <li><span></span> <el-checkbox v-model="checked1" @change="GetMassif" true-label="2022,#ff2dc6,1" false-label="2022,#ff2dc6,0" label="2022年" size="large" /></li>
                <li><span></span> <el-checkbox v-model="checked1" @change="GetMassif" true-label="2021,#1549cf,1" false-label="2021,#1549cf,0" label="2021年" size="large" /></li>
                <li><span></span> <el-checkbox v-model="checked1" @change="GetMassif" true-label="2020,#e14915,1" false-label="2020,#e14915,0" label="2020年" size="large" /></li>
            </ul>
        </div>
     </div>
</template>

<script setup lang='ts'>
import { onMounted, reactive, ref } from 'vue';
import {ElCheckbox} from "element-plus"
import { shallowRef } from '@vue/reactivity'
import AMapLoader from '@amap/amap-jsapi-loader';
import axios from 'axios';


onMounted(() => {
    initMap()
})

var texta = ref()
var map  = shallowRef(null);
var amap = (null);
var dataarr = []
var datalt = {}
var polygonarr = []
var polygonobj = (null)

var infoWindow=(null)

//加载地图
const initMap = () => {
    AMapLoader.load({
        key:"你的key",             // 申请好的Web端开发者Key,首次调用 load 时必填
        version:"2.0",      // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
        plugins:[
            "AMap.Scale", //工具条,控制地图的缩放、平移等
            "AMap.ToolBar", //比例尺,显示当前地图中心的比例尺
            // "AMap.Geolocation", //定位,提供了获取用户当前准确位置、所在城市的方法
            "AMap.HawkEye", //鹰眼,显示缩略图
            "AMap.GeoJSON", //GeoJSON
            "AMap.convertFrom", //坐标系转换
        ],       // 需要使用的的插件列表,如比例尺'AMap.Scale'等
    }).then((AMap)=>{
        amap = AMap
        map = new AMap.Map("container",{  //设置地图容器id
            viewMode:"2D",    //是否为3D地图模式
            zooms:[6,16.7],
            zoom:15,           //初始化地图级别
            center:[109.314545,23.964934], //初始化地图中心点位置
            mapStyle: 'amap://styles/whitesmoke', //设置地图的显示样式
            layers: [
                new AMap.TileLayer.Satellite(),
                new AMap.TileLayer.RoadNet({
                    opacity:0.5
                }),
            ],//地图图层
            
        });

        map.addControl(new AMap.Scale()); //异步同时加载多个插件
        map.addControl(new AMap.ToolBar());
        
        let HawkEye = new AMap.HawkEye({
            position: "LT", //控件停靠位置(LT/RT/LB/RB)
        });
        map.addControl(HawkEye);
        
        map.on('mousemove',showInfoMove)

    }).catch(e=>{
        console.log(e);
    })
}
//移动鼠标事件
const showInfoMove = (e) =>{
    texta.value = '当前经纬度:'+e.lnglat.getLng()+','+e.lnglat.getLat()
}

//读取geojson数据
const getdata = (year :any,color:any) =>{
    axios({
        method: 'get',
        url: 'public/data/dk'+year+'.json',
    }).then((res) => {

        datalt={
            "year":year,
            "data":res.data
        }
        dataarr.push(datalt)
        
        // 转换数据
        TransformationData(res.data,year,color)
        console.log('GeoJSON 数据加载完成')
    }).catch((msg) => {
        console.log("msg", msg)
        console.log('GeoJSON 服务请求失败')
    })

}

// 将GPS 84转换成高德坐标
const TransformationData = (data:any, year :any , color:any) => {

    new amap.GeoJSON({

        geoJSON: data,
        // 还可以自定义getMarker和getPolyline
        getPolygon: function (geojson:any, lnglats:any) {
            // 计算面积
            // var area = amap.GeometryUtil.ringArea(lnglats[0])
            // gps 84 转高德  gcj20坐标系
            // console.log(geojson.properties)

            amap.convertFrom(lnglats[0], "gps", function(status:any, result:any) { 
                
                if (result.info === 'ok') {   
                    
                    var path2 = result.locations
                    // 添加覆盖物
                    addpolygon(path2,color,year,geojson.properties)//坐标,颜色,年,其他属性

                }
            })
        }
    });
}

// 添加覆盖物
const addpolygon=(path2:any,color:any,year:any,properties:any)=>{
    // console.log(properties)
    polygonobj={
        "id":year,
        "polygondata":new amap.Polygon({
            path: path2,
            // fillOpacity: 1 - Math.sqrt(area / 8000000000),// 面积越大透明度越高
            fillOpacity:0.5,
            strokeColor: 'white',//线条颜色
            fillColor: color,//多边形填充颜色
            height: 0,  //是否离地绘制,默认值为0.0,等于0时贴地绘制。
            strokeWeight : 1,//轮廓线宽度
            strokeStyle: "dashed", // 轮廓线样式,实线:solid,虚线:dashed 
            strokeOpacity: 0.75, //轮廓线透明度,取值范围 [0,1] ,0表示完全透明,1表示不透明。默认为0.9
            draggable : false, //设置多边形是否可拖拽移动,默认为false
            strokeDasharray: [5, 5], //勾勒形状轮廓的虚线和间隙的样式
            extData:{//用户自定义属性,支持JavaScript API任意数据类型,如Polygon的id等
                "Name":properties.Name,
                "MJ":properties.MJ,
                "OBJECTID":properties.OBJECTID,
                "Shape_Area":properties.Shape_Area,
                "Shape_Length":properties.Shape_Length,
            },
        })
    }

    //绑定点击事件
    polygonobj.polygondata.on('click', (e:any) => {
        // console.log(e.target._opts.extData)'
        var extresult_name = e.target._opts.extData.Name.split('.')
        infoWindow = new amap.InfoWindow({
            closeWhenClickMap:true,
            content: "地块信息<hr /><Br>代码:"+extresult_name[0]+"<Br>地块序号:"+extresult_name[1]+"<Br>名字:"+extresult_name[2]+"<Br>地块编号:"+extresult_name[3]+"<Br>地块面积:"+(e.target._opts.extData.MJ).toFixed(2)+"平方米"
        })
        infoWindow.open(map, e.lnglat);
    })

    //触碰覆盖物
    // polygonobj.polygondata.on('mouseover', () => {
    //     polygon2.setOptions({
    //         fillOpacity: 0.7,
    //         fillColor: '#7bccc4'
    //     })
    // })

    //离开覆盖物
    // polygonobj.polygondata.on('mouseout', () => {
    //     polygon2.setOptions({
    //         fillOpacity: 0.5,
    //         fillColor: '#ccebc5'
    //     })
    // })

    polygonarr.push(polygonobj)
    map.add(polygonobj.polygondata); 
    
}

//隐藏覆盖物
const hidepolygon = (year:any)=>{
    polygonarr.forEach(element => {
        
        if (element.id == year){
            element.polygondata.hide()
        }
    });
}
//显示
const showpolygon = (year:any)=>{
    polygonarr.forEach(element => {
        if (element.id == year){
            element.polygondata.show()
        }
    })
}

var checkobj ={}
const GetMassif = (aa:any) => {
    
    var checkarr = [] // 年,颜色,当前状态,是否加载
    checkarr= aa.split(',')
    if (checkobj[checkarr[0]]){
        
        // 判断状态
        if (checkarr[2]==1){
            showpolygon(checkarr[0])
        }else{
            hidepolygon(checkarr[0])
        }
        
    }else{

        checkarr.push("1")//存入第四个参数,是否加载
        checkobj[checkarr[0]]= checkarr
        //判断状态
        if (checkarr[2]==1){
            getdata(checkarr[0],checkarr[1]) //首次加载数据
        }

    }
    
}

</script>

<style  scoped>
    #container{
        padding:0px;
        margin: 0px;
        width: 100%;
        height: 100vh;
    }
    .state-text{
        padding: 0.75rem 1.25rem;
        margin-bottom: 1rem;
        border-radius: 0.25rem;
        position: fixed;
        top: 1rem;
        background-color: white;
        width: auto;
        min-width: 22rem;
        border-width: 0;
        right: 1rem;
        box-shadow: 0 2px 6px 0 rgb(114 124 245 / 50%);
    }
    .Console {
        padding: 0.75rem 1.25rem;
        margin-bottom: 1rem;
        border-radius: 0.25rem;
        position: fixed;
        top: calc( 1rem + 4rem);
        background-color: white;
        width: auto;
        min-width: 11rem;
        border-width: 0;
        right: 1rem;
        box-shadow: 0 2px 6px 0 rgb(114 124 245 / 50%);
    }
    .Console_list li{
        list-style: none;
        line-height: 28px;
    }
    .Console_list li:nth-child(1) span {
        display: inline-block;
        width: 12px;
        height: 12px;
        background-color: #ff2dc6;
    }
    .Console_list li:nth-child(2) span{
        display: inline-block;
        width: 12px;
        height: 12px;
        background-color: #1549cf;
    }
    .Console_list li:nth-child(3) span {
        display: inline-block;
        width: 12px;
        height: 12px;
        background-color: #e14915;
    }
</style>

第一次在CSDN写文章,希望能帮到大家。

如果觉得有用请给我点个赞。

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐