uniapp——地图

thorui加入自己的理解以及修改。
效果图:
在这里插入图片描述
代码:

<template>
	<view class="maps-container">
		<view class="search-bar">
			<view class="search-bar-form">
				<!-- 第一个显示的输入框 -->
				<view class="search-bar-label" v-show="!inputShowed" @tap="showInput">
					<icon class="icon-search" type="search" :size="16"></icon>
					<view class="search-bar-text">请输入您的目的地</view>
				</view>
				<!-- 点击后出现的第二个输入框 -->
				<view class="search-bar-box">
					<icon class="icon-search-in-box" type="search" :size="16"></icon>
					<input confirm-type="search" class="search-bar-input" placeholder="请输入您的目的地" :value="inputVal" :focus="inputShowed"
					 @confirm="bindInput" @input="inputTyping" />
					 <!-- 取消的叉叉 -->
					<view class="icon-clear" v-if="inputVal" @tap="clearInput">
						<icon type="clear" size="14"></icon>
					</view>
				</view>
			</view>
			<view class="cancel-btn" @tap="hideInput" v-show="inputShowed">取消</view>
		</view>
		
		<map class="tui-map" :latitude="lat" :longitude="lng" :markers="covers" @markertap="marker" :scale="12"></map>
		
		<scroll-view scroll-y class="scrollView" :style="{height:scrollH +'px'}" @scrolltolower="pullUp">
			<view class="tui-list">
				<view class="tui-list-cell" :class="[index==address.length-1?'tui-cell-last':'']" v-for="(item,index) in address"
				 :key="index">
					<view class="addr-title">
						<text>{{item.title}}</text>
					</view>
					<view class="addr-box ">
						<view class="addr-detail ">
							<text class="distance">{{item.distance}}m</text>
							{{item.address}}
						</view>
						<view class="addr-opera ">
							<view class="opera-box " hover-class="tui-opcity" :hover-stay-time="150 " @tap="call " :data-id="item.id" v-if="item.tel">
								<image src="/static/map_image/call.png" class="mini-img"></image>
								<view class="text">打电话</view>
							</view>
							<view class="opera-box " hover-class="tui-opcity" :hover-stay-time="150" @tap="go" :data-id="item.id">
								<image src="/static/map_image/go.png" class="mini-img"></image>
								<view class="text">到这里</view>
							</view>
						</view>
					</view>
				</view>
				<!-- <tui-loadmore :index="3" v-if="loading"></tui-loadmore> -->
			</view>
		</scroll-view>
	</view>
</template>

<script>
	const QQMapWX = require('@/utils/qqmap-wx-jssdk.min.js');
	export default {
		data() {
			return {
				inputShowed: false,
				inputVal: "",
				qqmapsdk: null,
				key: 'W4WBZ-TUD65-IDAIR-QPM36-HMFQ5-CGBZP',
				lat: 22.63137,
				lng: 114.010857,
				// 标记点数组,设置了就能在地图上显示点
				covers: [],
				address: [],
				scrollH: 256,
				pageIndex: 1,
				loading: true,
				pullUpOn: true,
				keywords: ''
			}
		},
		onLoad(options) {
			this.qqmapsdk = new QQMapWX({
				key: this.key
			});
			// 这里可以改成自己想要搜索的值
			this.keywords = options.key || '加油站';
			setTimeout(() => {
				let winHeight = uni.getSystemInfoSync().windowHeight;
				// scrollview的高度,uni.upx2px(1000)越大,高度越小
				// this.scrollH = winHeight - 44 - uni.upx2px(600);
				this.scrollH = winHeight - 44 - uni.upx2px(1000);
				this.getLocation(() => {
					this.getPoiAround(this.keywords)
				});
			}, 300)
		},
		methods: {
			// 去掉前导空格和后导空格。
			trim: function(value) {
				return value ? value.toString().replace(/(^\s*)|(\s*$)/g, "") : value;
			},
			// 显示第二个输入框
			showInput() {				
				this.inputShowed = true
			},
			// 隐藏第二个输入框
			hideInput() {
				this.inputVal = "";
				this.inputShowed = false;
				uni.hideKeyboard(); //强行隐藏键盘
			},
			// 取消的叉叉的事件
			clearInput() {
				this.inputVal = ""
			},
			// 输入一个字符串就会进入这里
			inputTyping: function(e) {				
				this.inputVal = e.detail.value
			},
			getLocation(callback) {
				//当前位置
				const that = this;
				//H5:使用坐标类型为 gcj02 时,需要配置腾讯地图 sdk 信息(manifest.json -> h5)
				uni.getLocation({
					type: 'gcj02',
					altitude: true,
					success(res) {
						that.lat = res.latitude;
						that.lng = res.longitude;
						callback();
					},
					fail(res) {
						callback();
					}
				});
			},
			calculateDistance(to, callback) {
				// let url=`https://apis.map.qq.com/ws/distance/v1/?mode=walking&to=&output=jsonp&key=W4WBZ-TUD65-IDAIR-QPM36-HMFQ5-CGBZP&from=39.901403%2C116.406243`;
				this.qqmapsdk.calculateDistance({
					from: '', //默认当前位置
					to: to,
					success: res => {
						callback && callback(res.result);
					},
					fail: res => {
						callback && callback(false);
					}
				});
			},
			
			getResult(data) {
				let arr = [];
				let addr = [];
				let idx = this.address.length;
				// this.calculateDistance(data, d => {
				// 	if (d) {
				// 		let distanceArr = d.elements || [];
				// 		for (let i = 0, len = data.length; i < len; i++) {
				// 			data[i].distance = distanceArr[i].distance;
				// 		}
				// 	}
				// });

				for (let [index, item] of data.entries()) {
					arr.push({
						id: index + idx,
						latitude: item.location.lat,
						longitude: item.location.lng,
						title: item.title,
						iconPath: "/static/map_image/location.png",
						width: 32,
						height: 32
					});
					let tel = this.trim(item.tel);
					if (~tel.indexOf(';')) {
						tel = tel.split(';')[0];
					}
					addr.push({
						id: index + idx,
						latitude: item.location.lat,
						longitude: item.location.lng,
						title: item.title,
						address: item.address,
						tel: tel,
						distance: item._distance
					});
				}
				this.address = this.address.concat(addr);
				// 标记点数组,设置了就能在地图上显示点
				this.covers = this.covers.concat(arr);
				this.pageIndex++;
				this.loading = false;
				if (data.length < 10) {
					this.pullUpOn = false;
				}

			},
			pullUp() {
				if (!this.pullUpOn || this.loading) return;
				this.loading = true;
				this.getPoiAround(this.keywords)
			},
			// 根据关键字搜索周边符合的地址
			getPoiAround(keywords) {
				//检索周边的POI
				let boundary = `nearby(${this.lat},${this.lng},1000)`;
				
				// #ifdef H5
				//https://lbs.qq.com/service/webService/webServiceGuide/webServiceSearch
				let url =
					`https://apis.map.qq.com/ws/place/v1/search?keyword=${keywords}&boundary=${boundary}&page_size=20&page_index=${this.pageIndex}&output=jsonp&key=${this.key}`;
				this.tui.tuiJsonp(
					url,
					res => {
						if (res.status === 0) {
							let data = res.data || [];
							this.getResult(data)
						}
					},
					'QQmap'
				);
				// #endif

				// #ifndef H5
				this.qqmapsdk.search({
					keyword: keywords,
					page_index: this.pageIndex,
					page_size: 20,
					boundary: boundary,
					//无此参数
					location: {
						latitude: this.lat,
						longitude: this.lng
					},
					success: res => {
						let data = res.data || [];
						this.getResult(data)
					},
					fail: res => {
						this.loading = false;
						this.tui.toast('获取位置信息失败,请检查是否打开位置权限');
					}
				});
				// #endif
			},
			// 点了键盘上的搜索响应事件
			bindInput: function(e) {
				console.log("输入11",e)
				this.keywords = e.detail.value;
				this.pageIndex = 1;
				this.address = [];
				this.covers = [];
				this.pullUpOn = true;
				// 根据关键字搜索
				this.getPoiAround(this.keywords);
			},
			// 点击标记点时触发
			marker: function(e) {
				const that = this
				const item = that.address[e.detail.markerId || 0];
				const menu = item.tel ? ["打电话", "到这里"] : ["到这里"];

				uni.showActionSheet({
					itemList: menu,
					success(res) {
						if (res.tapIndex == 0 && item.tel) {
							uni.makePhoneCall({
								phoneNumber: item.tel
							})
						} else {
							const latitude = Number(item.latitude)
							const longitude = Number(item.longitude)
							uni.openLocation({
								name: item.title,
								address: item.address,
								latitude,
								longitude,
								scale: 18
							})
						}
					},
					fail(res) {
						console.log(res.errMsg)
					}
				})

			},
			call(event) {
				const index = Number(event.currentTarget.dataset.id);
				const tel = this.address[index].tel;
				if (tel) {
					uni.makePhoneCall({
						phoneNumber: tel
					})
				}

			},
			go(event) {
				const index = Number(event.currentTarget.dataset.id)
				const item = this.address[index];
				const latitude = Number(item.latitude)
				const longitude = Number(item.longitude)
				uni.openLocation({
					name: item.title,
					address: item.address,
					latitude,
					longitude,
					scale: 18
				})
			}
		}
	}
</script>

<style>
	page {
		height: 100%;
	}

	.tui-list {
		background-color: #fff;
		position: relative;
		width: 100%;
		display: flex;
		flex-direction: column;
		padding-bottom: env(safe-area-inset-bottom);
	}

	.tui-list-cell {
		position: relative;
		display: flex;
		flex-direction: row;
		justify-content: space-between;
		align-items: center;
	}

	.tui-list-cell::after {
		content: '';
		position: absolute;
		border-bottom: 1rpx solid #eaeef1;
		-webkit-transform: scaleY(0.5);
		transform: scaleY(0.5);
		bottom: 0;
		right: 0;
		left: 30rpx;
	}

	.tui-cell-last::after {
		border-bottom: 0;
	}

	.maps-container {
		width: 100%;
		height: 100%;
		overflow: hidden;
	}

	.tui-map {
		width: 100%;
		/* height: 1000rpx; */
		height: 65%;
		display: block;
	}

	.scrollView {
		width: 100%;
		padding-bottom: 50rpx;
		background-color: #fff;
	}

	.search-bar {
		position: relative;
		padding: 8px 10px;
		display: -webkit-flex;
		display: flex;
		box-sizing: border-box;
		align-items: center;
		background-color: #fff;
	}

	.icon-search {
		margin-right: 8px;
	}

	.icon-search-in-box {
		margin-right: 8rpx;
	}

	.search-bar-form {
		position: relative;
		-webkit-box-flex: 1;
		-webkit-flex: auto;
		flex: auto;
		border-radius: 5px;
		background-color: #f0f0f0;
	}

	.search-bar-text {
		display: inline-block;
		font-size: 14px;
		vertical-align: middle;
	}

	.search-bar-box {
		width: 100%;
		height: 30px;
		padding-left: 10px;
		padding-right: 30px;
		box-sizing: border-box;
		display: flex;
		align-items: center;
		flex-wrap: nowrap;
		position: relative;
		z-index: 1;

	}

	.search-bar-input {
		font-size: 14px;
		flex: 1;
	}

	.icon-clear {
		height: 100%;
		position: absolute;
		top: 0;
		right: 0;
		padding: 0 8px;
		font-size: 0;
		display: flex;
		align-items: center;
	}

	.search-bar-label {
		width: 100%;
		height: 100%;
		position: absolute;
		left: 0;
		top: 0;
		z-index: 2;
		border-radius: 3px;
		text-align: center;
		color: #9b9b9b;
		background: #f0f0f0;
		display: flex;
		align-items: center;
		justify-content: center;

	}

	.cancel-btn {
		margin-left: 10px;
		line-height: 30px;
		color: #5982fd;
		white-space: nowrap;
		font-size: 15px;
	}

	.tui-list-cell {
		display: initial;
		padding: 30rpx;
	}

	.addr-title {
		font-size: 30rpx;
		line-height: 40rpx;
		color: #000;
		font-weight: bold;
		width: 100%;
		padding-bottom: 20rpx;
	}

	.addr-box {
		display: flex;
		align-items: flex-end;
		justify-content: space-between;
	}

	.addr-detail {
		width: 450rpx;
		overflow: hidden;
		text-overflow: ellipsis;
		display: -webkit-box;
		-webkit-line-clamp: 2;
		/* autoprefixer: off */
		-webkit-box-orient: vertical;
		/* autoprefixer: on */
		font-size: 24rpx;
		color: #999;
	}

	.distance {
		color: #5677fc;
		padding-right: 6rpx;
	}

	.addr-opera {
		display: flex;
		align-items: center;
		justify-content: space-between;
	}

	.opera-box {
		text-align: center;
		margin-left: 26rpx;
	}

	.mini-img {
		width: 44rpx;
		height: 44rpx;
	}

	.text {
		color: #333;
		font-size: 24rpx;
		line-height: 30rpx;
	}
</style>

获取位置权限:
在这里插入图片描述

项目下载地址:https://download.csdn.net/download/wy313622821/14503289

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wy313622821

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值