uniapp使用地图开发app, renderjs使用方法及注意事项

上次提到uniapp开发地图app时得一些问题,最后提到使用renderjs实现app中使用任何地图(下面将以腾讯地图为例,uniapp中写app时推荐使用得是高德地图,无法使用腾讯地图(renderjs方式除外))。

1、renderjs介绍,这里直接参照uniapp开发官网介绍即可:renderjs | uni-app官网

官网也有示例,示例是使用echart得,不过使用方法和地图相类似。

下面先看一下demo效果:

这是一个app中使用地图得makers,点击单个makers会显示对应得图片在上面,并且点击得maker会被放大,这个功能使用uniapp得map组件时是会有很大得问题得,再次就不再赘述。下面看看代码实现。

1、先来看看整个页面得组成(文章最后附上相关示例代码):

从上面可以看到script标签有两个,一个是普通得script标签,另一个是lang="renderjs"得标签。

2、注意事项:上面提到得renderjs中,module得名字需要和template上得标签名称一致,如图:

mapModule.update中update是该模块下面得一个方法。

3、接下来介绍一下

html 复制代码
<view class="curr" id="container" :prop="mapModel" :change:prop="mapModule.update"></view>

改代码,mapModel为script普通标签里面得一个响应式变量

:change:prop="mapModule.update" 含义,当script里面得mapModel数据发生变化时,会通过该处触发renderjs里面得update方法。

4、renderjs中不能使用http请求,相关请求只能放在普通标签里面,renderjs仅根据数据变化做逻辑处理(可以理解为一个子组件)

5、最后附上相关代码(mapDemo.vue):

javascript 复制代码
<template>
	<view class="index-wrap">
		<view class="curr-position" @click="mapModule.setPosition">
			<image src="../../static/mapImg/5.png"></image>
		</view>
		<view class="curr" id="container" :prop="mapModel" :change:prop="mapModule.update"></view>
	</view>
</template>

<script>
export default {
	components: { IndexTabs, UpdateApp },
	data() {
		return {
			showMenu: false,
			id: 0, // 使用 marker点击事件 需要填写id
			mapModel: {}
		};
	},
	computed: {

		getShow() {
			if (this.showMenu) {
				return true;
			} else {
				const timer = setTimeout(() => {
					clearTimeout(timer);
					return false;
				}, 3000)
			}
		}
	},
	
	methods: {

		init() {
			this.mapModel = {
				markerLatlng: [{ lat: 40.77460069719003, lng: 114.8868407358159 },
				{ lat: 40.7746130606868, lng: 114.88729786752276 },
				{ lat: 40.7746130606868, lng: 114.88739786752276 },
				{ lat: 40.77465839357235, lng: 114.88736317180303 },]
			}
		}
	}

};
</script>

<script module="mapModule" lang="renderjs">
	import {
		initScript,
		getMap,
		getLatLng,
		getMultiMarker,
		getGeometriesItem,
		getFitBounds
	} from '../../utils/tmap';
	import {getPosition} from '../../utils/utils';
	export default {
		data() {
			return {
				ownerInstance: null,  
				map: null,
				center: null,
				marker: null,
				infoWindow: null,
				currPosition: {},
				mapModel: {},
			};
		},
		methods: {
			async setPosition(){
				this.currPosition = await getPosition()
				this.center = getLatLng(this.currPosition.lat, this.currPosition.lng)
				this.map.setCenter(this.center)
			},
			init(){
				this.ownerInstance.ownerInstance('init')
			},
			async refresh() {
				
				// 待处理
				if(this.mapModel.markerLatlng.length){
					const first = this.mapModel.markerLatlng[0]
					this.center = getLatLng(first.lat, first.lng)
				}
				
				if(this.map){
					getFitBounds(this.map, this.mapModel.markerLatlng)
				}else{
					this.map = getMap(this.center);
				}
				getFitBounds(this.map, this.mapModel.markerLatlng, 0.2)
				this.marker = getMultiMarker(this.map, this.mapModel.markerLatlng.map((item, index )=> getGeometriesItem(item, 'marker'+index)))
				
				this.marker.on('click', this.onMarker)
				
			},
			onMarker(e){
				const markers = this.marker.geometries.map(item => item.id === e.geometry.id ? {...item, styleId: 'currMarker'} : {...item, styleId: 'marker'})
				this.marker.updateGeometries(markers)
				this.dealInfoWindow(e.geometry.position)
			},
			dealInfoWindow(center){
				if(this.infoWindow){
					this.infoWindow.close()
				}
				this.infoWindow = new TMap.InfoWindow({
					map: this.map,
					position: center,
					offset: {x: 0, y: -80},
					content: "<div><img src='https://mapapi.qq.com/web/lbs/javascriptGL/demo/img/em.jpg'></div>"
				});
			},
			update(newValue, _, ownerInstance) {
				this.mapModel = newValue
				if (this.ownerInstance) {
					this.refresh()
				} else {
					this.ownerInstance = ownerInstance;
					initScript(this.init)
				}
			}
		}

	};
</script>

<style lang="scss" scoped>
.index-wrap {
	height: 100vh;
	width: 100%;
	display: flex;
	flex-direction: column;
	justify-content: center;

	.curr-position {
		position: fixed;
		bottom: 340rpx;
		right: 32rpx;
		z-index: 1001;
		display: flex;
		justify-content: center;
		align-items: center;
		background: #fff;
		border-radius: 12rpx;
		height: 80rpx;
		width: 80rpx;

		image {
			display: inline-block;
			width: 48rpx;
			height: 48rpx;
		}
	}

	.curr {
		display: flex;
		justify-content: center;
		align-items: center;
		flex: 1;
	}

	.map-container {
		flex: 1;
		width: 100%;
		height: 100%;
		z-index: 100;
		display: block;

		// transition: all 0 ease-in-out 0;
		&.active {
			display: none;
			// transition: all 0 ease-in-out 0.3s;
		}

		// margin-top: 200rpx;
	}
}
</style>

下面时renderjs中引入得utils.js和tmap.js:

utils.js

javascript 复制代码
/**
 * @description 通过uni.getLocation获取相关地理信息
 * @returns
 */
export function getPosition() {
  return new Promise((resolve) => {
    uni.getLocation({
      type: "gcj02",//"wgs84",
      geocode: true,
      timeout: 6,
      fail: () => {
        resolve({ ...getLocationLatLng(), errMsg: "getLocation:fail" });
      },
      success: (res) => {
        const {province, city, district, street, streetNum, poiName} = res.address
        const params = {
          ...res,
          latitude: res.latitude,
          longitude: res.longitude,
          address_info: `${province}${city}${district}${street}${streetNum}`,
          address: poiName,
        };
        uni.setStorageSync("LatLng", JSON.stringify(res));
        resolve(params);
      },
    });
    const timer = setTimeout(() => {
      clearTimeout(timer);
      resolve({ ...getLocationLatLng(), errMsg: "getLocation:fail" });
    }, 1000);
  });
}

tmap.js: (key值需要替换成你自己项目中地图的key)

javascript 复制代码
import {icon1} from './mapIcon'
const key = '此处为你申请的腾讯地图得key'


export function getLocation() {
    return new TMap.maps.Geolocation(key, "腾讯地图API示例")
}

export function initScript(callback) {
    var script = document.createElement("script");
    script.type = "text/javascript";
    script.src = "https://map.qq.com/api/gljs?v=1.exp&key=" + key;
    // script.src = "https://map.qq.com/api/js?v=2.exp&key=";
    document.body.appendChild(script);
    script.onload = () => {
        callback()
    }
}

export function getMap(center, id, zoom = 15) {
    return new TMap.Map(document.getElementById(id || 'container'), {
        center,//设置地图中心点坐标
        zoom,   //设置地图缩放级别
        showControl: false,
    })
}

/**
 * 
 * @param {Number} lat 经度
 * @param {Number} lng 维度
 * @returns 
 */
export function getLatLng(lat, lng) {
    return new TMap.LatLng(lat, lng);
}

/**
 * @description 获取路径数组
 * @param {Array} pathList 经纬度数组 
 * @returns 
 */
export function getPath(pathList) {
    return pathList.map(item => getLatLng(item.lat, item.lng));
}

/**
 * @description 地图设置会放路径
 * @param {Object} map 地图对象 
 * @param {Array} pathList 路径数组 
 * @returns 
 */

export function getPolylineLayer(map, pathList) {
    return new TMap.MultiPolyline({
        map, // 绘制到目标地图
        // 折线样式定义
        styles: {
            style_blue: new TMap.PolylineStyle({
                color: '#3777FF', // 线填充色
                width: 4, // 折线宽度
                borderWidth: 2, // 边线宽度
                borderColor: '#FFF', // 边线颜色
                lineCap: 'round', // 线端头方式
                eraseColor: 'rgba(190,188,188,1)',
            }),
        },
        geometries: [
            {
                id: 'erasePath',
                styleId: 'style_blue',
                paths: getPath(pathList),
            },
        ],
    })
}

/**
 * 
 * @param {Object} LatLng 经纬度对象{lat,lng} 
 * @param {String} id  标注点Id
 * @param {String} styleId 样式id
 * @returns 
 */
export function getGeometriesItem(LatLng, id, styleId = 'marker') {
    return { //点标注数据数组
        id,
        styleId,
        "position": getLatLng(LatLng.lat, LatLng.lng),
        // "properties": {
        //     "title": "marker"
        // }
    }
}

export function getMarkerUrlByType(type) {
    return 'static/mapImg/marker.png'
}

export function getMarkerStyle(key, src, width = 70, height = 70) {
    return {
        [key]: new TMap.MarkerStyle({
            width,
            height,
            src,
        })
    }
}

export function getMultiMarker(map, geometries) {
    return new TMap.MultiMarker({
        id: "marker-layer", //图层id
        map,
        styles: { //点标注的相关样式
            ...getMarkerStyle('marker', icon1),
            ...getMarkerStyle('currMarker', icon1, 90, 90),
            'car': new TMap.MarkerStyle({
                width: 40,
                height: 40,
                anchor: {
                    x: 20,
                    y: 20,
                },
                faceTo: 'map',
                rotate: 180,
                src: icon1
                // src: 'https://mapapi.qq.com/web/lbs/javascriptGL/demo/img/car.png',
            })
        },
        geometries
    });
}

function getfitBoundItemNum(base, add){
  return base + add
}

/**
 * 
 * @param {Object} map 地图对象 
 * @param {Array} latlngList 坐标点集合,示例:[{lat: 0, lng: 0}] 
 */
export function getFitBounds(map, latlngList, scale = 1) {
    let latlist = []
    let lnglist = []
    latlngList.forEach(item => {
        latlist.push(item.lat)
        lnglist.push(item.lng)
    })
    const latMax = Math.max(...latlist) 
    const latMin = Math.min(...latlist) 
    const lngMax = Math.max(...lnglist) 
    const lngMin = Math.min(...lnglist)
    const latDiff = (latMax - latMin) * scale
    const lngDiff = (lngMax - lngMin) * scale
    const ne = getLatLng(getfitBoundItemNum(latMax, latDiff), getfitBoundItemNum(lngMax, lngDiff))
    const sw = getLatLng(getfitBoundItemNum(latMin, -latDiff*2.5), getfitBoundItemNum(lngMin, -lngDiff))
    const latLngBounds = new TMap.LatLngBounds(sw, ne)
    map.fitBounds(latLngBounds); //根据指定的范围调整地图视野
}

mapIcon.js(图片base64字符串),注意:腾讯地图中图片地址必须是绝对地址,如果你们可以使用相对地址,欢迎留言讨论:

javascript 复制代码
export const icon1 = `data:image/png;base64,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`
相关推荐
一个处女座的程序猿O(∩_∩)O2 小时前
小型 Vue 项目,该不该用 Pinia 、Vuex呢?
前端·javascript·vue.js
hackeroink5 小时前
【2024版】最新推荐好用的XSS漏洞扫描利用工具_xss扫描工具
前端·xss
迷雾漫步者6 小时前
Flutter组件————FloatingActionButton
前端·flutter·dart
向前看-7 小时前
验证码机制
前端·后端
燃先生._.8 小时前
Day-03 Vue(生命周期、生命周期钩子八个函数、工程化开发和脚手架、组件化开发、根组件、局部注册和全局注册的步骤)
前端·javascript·vue.js
高山我梦口香糖9 小时前
[react]searchParams转普通对象
开发语言·前端·javascript
m0_748235249 小时前
前端实现获取后端返回的文件流并下载
前端·状态模式
m0_7482402510 小时前
前端如何检测用户登录状态是否过期
前端
black^sugar10 小时前
纯前端实现更新检测
开发语言·前端·javascript