定位——h5原生/高德/腾讯定位(城市搜索、自动补全、定位按钮和logo修改)

在项目添加新功能时,使用cdn方式引入使用地图功能,使用功能只用到了地图的定位、点标记、详细地址查询、poi搜索和输入提示、计算两点之间的距离;因为在寻找高德地图问题时发现h5 和 web 端的好少,因此记录一下方便以后查找。

h5的navigator 原生定位

// 在导入js的时候添加插件AMap.Geocoder
<script src="https://webapi.amap.com/maps?v=1.4.15&key=你的WEBjs的key&plugin=AMap.Geocoder"></script>
let geocoder = new AMap.Geocoder({}); // 获取地理编码与逆地理编码类 实例
// 判断是否存在navigator.geolocation
if(navigator && navigator.geolocation) {
	// 开始定位
    navigator.geolocation.getCurrentPosition(function(position) {
        let latitude = position.coords.latitude;// 获取纬度
        let longitude = position.coords.longitude;// 获取经度
        // 获取到的是gps 定位 使用高德的经纬度转换
        // https://lbs.amap.com/api/webservice/guide/api/convert 这是经纬度转换的地址可以看下有什么参数
        $.ajax({
            url: 'https://restapi.amap.com/v3/assistant/coordinate/convert?key=必须是web服务的key',
            type: 'get',
            data: {
                locations: longitude+','+latitude,
                coordsys: "gps",
            },
            success:function(res){
            	// 根据转换的经纬度 查询当前位置的详细地址
                geocoder.getAddress(res.locations.split(','),function(status, result) { 
                	// 查询详细地址
                    alert(result.regeocode.formattedAddress)
                });
            }
        })
    },function(err){
        console.log(err);
    },{
        enableHighAcuracy: true, //位置是否精确获取
        timeout: 5000,            //获取位置允许的最长时间
        maximumAge: 1000          //多久更新获取一次位置
    });
}

1. 高德地图

  1. 首先我们引入脚本

当前时间 2020/09/22 高德地图版本号 v=1.4.15
使用高德地图 v=2.0 版本在ios上有兼容问题地图渲染不出来 显示白屏效果 (不推荐使用)
高德地图对 http 站点的定位服务不精确 ,微信自从升级到7.0后就对http 站点的定位不支持了所以高德在微信上定位失效可能是http 站点导致的问题( 但是在ie 浏览器和edge浏览器是可以使用的 )
如何申请高德地图key

<!--引入高德地图JSAPI -->
<script src="https://webapi.amap.com/maps?v=1.4.15&key=you key & plugin=AMap.Geocoder"></script>
  1. 在$(document).ready(function(){ }) 中执行map 的init 方法
	let mapObj; // 地图实例
	let geolocation; // 定位对象实例
	let geocoder = new AMap.Geocoder({}); // 获取地理编码与逆地理编码类 实例
	
	mapObj = new AMap.Map('container',{
        center: [ 121.47, 31.23], // 地图中心点坐标值
        resizeEnable: true, // 是否监控地图容器尺寸变化,默认值为false
        zoom: 9, // 地图显示的缩放级别
    });
    // 定位
    mapObj.plugin('AMap.Geolocation', function() {
        geolocation = new AMap.Geolocation({
            enableHighAccuracy: true,//是否使用高精度定位,默认:true
            timeout: 10000,          //超过10秒后停止定位,默认:无穷大
            maximumAge: 0,           //定位结果缓存0毫秒,默认:0
            convert: true,           //自动偏移坐标,偏移后的坐标为高德坐标,默认:true
            showButton: true,        //显示定位按钮,默认:true
            buttonPosition: 'RB',    //定位按钮停靠位置,默认:'LB',左下角
            // buttonOffset: new AMap.Pixel(80, 90),//定位按钮与设置的停靠位置的偏移量,默认:Pixel(10, 20)
            showMarker: true,        //定位成功后在定位到的位置显示点标记,默认:true
            showCircle: false,        //定位成功后用圆圈表示定位精度范围,默认:true
            panToLocation: true,     //定位成功后将定位到的位置作为地图中心点,默认:true
            zoomToAccuracy:true      //定位成功后调整地图视野范围使定位位置及精度范围视野内可见,默认:false
        });
        mapObj.addControl(geolocation); // 添加定位控件
        // 重新定位 只需要执行下面的方法就行
        geolocation.getCurrentPosition();
        AMap.event.addListener(geolocation, 'complete', onComplete)
        AMap.event.addListener(geolocation, 'error', onError)
    })
	
	// 定位成功
	function onComplete (data) {
	    // data是具体的定位信息
	    let position = [data.position.lng, data.position.lat]
	    mapObj.setZoomAndCenter(15, position) // 将当前定位设置为中心并缩放至对应层级
	    compareDistance(data.position); // 查询距离
	}
	// 定位失败
	function onError (data) {
	    // 定位出错
	}
	
	// 计算两个坐标点距离
	let compareDistance = function(position1, position2) {
	    //转换
	    var myDistance = position1.distance([121.492728, 31.150647]);//这里测量距离
	    // console.log(myDistance,'米')
	}

	// 获取城市
    getCityGD(function(res) {
        // poi搜索 和 输入提示
        poiSearchAndInputTip(res.city);
    })

	// 获取当前城市
	function getCityGD(callback) {
	    AMap.plugin('AMap.CitySearch', function () {
	        var citySearch = new AMap.CitySearch()
	        citySearch.getLocalCity(function (status, result) {
	          if (status === 'complete' && result.info === 'OK') {
	            // 查询成功,result即为当前所在城市信息
	            callback(result)
	          }else{
				callback('')
			  }
	        })
	      })
	}  
	
	// poiSearchAndInputTip  // poi搜索 和 输入提示
	function poiSearchAndInputTip(city) {
	    AMap.plugin(['AMap.Autocomplete','AMap.PlaceSearch'],function(){
	        var autoOptions = {
	            input: "tipinput",
	            // 城市,默认全国
	            city: city || "全国",
	        }
	        var autocomplete= new AMap.Autocomplete(autoOptions)
	
	        var placeSearch = new AMap.PlaceSearch({
	            city: city || '全国',
	            map: mapObj,
	            pageSize: 1
	        })
	        AMap.event.addListener(autocomplete, 'select', function(e){
	            //TODO 针对选中的poi实现自己的功能
	            let location = e.poi.location; // 当前点的经纬度 
	            // e.poi // 当前点的详细信息
	            placeSearch.setCity(e.poi.adcode);
	            placeSearch.search(e.poi.name);  //关键字查询查询
	            // 根据经纬度查询 详细地址 具体到街道
	            geocoder.getAddress(location,function(status, result){ // 查询详细地址
	                if (status === 'complete'&& result.regeocode) {
	                    document.getElementById('address').innerHTML = result.regeocode.formattedAddress;
	                }else{
	                    console.error('根据经纬度查询地址失败')
	                }
	            })
	        })
	    })
	}
  1. 创建marker
	// 创建点标记 position 格式 {lat:121.492728 , lng:31.150647}
	let createMarker = function(position) { //
	    // 创建点标记
	    var marker = new AMap.Marker({
	    	// 转换经纬度 new AMap.LngLat
	        position: new AMap.LngLat(position.lat, position.lng),   // 经纬度对象,也可以是经纬度构成的一维数组[116.39, 39.9]
	        offset: new AMap.Pixel(-10, -10),
	        // 添加icon图标是因为有时候在手机端图片显示不出来
	        icon: "https://webapi.amap.com/theme/v1.3/markers/n/mark_b.png", // 添加 Icon 图标 URL
	    });
	    mapObj.add(marker)
	}
  1. 创建圆
	// position 格式 {lat:121.492728 , lng:31.150647}
	let createCircle = function (position) {
	    // 创建圆 
	    var circle = new AMap.Circle({
	        center: new AMap.LngLat(121.492728,31.150647), // 圆心位置
	        radius: 500,  //半径
	        strokeColor: "#216BFF",  //线颜色
	        strokeOpacity: 1,  //线透明度
	        strokeWeight: 1,  //线粗细度
	        fillColor: "#1F6AFF",  //填充颜色
	        fillOpacity: 0.1 //填充透明度
	    });
	    // 添加圆
	    mapObj.add(circle);
	}
  1. 去除高德logo和定位按钮样式
/* 隐藏高德logo */
.amap-logo,.amap-copyright { display:none !important; }
/* 定位按钮位置调整 */
.amap-geolocation-con .amap-geo { bottom:200px!important; display: none!important;}

创建圆和点标记是通过目标点的圆圈范围来判断、当前位置是否处于目标的范围内 , 高德地图在浏览器上是获取不到当前定位的 需要通过手机打开gps定位 并在https 站点上才能获取, 如果是做 h5+app 的话可以在app 上显示定位的。


2. 腾讯地图

  1. 腾讯地图导入脚本

腾讯地图导入geolocation脚本是因为 腾讯地图的定位服务是一个单独的脚本服务

<!--  腾讯地图 -->
<script charset="utf-8" src="https://map.qq.com/api/js?v=2.exp&key=you key"></script>
<!--  如果有需要腾讯地图定位服务可以使用 -->
<script src="https://3gimg.qq.com/lightmap/components/geolocation/geolocation.min.js"></script>
  1. 同高德地图在dom渲染完成后执行
	let key = 'you key';// 腾讯key
	let mapObj; // 地图实例
	
	// 创建地图
	mapObj = new qq.maps.Map(document.getElementById("container"), {
        center: new qq.maps.LatLng(31.23, 121.47),      // 地图的中心地理坐标。
        zoomControl: false,                      //设置缩放控件启用
        zoomControlOptions: {                   //设置缩放控件的样式状态
            style: qq.maps.ZoomControlStyle.SMALL
        },
        disableDefaultUI: true,        // 禁止所有控件                     
        draggable: true,               //设置是否可以拖拽
        scrollwheel: true,             //设置是否可以滚动
        disableDoubleClickZoom: false,    //设置是否禁止可以双击放大
        zoom: 15                       	// 地图的当前缩放等级。
    });
  1. 腾讯地图定位

腾讯和高德坐标系 都是使用的GCJ-02坐标系
腾讯和高德的坐标转换接口=>> 坐标转换接口、快捷键

  • WGS84 :地理坐标系统,Google Earth中国外的Google Map使用,另外,目前基本上所有定位空间位置的设备都使用这种坐标系统,例如手机的GPS系统
  • GCJ-02:投影坐标系统,也就是我们平常所说的火星坐标系,Google Map中国高德腾讯好像使用,这个是中国自己在WGS84基础上加密而成,目的显而易见。
  • BD09:投影坐标系统,百度地图使用,在GCJ-02基础上二次加密而成。
  • 坐标系科普–引用地址、有兴趣可以自己去看看

如何申请腾讯地图key

腾讯地图定位使用

	var key = "you key";
	// Geolocation 参数 第一个是腾讯地图的key  第二个是调用来源,一般为您的应用名称
    var geolocation = new qq.maps.Geolocation(key, "myapp");
    // 请求定位时间
    var options = {timeout: 9000};
    // 执行获取定位
    geolocation.getLocation(showPosition, showErr, options);
	// 定位成功
    function showPosition(position) {
    	// 成功...
    }
    function showErr() {
    	// 失败... 
    }
  1. 这里我使用的是高德地图定位啦,如有需要将下面定位部位替换成上面腾讯地图定位即可
	// 定位 -- 高德
    AMap.plugin('AMap.Geolocation', function() {
        geolocation = new AMap.Geolocation({
            enableHighAccuracy: true,//是否使用高精度定位,默认:true
            timeout: 10000,          //超过10秒后停止定位,默认:无穷大
            maximumAge: 0,           //定位结果缓存0毫秒,默认:0
            convert: true,           //自动偏移坐标,偏移后的坐标为高德坐标,默认:true
            showButton: true,        //显示定位按钮,默认:true
            buttonPosition: 'RB',    //定位按钮停靠位置,默认:'LB',左下角
            // buttonOffset: new AMap.Pixel(80, 90),//定位按钮与设置的停靠位置的偏移量,默认:Pixel(10, 20)
            showMarker: true,        //定位成功后在定位到的位置显示点标记,默认:true
            showCircle: false,        //定位成功后用圆圈表示定位精度范围,默认:true
            panToLocation: true,     //定位成功后将定位到的位置作为地图中心点,默认:true
            zoomToAccuracy:true      //定位成功后调整地图视野范围使定位位置及精度范围视野内可见,默认:false
        });
        // 重新定位 只需要执行下面的方法就行
        geolocation.getCurrentPosition();
        AMap.event.addListener(geolocation, 'complete', onComplete)
        AMap.event.addListener(geolocation, 'error', onError)
    })
    // 定位成功
	function onComplete (data) {
	    // 将高德坐标转换成腾讯的坐标 new qq.maps.LatLng 
		let arr = data.position.toString().split(',');
		// 设置中心点
	    mapObj.panTo(new qq.maps.LatLng(arr[1],arr[0]));//坐标 当前位置
	    mapObj.zoomTo(17) // 设置层级
	    // 创建当前位置marker
		createMarker(new qq.maps.LatLng(arr[1],arr[0]))
	}
	// 定位失败
	function onError (data) {
	    // 定位出错...
	}
	
	// 创建marker 当前位置 marker  因为腾讯定位没有给我们定位图片所以要自己创建一个marker
	function createMarker (center, iconImg) {
		iconImg  = iconImg || 'http://lbs.qq.com/javascript_v2/img/center.gif'
		let anchor = new qq.maps.Point(0, 39),
		size = new qq.maps.Size(42, 68),
		origin = new qq.maps.Point(0, 0),
		icon = new qq.maps.MarkerImage(
		    iconImg,
		    size,
		    origin,
		    anchor
		);
		// 创建maker 
		var marker = new qq.maps.Marker({
		    position: center,
		    map: mapObj,
		    icon: icon
		})
	}
  1. 腾讯poi 选点 和 地点搜索 — 腾讯 Autocomplete 自动补全

    利用js 防抖函数处理 oninput 事件防止请求多次执行

    这是Autocomplete 参数地址
    在这里插入图片描述

	//监听输入拼音,当用户在输入拼音时不进行操作
	let timer = null, nowCity;
	// 地图文本框监听 --- 控制 placeholder 显示隐藏
	function mapInput(e, dom){
		// 判断当前文本框去除空格后是否有值 
	    if(!$(dom)[0].value.trim().length) {
	        $('.placeholder-class').show(); // 自定义文本框placeholder
	     }else {
	        $('.placeholder-class').hide(); // 自定义文本框placeholder
	        clearTimeout(timer)
	        timer = null;
			// 防抖处理
	        timer = setTimeout(()=> {
	        	// 限制自动补全的查询范围 nowCity
	            txAutocomplete($(dom)[0].value.trim(), nowCity)
	        },500)
	    }
	}
	// 获取当前的地理位置非精确定位 城市 在init中执行
	function getCity() {  
		$.ajax({
	        type:'get',
	        async: false,
			url:'https://apis.map.qq.com/ws/location/v1/ip',
			data:{
	            key: key,
	            output: 'jsonp'
	        },
	        dataType: "jsonp",
	        jsonp: "callback",//传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名(一般默认为:callback)
	        success:function (response){
	            nowCity = response.result.ad_info.city
			}
		})
	} 


	
	function txAutocomplete(value, city) {
		$.ajax({
	        type:'get',
	        async: false,
			url:'https://apis.map.qq.com/ws/place/v1/suggestion',
			data:{
				keyword: value, // input 输入框的内容
				region: city, // 查询内容的城市 当前城市没有查找到默认全国搜索
	            key: key, // 腾讯地图key
	            region_fix: 0, 
	            output: 'jsonp'
	        },
	        dataType: "jsonp",
	        jsonp: "callback",//传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名(一般默认为:callback)
			success:function (response){
	            if(response.status == 0) {
	            	// 判断是否有数据 
	               if(response.data.length == 0) {
	                    $('#poiTip').hide(); // 这是搜索结果展示容器 如上图 id 隐藏
	               }else { 
	                    $('#poiTip').show(); // 这是搜索结果展示容器 如上图 id 显示
	               }
	               // autocompleteHtml 生成html 样式 可以自己定义
	               htmlVal = autocompleteHtml(response.data)
	               $('#poiTip').html(htmlVal) // 将html 放到容器展示 
	            }
			}
		})
	}
	let selectMarker, selectAddressName ;
	// 选中的地址
	function selectAddress(lat, lng, evt) {
	    // 选择完地址后 隐藏 Autocomplete 提示
	    $('#poiTip').hide();
	
	    if(selectMarker) selectMarker.setMap(null);// 移除点标记
	    let center = new qq.maps.LatLng(lat, lng) // 拿到经纬度转换
	
	    // 查询详细地址 具体到街道
	    getDetailsTX([lat, lng], function(res){
	    	selectAddressName = res;
	        $('#address').html(selectAddressName)
	    }); // 腾讯
	
	    // 添加marker 
	    selectMarker = new qq.maps.Marker({
	        position: center,
	        draggable: false,// 是否可以拖动
	        map: mapObj
	    });
	
	    // 将地图中心移到对应坐标
	    mapObj.panTo(center); 
	    // 将缩放至17 最大18 最小3
	    mapObj.zoomTo(17)
	
	
	    // 点击marker 添加信息窗体 初始化infoWindow
	    var infoWindow = new qq.maps.InfoWindow({
	        map: mapObj,
	        position: new qq.maps.LatLng(39.984104, 116.307503),
	        offset: { x: -8, y: -32 }
	    });
	    infoWindow.close();// 先隐藏
	
	
	    // 监听地图marker 点击事件
	    qq.maps.event.addListener(selectMarker, 'click', function() {
	            infoWindow.open();
	            infoWindow.setPosition(selectMarker.getPosition());
	            // 信息窗体展示详细地址
	            infoWindow.setContent(`${selectAddressName }`)
	    });
	}
	// 获取详情地址 --- 逆地址解析 -- 腾讯  三林地铁站 ==> "上海市浦东新区三林路1518号"
	function getDetailsTX(local, callback) {
		// local 是个数组 [lat, lng]
	    $.ajax({
	        type: 'get',
	        url: 'https://apis.map.qq.com/ws/geocoder/v1/',
	        data: {
	            location: local.toString(), // 需要这样 39.984104,116.307503 参数格式
	            get_poi: 1,
	            key: key,
	            output: 'jsonp' // 防止跨域
	        },
	        dataType: "jsonp", 
	        jsonp: "callback",//传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名(一般默认为:callback)
	        success: function(res){
	            callback(res.result.address); //address
	        }
	    })
	}
  1. 计算两点之间距离 直线
// 开始坐标点 和 结束坐标点
var start = new qq.maps.LatLng(start_lat, start_lng),  
	end = new qq.maps.LatLng(end_lat, end_lng);
var total = Math.round(qq.maps.geometry.spherical.computeDistanceBetween(start, end) * 10) / 10;
  1. 去除腾讯地图logo
	// 去除腾讯地图logo
    $("#container").bind("DOMNodeInserted",function(e){
        var tempCount = 0;
        $("#container .smnoprint").siblings().each(function(){
            tempCount++;
            if(tempCount==2||tempCount==3){
                $(this).remove();
            }
        });
    });

以上 就是此次用到的地方 后续如果还有用到会进行更新

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值