2024/08/13更新:使用原生天地图开发更推荐leaflet+天地图,leaflet hooks封装地址:【天地图】VUE3基于Leaflet.js部分功能hooks封装useLeafletMap.js-CSDN博客

仅根据个人习惯封装,仅供参考。

天地图API地址:http://lbs.tianditu.gov.cn/api/js4.0/class.html

该hooks除了需引入天地图外,还需引入开源库图片覆盖物!!!开源库地址:http://lbs.tianditu.gov.cn/api/js4.0/opensource/source.html

各方法详细说明在代码里体现,首先创建一个hooks——useTdtMap.js

/**
 * useTdtMap(天地图hooks)
 * params:
 *  id: 天地图绑定的html标签id,具有唯一性
 */
import { createVNode, render } from 'vue'

export const useTdtMap = (id) => {
	let map = null // 地图对象

	// 地图初始化,请根据个人情况自行配置地图初始化操作
	const mapInit = () => {
		map = new T.Map(id)
		// 设置地图中心点坐标及地图级别
		map.centerAndZoom(new T.LngLat(116.40769, 39.89945), 12)
		//创建对象
		map.disableDoubleClickZoom() // 禁止双击放大地图
		// 设置底色
		map.setStyle('indigo')
		document.getElementsByClassName('tdt-control-copyright tdt-control')[0].style.display = 'none' // 去除天地图logo
		return Promise.resolve() // 回调地图初始化完成
	}

    /**
     * setMapCenter(地图平移)
     * params:
     *  coordinate: 中心点经纬度
     *  格式:'lng,lat'
     *  示例:'116.40769,39.89945'
     *  以下coordinate格式同该格式一致
     */
	const setMapCenter = (coordinate) => {
		let lng = coordinate.split(',')[0]
		let lat = coordinate.split(',')[1]
		map.panTo(new T.LngLat(lng, lat))
	}

	// 地图缩放 coordinate:同上 zoom:比例尺级别
	const setMapScale = (coordinate, zoom) => {
		let lng = coordinate.split(',')[0]
		let lat = coordinate.split(',')[1]
		map.centerAndZoom(new T.LngLat(lng, lat), zoom)
	}

	// 地图显示范围 coordinate1:范围点位1 coordinate2:范围点位2
	const setMapBounds = (coordinate1, coordinate2) => {
		let lng1 = coordinate1.split(',')[0]
		let lat1 = coordinate1.split(',')[1]
		let lng2 = coordinate2.split(',')[0]
		let lat2 = coordinate2.split(',')[1]
		map.setMaxBounds(new T.LngLatBounds(new T.LngLat(lng1, lat1), new T.LngLat(lng2, lat2)))
	}

	// 地图设置显示级别
	const setZoomLevels = (minLevels = 1, maxLevels = 18) => {
		map.setMinZoom(minLevels)
		map.setMaxZoom(maxLevels)
	}

	/**
	 * 添加图片覆盖物类
	 * params:
	 *  coordinate1: 经纬度 格式:'lng,lat'
	 *  coordinate2: 经纬度 格式:'lng,lat'
	 *  imgUrl: 点位显示图标
	 *  option: 图片覆盖物属性,{ opacity: 图片透明度, alt: 如果无法显示图像,浏览器将显示替代文本 }
	 */
	const addMapImgOverLay = (coordinate1, coordinate2, imgUrl, option = {}) => {
		let lng1 = coordinate1.split(',')[0]
		let lat1 = coordinate1.split(',')[1]
		let lng2 = coordinate2.split(',')[0]
		let lat2 = coordinate2.split(',')[1]
		let bd = new T.LngLatBounds(new T.LngLat(lng1, lat1), new T.LngLat(lng2, lat2))
		let img = new T.ImageOverlay(imgUrl, bd, option)
		map.addOverLay(img)
		// return img
	}

	/**
	 * 地图添加自定义点位并返回该点位对象
	 * params:
	 *  coordinate: 经纬度 格式:'lng,lat'
	 *  iconUrl: 点位显示图标
	 *  clickEvent: 监听点击事件回调
	 *  iconOptions: 天地图ICON图标配置
	 *   格式:{
     *     iconSize: '30,30', 图标大小,非必需配置
     *     iconAnchor: '15,30' 图标偏移,非必需配置
     *   }
	 */
	const addMapMarker = (
		coordinate,
		iconUrl = '*',
		clickEvent = null,
		iconOptions = {}
	) => {
		let marker = getMapMarkerObj(coordinate, iconUrl, iconOptions)
		if (clickEvent) {
			marker.addEventListener('click', clickEvent)
		}
		addMapOverLay(marker)
		return marker
	}

	// 生成点标注对象
	const getMapMarkerObj = (coordinate, iconUrl, iconOptions) => {
		let lng = coordinate.split(',')[0]
		let lat = coordinate.split(',')[1]
		const option = {
			iconSize: iconOptions.iconSize || '30,30',
			iconAnchor: iconOptions.iconAnchor || '15,30'
		}
		// 添加点位图标
		let icon = new T.Icon({
			iconUrl: iconUrl,
			iconSize: new T.Point(option.iconSize.split(',')[0], option.iconSize.split(',')[1]),
			iconAnchor: new T.Point(option.iconAnchor.split(',')[0], option.iconAnchor.split(',')[1])
		})
		let marker = new T.Marker(new T.LngLat(lng, lat), { icon: icon })
		return marker
	}

	/**
	 * 地图添加自定义线并返回该线对象
	 * params:
	 *  coordinateList: 线的各点位经纬度数组 格式:[{ lng: 'lng', lat: 'lat' }]
	 *  polylineOption: 线配置项,参考天地图
	 *  clickEvent: 监听点击事件回调
	 */
	const addMapLine = (coordinateList, polylineOption = null, clickEvent = null) => {
		let points = coordinateList.map((item) => {
			return new T.LngLat(item.lng, item.lat)
		})
		let marker = new T.Polyline(points, polylineOption)
		if (clickEvent) {
			marker.addEventListener('click', clickEvent)
		}
		addMapOverLay(marker)
		return marker
	}

	/**
	 * 地图添加自定义面并返回该线对象
	 * params:
	 *  coordinateList: 面的各点位经纬度数组 格式:[[{ lng: 'lng', lat: 'lat' }], [{ lng: 'lng', lat: 'lat' }]]
	 *  格式说明:处理面内环情况 外环位置是逆时针定义 内环位置值是顺时针定义
	 *  polylineOption: 面配置项,参考天地图
	 *  clickEvent: 监听点击事件回调
	 */
	const addMapPolygon = (coordinateList, polygonOption = null, clickEvent = null) => {
		let polygon = coordinateList.map((item) => {
			return item.map((pointItem) => {
				return new T.LngLat(pointItem.lng, pointItem.lat)
			})
		})
		let marker = new T.Polygon(polygon, polygonOption)
		if (clickEvent) {
			marker.addEventListener('click', clickEvent)
		}
		addMapOverLay(marker)
		return marker
	}

	/**
	 * 地图添加自定义窗口并返回窗口对象
	 * params:
	 *  coordinate: 信息窗口经纬度 格式:'lng,lat'
	 *  infoWindowOption: 信息窗口配置项
	 *  template: 自定义模板组件
	 *  params: 传入组件自定义参数
	 *  clickEvent: 监听点击事件回调
	 */
	const addMapInfoWindow = (coordinate, infoWindowOption, template, params, clickEvent = null) => {
		// 创建虚拟节点并传参
		const infoWindowContent = getTemplateNode(template, params)
		// 监听组件自定义handleClick事件
		clickEvent && infoWindowContent.el.addEventListener('click', clickEvent)
		// 创建天地图信息窗口 infoWindowContent.el:test模板dom
		let infoWindow = getInfoWindowObj(infoWindowContent.el, coordinate, infoWindowOption)
		// 地图添加信息窗口
		addMapOverLay(infoWindow)
		return infoWindow
	}

	/**
	 * 生成一个模板节点并传参
	 * params:
	 *  template: 自定义模板组件
	 *  params: 传入组件自定义参数
	 */
	const getTemplateNode = (template, params) => {
		// 创建虚拟节点并传参
		const infoWindowContent = createVNode(template, params)
		let node = document.createElement('div') // 创建一个div节点
		render(infoWindowContent, node) // 实例组件挂载到node节点上
		return infoWindowContent
	}

	// 生成信息窗口对象
	const getInfoWindowObj = (el, coordinate, infoWindowOption) => {
		let lng = coordinate.split(',')[0]
		let lat = coordinate.split(',')[1]
		let infoWindow = new T.InfoWindow(el, infoWindowOption)
		// 设置信息窗口经纬度
		infoWindow.setLngLat(new T.LngLat(lng, lat))
		return infoWindow
	}

	// 地图添加覆盖物 obj: 覆盖物对象
	const addMapOverLay = (obj) => {
		map.addOverLay(obj)
	}

	// 地图移除覆盖物 obj: 覆盖物对象
	const removeMapOverLay = (obj) => {
		map.removeOverLay(obj)
	}

	// 地图移除所有覆盖物
	const removeMapAllOverLay = () => {
		map.clearOverLays()
	}

	return {
		mapInit,
		setMapCenter,
		setMapScale,
		setMapBounds,
		setZoomLevels,
		addMapImgOverLay,
		addMapMarker,
		addMapLine,
		addMapPolygon,
		addMapInfoWindow,
		addMapOverLay,
		removeMapOverLay,
		removeMapAllOverLay
	}
}

引入天地图hooks并初始化地图,以下都为部分关键代码

<template>
    <div id="TdtMap" class="map-div"></div>
</template>
<script setup>
    import { useTdtMap } from '@/hooks/useTdtMap'
    // 引入
	const {
		mapInit,
		renderArea,
		setMapCenter,
		setMapScale,
		setMapBounds,
		setZoomLevels,
		addMapImgOverLay,
		addMapMarker,
		addMapLine,
		addMapPolygon,
		addMapInfoWindow,
		addMapOverLay,
		removeMapOverLay,
		removeMapAllOverLay
	} = useTdtMap('TdtMap')
    // 初始化地图
    onMounted(() => {
        mapInit().then(() => {
            // 地图初始化完毕后回调操作
        })
    })
</script>
<style scoped>
    .map-div {
        width: 100vw;
        height: 100vh;
    }
</style>

setMapCenter:手动设置地图平移示例:

setMapCenter('116.40769,39.89945')

setMapScale:手动设置地图中心点及比例尺级别示例:

setMapScale('104.06595,30.57054', 13) // 设置地图缩放

 setMapBounds:手动设置地图显示范围示例:

setMapBounds('103.90114,30.49365', '104.23073,30.64736') // 设置地图显示范围

  setZoomLevels:手动设置地图显示级别示例:

setZoomLevels(12, 18) // 设置地图级别

  addMapImgOverLay:添加地图图片覆盖物示例:

import testImg from '@/assets/image/test.png'
addMapImgOverLay(
    '103.8687,30.72825',
    '104.27167,30.38782',
    testImg,
    {
	    opacity: 100,
		alt: ''
    }
)

  addMapMarker:添加自定义点位并返回该点位对象示例:

import testIcon from '@/assets/image/test.png'
const marker = addMapMarker(
                    '116.40769,39.89945',
                    testIcon ,
                    () => {},
                    {
                        iconSize: '30,30',
                        iconAnchor: '15,30'
                    }
                )

addMapLine:添加自定义线并返回该线对象示例:

const coordinateList = [
    {
        lng: '116.40769',
        lat: '39.89945'
    },
    {
        lng: '116.50769',
        lat: '39.99945'
    },
    {
        lng: '116.60769',
        lat: '39.79945'
    },
    {
        lng: '116.70769',
        lat: '39.69945'
    },
    {
        lng: '116.80769',
        lat: '39.59945'
    }
]

// 默认线配置
const marker = addMapLine(coordinateList)

addMapPolygon:添加自定义面并返回该面对象示例:

// 蒙层四角 中国四角坐标 外部图层
const smegmaPointList = [
	{
		lng: '73.0',
		lat: '59.0'
	},
	{
		lng: '73.0',
		lat: '3.0'
	},
	{
		lng: '136.0',
		lat: '3.0'
	},
	{
		lng: '136.0',
		lat: '59.0'
	},
	{
		lng: '73.0',
		lat: '59.0'
	}
]
// 区域范围
const mapCoordinateData = [
	{
		lng: '104.0325',
		lat: '30.56888'
	},
	{
		lng: '104.04353',
		lat: '30.56795'
	},
	{
		lng: '104.04375',
		lat: '30.53942'
	},
	{
		lng: '104.02315',
		lat: '30.53931'
	},
	{
		lng: '104.02164',
		lat: '30.54504'
	},
	{
		lng: '104.02542',
		lat: '30.55657'
	},
	{
		lng: '104.03053',
		lat: '30.56278'
	},
	{
		lng: '104.0325',
		lat: '30.56888'
	}
]
// 常规画面示例
const marker = addMapPolygon([smegmaPointList])
// 画内环圆示例并配置相关信息
const marker = addMapPolygon(
                    [smegmaPointList, mapCoordinateData],
                    {
	                    color: 'black',
                    	weight: 3,
                    	opacity: 0.2,
	                    fillColor: '#0c2940', // 蒙层颜色
	                    fillOpacity: 0.7 // 透明度
                    },
                    () => {}
                )

addMapInfoWindow:添加自定义信息窗口并返回该窗口对象示例:

// 自定义模块test @/components/test/index.vue
<template>
    <div>{{ title }}</div>
<template>

<scropt>
    defineProps({
        title: {
            type: String,
            default: ''
        }
    })
</scropt>

// 自定义信息窗口 关键代码
import TestTemplate from '@/components/test/index.vue'

const infoWindowOption = {
    closeButton: false, // 关闭天地图弹框默认关闭图标
    offset: new T.Point(0, -15)
}
const infoWindow = addMapInfoWindow('116.40769,39.89945', infoWindowOption, TestTemplate, { 
title: '测试文本' })

addMapOverLay:添加覆盖物示例:

addMapOverLay(marker) // marker同上示例

removeMapOverLay:移除覆盖物示例:

removeMapOverLay(marker) // marker同上示例

removeMapAllOverLay:移除天地图所有覆盖物示例:

removeMapAllOverLay()

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐