谈腾讯地图web api如何实现类似百度地图内置的城市切换、关键字输入提示功能

版权声明:本文为博主原创文章,转载请注明出处! https://blog.csdn.net/chuangxin/article/details/88636788

  PC WEB端新增客户的时候需要填写客户地址和联系人信息,包括:省市区、街道、详细地址和经纬度以及联系人、固话和移动电话。获取客户地址信息之前用的是百度地图,由于小程序中客户拜访时,需要对客户进行定位、距离计算,所以客户经纬度都转换成了gcj02坐标。由于之前的百度地图经纬度坐标是百度自己坐标,因此需要获取经纬度时进行坐标转换,根据坐标点在百度地图上显示时需要二次转换,所以打算将百度地图替换成腾讯地图。

1、腾讯地图WEB API缺陷

先看下百度地图提供的2个现成功能,简单设置即可用:
1)城市切换
在这里插入图片描述
2)关键字输入提示
在这里插入图片描述
看完百度地图web api,再看看腾讯地图web api有没有这2功能:
1)城市切换,没有自带的,需要自行实现;
2)搜索关键字提示,提供了api接口,没有UI,需要自行完善;

2、基于jquery、bootstrap的腾讯地图城市切换和搜索关键字提示实现

1)页面截图

在这里插入图片描述
在这里插入图片描述

2)html代码
<!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8" />
	<title>腾讯地图API</title>
	<link rel="stylesheet" href="https://cdn.bootcss.com/twitter-bootstrap/3.3.7/css/bootstrap.min.css" />
	<link rel="stylesheet" href="https://cdn.bootcss.com/font-awesome/4.5.0/css/font-awesome.min.css" />
	
	<script src="https://cdn.bootcss.com/jquery/1.11.1/jquery.min.js"></script>
	<script src="https://cdn.bootcss.com/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
	<style type="text/css">
		ul,li{margin:0; padding:0; list-style: none}
		.form-horizontal .form-group {margin-right: 0; margin-left: 0;}
		.form-control, .btn{border-radius:0; box-shadow:none;}
		.pr0 {padding-right: 0}
		.pl0 {padding-left: 0}
		#btn-reset, #btn-ok{width: 49.9%}
		#btn-ok {margin-left: -1px}
		.modal-backdrop {z-index: 900;}
		.modal {z-index: 901;}
		.pop_map .city-wrapper {position: absolute; background: #fff; border: 1px solid #e2e2e2; top: 46px; z-index: 9; width: 400px;}
		.pop_map .city-wrapper .hd {padding: 10px 10px 0; border-bottom: 1px solid #e5ebf3}
		.pop_map .city-wrapper .close {position: absolute; right: 0px; top: 0px; padding: 10px; font-size: 14px}
		.pop_map .city-wrapper .bd{padding: 10px; height: 300px; overflow-y: auto}
		.pop_map .city-wrapper .search{position: relative;}
		.pop_map .city-wrapper .search i {position: absolute; right: 10px; top: 10px;}
		.pop_map .form-control{box-shadow: none; border-radius:0;}
		.pop_map textarea{height: 48px;}
		.pop_map .keywords p {margin-bottom:0}
		.pop_map a, .pop_map a:hover {color: #166abe;}
		.pop_map a{line-height: 24px; margin-right: 10px; white-space:nowrap; text-decoration: none; outline:0}
		.pop_map .keywords {border-bottom: 1px solid #e5ebf3}
		.pop_map .cities li{padding: 4px 0; border-bottom: 1px solid #e5ebf3}
		.pop_map .cities .col1{width: 40px; margin-right: 12px;}
		.pop_map .cities .col2{width: 310px;}
		.pop_map .cities .col2 a {margin-right: 10px;}		
	</style>
</head>
<body>
<div class="page-content container">
	<div class='page-body'>
	<div class='panel panel-default'>
		<div class="panel-heading"><h3 class='panel-title'>腾讯地图:城市切换、搜索关键字演示</h3></div>
		<table class='table table-bordered'>
			<thead>
				<tr>
					<th width=35>No.</th>
					<th width="40%">描述</th>
					<th width="60%"><button type="button" class="btn btn-primary" id="btn-call">调用地图</button></th>
				</tr>
			</thead>
			<tbody>
				<tr>
				<td>1</td>
				<td>省-市-区</td>
				<td id="td-city"></td></tr>
				<tr>
				<td>2</td>
				<td>街道</td>
				<td id="td-street"></td></tr>
				<tr>
				<td>3</td>
				<td>详细地址</td>
				<td id="td-address"></td></tr>
				<tr>
				<td>4</td>
				<td>经纬度</td>
				<td id="td-jwd"></td></tr>
				<tr>
				<td>5</td>
				<td>联系人</td>
				<td id="td-contact"></td></tr>
				<tr>
				<td>6</td>
				<td>联系方式</td>
				<td id="td-tel"></td></tr>																		
			</tbody>
		</table>
	</div>
</div>
<div id="pop-map" class="modal fade modal-primary pop_map" tabindex="-1">
<div class="modal-dialog" style="width:760px; margin-top:20px; min-height: 420px;">
	<div class="modal-content">
		<div class="modal-header">
			<button type="button" class="close" data-dismiss="modal" aria-hidden="true" id="refresh">×</button>
			<h4 class="modal-title" id="title">新增/修改</h4>
		</div>
		<div class="modal-body form-horizontal clearfix ">
			<div class="form-group">
				<div class="input-group">
					<span class="input-group-btn">
						<button type="button" class="btn btn-default" id="btn-city"><span id="btn-city-text" style="margin-right: 5px">全国</span><i class="fa fa-caret-down"></i></button>
					</span>
					<input id="pop-map_ap" class="form-control"></input>
					<span class="input-group-btn">
						<button type="button" id="btn-search" class="btn btn-primary">搜索</button>
					</span>
				</div>
			</div>
			<div class="clearfix">
				<div id="pop-map_map" class="col-xs-9" style="height:480px"></div>
				<div class="col-xs-3 pr0">
				<div class="form-group">
					<label>省-市-区</label><input class="form-control input-sm" id="txt-city" readonly></input>
				</div>
				<div class="form-group">
					<label>街道门牌号</label><textarea class="form-control input-sm" id="txt-street"></textarea>
				</div>
				<div class="form-group">
					<label>经纬度</label><input class="form-control input-sm" id="txt-jwd" readonly></input>
				</div>
				<div class="form-group">
					<label>联系人</label><input class="form-control input-sm" id="txt-contact"></input>
				</div>
				<div class="form-group">
					<label>移动电话</label><input class="form-control input-sm" id="txt-mobile"></input>
				</div>
				<div class="form-group">
					<label>固话</label><input class="form-control input-sm" id="txt-tel"></input>
				</div>
				<div class="form-group" style='margin-bottom:0'>
					<button class="btn btn-sm btn-default" id="btn-reset">重置</button><button class="btn btn-sm btn-primary ml-1" id="btn-ok">确定</button>
				</div>	
			</div>
		</div> <!-- /.modal-body -->
	</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->

<script charset="utf-8" src="https://map.qq.com/api/js?v=2.exp&key=VEQBZ-2NIRW-3AARP-OAXJ3-2SFQ7-RFBNL&libraries=place&callback=initMap"></script>
<script type="text/javascript">
	var LyPop = {
		id: "pop-map",
		poi: {},
		show: function(poi) {
			$("#" + this.id).modal({backdrop: 'static', keyboard: false});
			this.initPoi(poi);
		},
		hide: function() {
			$("#" + this.id).modal('hide');
		},
		onOk: function(poi) {
			console.log(poi);
			poi = poi || {};
			$("#td-city").text(poi.province ? poi.province + "-" + poi.city + "-" + poi.district : "");
			$("#td-street").text(poi.street || '');
			$("#td-address").text(poi.address || '');
			$("#td-jwd").text(poi.pos_jd ? poi.pos_jd + ", " + poi.pos_wd : "");
			$("#td-contact").text(poi.contact || "");
			$("#td-mobile").text(poi.mobile || "");
			$("#td-tel").text(poi.tel || "");
			this.hide();
		},
		initPoi: function(poi) {
			console.log("p: ", poi)
			poi = poi || {};
			$("#txt-city").val(poi.province ? poi.province + "-" + poi.city + "-" + poi.district : "");
			$("#txt-street").val(poi.street || '');
			$("#txt-jwd").val(poi.pos_jd ? poi.pos_jd + ", " + poi.pos_wd : "");
			$("#txt-contact").val(poi.contact || "");
			$("#txt-mobile").val(poi.mobile || "");
			$("#txt-tel").val(poi.tel || "");
			this.poi = poi;
			if(poi.pos_jd && poi.pos_wd) {	// 设置地图center
				map.panTo(new qq.maps.LatLng(poi.pos_wd, poi.pos_jd));
			}
		}
	}
	var StringUtil = {
			format: function() {
				if(arguments.length == 0) return null;
				var str = arguments[0], a = arguments.length > 1 ? arguments[1] : null;
				if (! a || typeof a != 'object') {
					for(var i=1;i<arguments.length;i++) {
						var re = new RegExp('\\{' + (i-1) + '\\}','gm');
						str = str.replace(re, arguments[i]);
					}
				} else {	//对象格式化.
					var r = new RegExp('\\{([\\s\\S]+?)\\}','gm'), b = null, _str = str;
					while((b = r.exec(_str)) !== null) {
						str = str.replace(b[0], a[b[1]]);
					}
				}
				return str;
			}
	}
	var map = null, geocoder = null, cityservice = null, searchService = null, keyword = "";
	
	function initMap() {
		//init map
		map = new qq.maps.Map(document.getElementById("pop-map_map"), {
			// 地图的中心地理坐标。
			center: new qq.maps.LatLng(39.916527,116.397128),
			zoom: 13,				//缩放级别,4-17
			mapTypeControl: false,	//地图、卫星类型选择开关
			panControl: true		//东南西北旋转按钮
		});
	    geocoder = new qq.maps.Geocoder({
	        complete : function(result){
	        	var addrComponents = result.detail && result.detail.addressComponents;
	        	if (addrComponents) {
	        		var strCity = addrComponents.province + "-" + addrComponents.city + "-" + addrComponents.district;
	        		if(strCity != $("#txt-city").val()) {
	        			$("#txt-city").val(strCity);
	        			$("#txt-street").val(addrComponents.street);
	        		}
	        		$("#txt-jwd").val(result.detail.location.lng + ", " + result.detail.location.lat);
	        		LyPop.curPoi = {
	        				province: addrComponents.province, city: addrComponents.city, district: addrComponents.district, 
	        				pos_jd: result.detail.location.lng, pos_wd: result.detail.location.lat
	        			}
	        	}
	        }
	    });
		
	    //设置城市信息查询服务
		cityservice = new qq.maps.CityService();
	    //请求成功回调函数
		cityservice.setComplete(function(result) {
			console.log("sss: ", result)
	        map.setCenter(result.detail.latLng);
	    });
		cityservice.setError(function(result) {
			console.log("error: ", result, arguments)
	        // map.setCenter(result.detail.latLng);
	    });
	    //调用Poi检索类。用于进行本地检索、周边检索等服务。
	    searchService = new qq.maps.SearchService({
	        complete : function(results){
	        	if(results.type === "CITY_LIST") {
	        		var cityName = results.detail.cities[0].cityName;
	        		searchService.setLocation(cityName);
	        		$("#" + LyPop.id + " .btn-city-text").text(cityName).data("city", cityName);
	        		searchService.search(keyword);
	        		return;
	            }
	            var pois = results.detail.pois;
	            var latlngBounds = new qq.maps.LatLngBounds();
	            for(var i = 0,l = pois.length;i < l; i++){
	                var poi = pois[i];
	                latlngBounds.extend(poi.latLng);  
	                var marker = new qq.maps.Marker({
	                    map:map,
	                    position: poi.latLng
	                });

	                marker.setTitle(poi.name);
	            }
	            map.fitBounds(latlngBounds);
	        }
	    });
	    
	    //添加监听事件
	    var ap = new qq.maps.place.Autocomplete(document.getElementById("pop-map_ap"));
	    qq.maps.event.addListener(ap, "confirm", function(res){
	        keyword = res.value;
	        searchService.search(keyword);
	    });
		qq.maps.event.addListener(map, 'click', function(event) {
			geocoder.getAddress(event.latLng);
		});
	}
	
	$(function() {
		//
		var hotcities = ['北京','上海','广州','天津', '重庆', '深圳','杭州', '成都', '南京'];
		var provincePys = ['A','F','G','H', 'J', 'L','N', 'Q', 'S', 'T', 'X', 'Y', 'Z'];
		var provinceList = [
		                    {province: "安徽", py: "A", fullname: "安徽省", cities: ["合肥", "芜湖", "蚌埠", "淮南", "马鞍山", "淮北", "铜陵", "安庆", "黄山", "滁州", "阜阳", "宿州", "六安", "亳州", "池州", "宣城"]},
		                    {province: "福建", py: "F", fullname: "福建省", cities: ["福州", "厦门", "莆田", "三明", "泉州", "漳州", "南平", "龙岩", "宁德"]},
		                    {province: "广东", py: "G", fullname: "广东省", cities: ["广州", "韶关", "深圳", "珠海", "汕头", "佛山", "江门", "湛江", "茂名", "肇庆", "惠州", "梅州", "汕尾", "河源", "阳江", "清远", "东莞", "中山", "潮州", "揭阳", "云浮"]},
		                    {province: "广西", fullname: "广西壮族自治区", cities: ["南宁", "柳州", "桂林", "梧州", "北海", "防城港", "钦州", "贵港", "玉林", "百色", "贺州", "河池", "来宾", "崇左"]},
		                    {province: "贵州", fullname: "贵州省", cities: ["贵阳", "六盘水", "遵义", "安顺", "毕节", "铜仁", "黔西南", "黔东南", "黔南"]},
		                    {province: "甘肃", fullname: "甘肃省", cities: ["兰州", "嘉峪关", "金昌", "白银", "天水", "武威", "张掖", "平凉", "酒泉", "庆阳", "定西", "陇南", "临夏", "甘南"]},
		                    {province: "河北", py: "H", fullname: "河北省", cities: ["石家庄", "唐山","秦皇岛","邯郸","邢台","保定","张家口","承德","沧州", "廊坊", "衡水"]},
		                    {province: "河南", fullname: "河南省", cities: ["郑州", "开封", "洛阳", "平顶山", "安阳", "鹤壁", "新乡", "焦作", "濮阳", "许昌", "漯河", "三门峡", "南阳", "商丘", "信阳", "周口", "驻马店"]},
		                    {province: "湖北", fullname: "湖北省", cities: ["武汉", "黄石", "十堰", "宜昌", "襄阳", "鄂州", "荆门", "孝感", "荆州", "黄冈", "咸宁", "随州", "恩施"]},
		                    {province: "湖南", fullname: "湖南省", cities: ["长沙", "株洲", "湘潭", "衡阳", "邵阳", "岳阳", "常德", "张家界", "益阳", "郴州", "永州", "怀化", "娄底", "湘西"]},
		                    {province: "黑龙江", fullname: "黑龙江省", cities: ["哈尔滨", "齐齐哈尔", "鸡西", "鹤岗", "双鸭山", "大庆", "伊春", "佳木斯", "七台河", "牡丹江", "黑河", "绥化", "大兴安岭"]},
		                    {province: "海南", fullname: "海南省", cities: ["海口", "三亚", "三沙", "儋州"]},
		                    {province: "江苏", py: "J", fullname: "江苏省", cities: ["南京", "无锡", "徐州", "常州", "苏州", "南通", "连云港", "淮安", "盐城", "扬州", "镇江", "泰州", "宿迁"]},
		                    {province: "江西", fullname: "江西省", cities: ["南昌", "景德镇", "萍乡", "九江", "新余", "鹰潭", "赣州", "吉安", "宜春", "抚州", "上饶"]},
		                    {province: "吉林", fullname: "吉林省", cities: ["长春", "吉林", "四平", "辽源", "通化", "白山", "松原", "白城", "延边"]},
		                    {province: "辽宁", py: "L", fullname: "辽宁省", cities: ["沈阳", "大连", "鞍山", "抚顺", "本溪", "丹东", "锦州", "营口", "阜新", "辽阳", "盘锦", "铁岭", "朝阳", "葫芦岛"]},
		                    {province: "宁夏", py: "N", fullname: "宁夏回族自治区", cities: ["银川", "石嘴山", "吴忠", "固原", "中卫"]},
		                    {province: "内蒙古", fullname: "内蒙古自治区", cities: ["呼和浩特", "包头", "乌海", "赤峰", "通辽", "鄂尔多斯", "呼伦贝尔", "巴彦淖尔", "乌兰察布", "兴安", "锡林郭勒", "阿拉善"]},
		                    {province: "青海", py: "Q", fullname: "青海省", cities: ["西宁", "海东", "海北", "黄南", "海南", "果洛", "玉树", "海西"]},
		                    {province: "山东", py: "S", fullname: "山东省", cities: ["济南", "青岛", "淄博", "枣庄", "东营", "烟台", "潍坊", "济宁", "泰安", "威海", "日照", "莱芜", "临沂", "德州", "聊城", "滨州", "菏泽"]},
		                    {province: "山西", fullname: "山西省", cities: ["太原", "大同", "阳泉", "长治", "晋城", "朔州", "晋中", "运城", "忻州", "临汾", "吕梁"]},
		                    {province: "陕西", fullname: "陕西省", cities: ["西安", "铜川", "宝鸡", "咸阳", "渭南", "延安", "汉中", "榆林", "安康", "商洛"]},
		                    {province: "四川", fullname: "四川省", cities: ["成都", "自贡", "攀枝花", "泸州", "德阳", "绵阳", "广元", "遂宁", "内江", "乐山", "南充", "眉山", "宜宾", "广安", "达州", "雅安", "巴中", "资阳", "阿坝", "甘孜", "凉山"]},
		                    {province: "台湾", py: "T", fullname: "台湾省", cities: ["台北", "高雄", "台南", "台中", "南投", "基隆", "新竹", "嘉义", "新北", "宜兰", "桃园", "苗栗", "彰化", "云林", "屏东", "台东", "花莲", "澎湖"]},
		                    {province: "西藏", py: "X", fullname: "西藏自治区", cities: ["拉萨", "日喀则", "昌都", "林芝", "山南", "那曲", "阿里"]},
		                    {province: "新疆", fullname: "新疆维吾尔自治区", cities: ["乌鲁木齐", "克拉玛依", "吐鲁番", "哈密", "昌吉", "博州", "巴州", "阿克苏", "克州", "喀什", "和田", "伊犁", "塔城", "阿勒泰"]},
		                    {province: "云南", py: "Y", fullname: "云南省", cities: ["昆明", "曲靖", "玉溪", "保山", "昭通", "丽江", "普洱", "临沧", "楚雄", "红河", "文山", "西双版纳", "大理", "德宏", "怒江", "迪庆"]},
		                    {province: "浙江", py: "Z", fullname: "浙江省", cities: ["杭州", "宁波", "温州", "嘉兴", "湖州", "绍兴", "金华", "衢州", "舟山", "台州", "丽水"]},
		                    {province: "其它", fullname: "", cities: ["香港", "澳门"]}
		                    ];
		var cities = [];
		for(var i in provinceList) {
			var _cities = provinceList[i]['cities'];
			for(var ii in _cities) {
				cities.push({name: _cities[ii], fullname: (provinceList[i]['province'] == '其它' ? '' : provinceList[i]['province'] + "/") + _cities[ii]});
			}
		}		
		var mapCity = '<div id="city-wrapper" class="city-wrapper" style="display:none;">'
			+ "<div class='hd'>"
			+	"<p>请选择城市</p>"
			+	"<div class='close'><i class='fa fa-close'></i></div>"
			+	"<p>当前城市: <span id='cur-city'></span></p>"
			+ "</div>"
			+ "<div class='bd'><div class='search'>";
		// 热门城市
		mapCity += "<div class='keywords'><p><a href='javascript:void(0);' fullname='全国'>全国</a>";
		for(var i in hotcities) {
			mapCity += StringUtil.format("<a href='javascript:void(0);' fullname='{0}'>{1}</a>", hotcities[i] + '市', hotcities[i]);
		}
		mapCity +=	"</p></p>";
		for(var i in provincePys) {
			mapCity += StringUtil.format("<a href='{0}'>{1}</a>", "#py_" + provincePys[i], provincePys[i]);
		}
		mapCity += "</p></div>";
		mapCity +=	"</div>" // search-end
			
		mapCity += "<ul class='cities'>";
		for(var i in provinceList) {
			var province = provinceList[i];
			mapCity += "<li class='clearfix'>";
			mapCity += StringUtil.format("<div class='pull-left col1'><a href='javascript:void(0);' {0}>{1}</a></div>", province.py ? "name=py_" + province.py: "", province.province);
			mapCity += "<div class='pull-left col2'>";
			for(var ii in province.cities) {
				mapCity += StringUtil.format("<a href='javascript:void(0);' fullname='{0}'>{1}</a>", province.province + "/" + province.cities[ii], province.cities[ii]);
			}
			mapCity += "</div>"
			mapCity += "</li>"
		}
		mapCity += "</ul>";
		mapCity += "</div></div>";
		//
		$("#btn-call").click(function(e){
			LyPop.show(LyPop.curPoi || {});
		});
		$("#btn-ok").on("click", function(e) {
			var curPoi = LyPop.curPoi || {};
			if (LyPop.onOk) {
				var result = $.extend({}, LyPop.poi, LyPop.curPoi);
				result.street = $("#txt-street").val();
				result.contact = $("#txt-contact").val();
				result.tel = $("#txt-tel").val();
				result.mobile = $("#txt-mobile").val();
				if(result.province && result.city) 
					result.address = (result.province == result.city ? "" : result.province) + result.city + result.district + ' ' + result.street;
				if(!result.province || !result.city || !result.district || !result.street) {
					alert('省市区、详细地址不能为空'); return
				}
				LyPop.curPoi = result;
				LyPop.onOk(result);
			}
		});
		$("#btn-reset").on("click", function(e) { LyPop.initPoi(LyPop.poi || {}); });
		$("#btn-search").on("click", function(e) {
			var keyword = $("#pop-map_ap").val();
			if(keyword) searchService.search(keyword);
		})
		$('#btn-city').on('click', function(e) {
			$("#city-wrapper").toggle();
		})
		$(".close").on('click', function(e) {
			$("#city-wrapper").hide();
		})
		$("#pop-map .modal-body").append(mapCity);
		$("#pop-map a[fullname]").on('click', function(e) {
        	$("#cur-city").text($(this).attr('fullname'));
        	$("#btn-city-text").text($(this).attr('fullname')).data('city', $(this).text());
        	$("#pop-map_ap").val('');
        	cityservice.searchCityByName( $(this).text() + "市");
        	$("#city-wrapper").hide();
		});
	})
</script>
</body>
</html>

代码说明:
中文整理的代码,结构有点乱,勉强可以工作,仅供参考。

3、进一步优化

建议大家封装成一个弹出框组件,可以:
1)根据poi数据,初始化地图;
2)可以显示、隐藏弹出框组件;
3)可以有返回结果回调;

猜你喜欢

转载自blog.csdn.net/chuangxin/article/details/88636788
今日推荐