微信公众号开发《三》微信JS-SDK之地理位置的获取与在线导航,集成百度地图实现在线地图搜索

本次讲解微信开发第三篇:获取用户地址位置信息,是非常常用的功能,特别是服务行业公众号,尤为需要该功能,本次讲解的就是如何调用微信JS-SDK接口,获取用户位置信息,并结合百度地铁,实现在线地图搜索,与在线导航。


官方文档地址:https://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html

在这粘贴上二篇博文链接,方便大家访问:

微信公众号开发《一》OAuth2.0网页授权认证获取用户的详细信息,实现自动登陆

微信公众号开发《二》发送模板消息实现消息业务实时通知

1.何为JS-SDK:微信JS-SDK是微信公众平台面向网页开发者提供的基于微信内的网页开发工具包。网页开发者可借助微信高效地使用拍照、选图、语音、位置等手机系统的能力,同时可以直接使用微信分享、扫一扫、卡券、支付等微信特有的能力,为微信用户提供更优质的网页体验。简单来说:就是在自己公众平台后台配置后,可直接调用的功能接口。

那如何配置呢?下面讲解下配置步骤:示例讲解是基于测试公众号,如何使用测试公众号,可以参考第一篇文章

 

1.在公众号后台绑定域名:测试公众号登录就可看见如下图。正式公众号配置位置:“公众号设置”的“功能设置”里填写“JS接口安全域名”


2.页面中引入接口JS文件,下载地址:http://res.wx.qq.com/open/js/jweixin-1.2.0.js

注意:JS最新版本为1.2.0,为了适配IOS开发,最好使用最新版本号JS,1.1.0版本可能会造成有些功能调用失败,有兴趣的可以看看官方文档:https://mp.weixin.qq.com/advanced/wiki?t=t=resource/res_main&id=mp1483682025_enmey

3.获取必须参数:

wx.config({
    debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
    appId: '', // 必填,公众号的唯一标识
    timestamp: , // 必填,生成签名的时间戳
    nonceStr: '', // 必填,生成签名的随机串
    signature: '',// 必填,签名
    jsApiList: [
		'openLocation',
		'getLocation'
	] // 必填,需要使用的JS接口列表,更多接口可看官方文档
});

看调用接口,可知,现在缺timestamp,signature,nonceStr。不用想的太复杂,还是那个原则,没什么获取什么,

获取signature签名,生成签名之前必须先了解一下jsapi_ticket,jsapi_ticket是公众号用于调用微信JS接口的临时票据。正常情况下,jsapi_ticket的有效期为7200秒,通过access_token来获取。由于获取jsapi_ticket的api调用次数非常有限,频繁刷新jsapi_ticket会导致api调用受限,影响自身业务,开发者必须在自己的服务全局缓存jsapi_ticket。

写个工具类封装获取方法

public class SHA1 { //sha算法
    private final int[] abcde = { 
            0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0 
        }; 
    // 摘要数据存储数组 
    private int[] digestInt = new int[5]; 
    // 计算过程中的临时数据存储数组 
    private int[] tmpData = new int[80]; 
    // 计算sha-1摘要 
    private int process_input_bytes(byte[] bytedata) { 
        // 初试化常量 
        System.arraycopy(abcde, 0, digestInt, 0, abcde.length); 
        // 格式化输入字节数组,补10及长度数据 
        byte[] newbyte = byteArrayFormatData(bytedata); 
        // 获取数据摘要计算的数据单元个数 
        int MCount = newbyte.length / 64; 
        // 循环对每个数据单元进行摘要计算 
        for (int pos = 0; pos < MCount; pos++) { 
            // 将每个单元的数据转换成16个整型数据,并保存到tmpData的前16个数组元素中 
            for (int j = 0; j < 16; j++) { 
                tmpData[j] = byteArrayToInt(newbyte, (pos * 64) + (j * 4)); 
            } 
            // 摘要计算函数 
            encrypt(); 
        } 
        return 20; 
    } 
    // 格式化输入字节数组格式 
    private byte[] byteArrayFormatData(byte[] bytedata) { 
        // 补0数量 
        int zeros = 0; 
        // 补位后总位数 
        int size = 0; 
        // 原始数据长度 
        int n = bytedata.length; 
        // 模64后的剩余位数 
        int m = n % 64; 
        // 计算添加0的个数以及添加10后的总长度 
        if (m < 56) { 
            zeros = 55 - m; 
            size = n - m + 64; 
        } else if (m == 56) { 
            zeros = 63; 
            size = n + 8 + 64; 
        } else { 
            zeros = 63 - m + 56; 
            size = (n + 64) - m + 64; 
        } 
        // 补位后生成的新数组内容 
        byte[] newbyte = new byte[size]; 
        // 复制数组的前面部分 
        System.arraycopy(bytedata, 0, newbyte, 0, n); 
        // 获得数组Append数据元素的位置 
        int l = n; 
        // 补1操作 
        newbyte[l++] = (byte) 0x80; 
        // 补0操作 
        for (int i = 0; i < zeros; i++) { 
            newbyte[l++] = (byte) 0x00; 
        } 
        // 计算数据长度,补数据长度位共8字节,长整型 
        long N = (long) n * 8; 
        byte h8 = (byte) (N & 0xFF); 
        byte h7 = (byte) ((N >> 8) & 0xFF); 
        byte h6 = (byte) ((N >> 16) & 0xFF); 
        byte h5 = (byte) ((N >> 24) & 0xFF); 
        byte h4 = (byte) ((N >> 32) & 0xFF); 
        byte h3 = (byte) ((N >> 40) & 0xFF); 
        byte h2 = (byte) ((N >> 48) & 0xFF); 
        byte h1 = (byte) (N >> 56); 
        newbyte[l++] = h1; 
        newbyte[l++] = h2; 
        newbyte[l++] = h3; 
        newbyte[l++] = h4; 
        newbyte[l++] = h5; 
        newbyte[l++] = h6; 
        newbyte[l++] = h7; 
        newbyte[l++] = h8; 
        return newbyte; 
    } 
    private int f1(int x, int y, int z) { 
        return (x & y) | (~x & z); 
    } 
    private int f2(int x, int y, int z) { 
        return x ^ y ^ z; 
    } 
    private int f3(int x, int y, int z) { 
        return (x & y) | (x & z) | (y & z); 
    } 
    private int f4(int x, int y) { 
        return (x << y) | x >>> (32 - y); 
    } 
    // 单元摘要计算函数 
    private void encrypt() { 
        for (int i = 16; i <= 79; i++) { 
            tmpData[i] = f4(tmpData[i - 3] ^ tmpData[i - 8] ^ tmpData[i - 14] ^ 
                    tmpData[i - 16], 1); 
        } 
        int[] tmpabcde = new int[5]; 
        for (int i1 = 0; i1 < tmpabcde.length; i1++) { 
            tmpabcde[i1] = digestInt[i1]; 
        } 
        for (int j = 0; j <= 19; j++) { 
            int tmp = f4(tmpabcde[0], 5) + 
                f1(tmpabcde[1], tmpabcde[2], tmpabcde[3]) + tmpabcde[4] + 
                tmpData[j] + 0x5a827999; 
            tmpabcde[4] = tmpabcde[3]; 
            tmpabcde[3] = tmpabcde[2]; 
            tmpabcde[2] = f4(tmpabcde[1], 30); 
            tmpabcde[1] = tmpabcde[0]; 
            tmpabcde[0] = tmp; 
        } 
        for (int k = 20; k <= 39; k++) { 
            int tmp = f4(tmpabcde[0], 5) + 
                f2(tmpabcde[1], tmpabcde[2], tmpabcde[3]) + tmpabcde[4] + 
                tmpData[k] + 0x6ed9eba1; 
            tmpabcde[4] = tmpabcde[3]; 
            tmpabcde[3] = tmpabcde[2]; 
            tmpabcde[2] = f4(tmpabcde[1], 30); 
            tmpabcde[1] = tmpabcde[0]; 
            tmpabcde[0] = tmp; 
        } 
        for (int l = 40; l <= 59; l++) { 
            int tmp = f4(tmpabcde[0], 5) + 
                f3(tmpabcde[1], tmpabcde[2], tmpabcde[3]) + tmpabcde[4] + 
                tmpData[l] + 0x8f1bbcdc; 
            tmpabcde[4] = tmpabcde[3]; 
            tmpabcde[3] = tmpabcde[2]; 
            tmpabcde[2] = f4(tmpabcde[1], 30); 
            tmpabcde[1] = tmpabcde[0]; 
            tmpabcde[0] = tmp; 
        } 
        for (int m = 60; m <= 79; m++) { 
            int tmp = f4(tmpabcde[0], 5) + 
                f2(tmpabcde[1], tmpabcde[2], tmpabcde[3]) + tmpabcde[4] + 
                tmpData[m] + 0xca62c1d6; 
            tmpabcde[4] = tmpabcde[3]; 
            tmpabcde[3] = tmpabcde[2]; 
            tmpabcde[2] = f4(tmpabcde[1], 30); 
            tmpabcde[1] = tmpabcde[0]; 
            tmpabcde[0] = tmp; 
        } 
        for (int i2 = 0; i2 < tmpabcde.length; i2++) { 
            digestInt[i2] = digestInt[i2] + tmpabcde[i2]; 
        } 
        for (int n = 0; n < tmpData.length; n++) { 
            tmpData[n] = 0; 
        } 
    } 
    // 4字节数组转换为整数 
    private int byteArrayToInt(byte[] bytedata, int i) { 
        return ((bytedata[i] & 0xff) << 24) | ((bytedata[i + 1] & 0xff) << 16) | 
        ((bytedata[i + 2] & 0xff) << 8) | (bytedata[i + 3] & 0xff); 
    } 
    // 整数转换为4字节数组 
    private void intToByteArray(int intValue, byte[] byteData, int i) { 
        byteData[i] = (byte) (intValue >>> 24); 
        byteData[i + 1] = (byte) (intValue >>> 16); 
        byteData[i + 2] = (byte) (intValue >>> 8); 
        byteData[i + 3] = (byte) intValue; 
    } 
    // 将字节转换为十六进制字符串 
    private static String byteToHexString(byte ib) { 
        char[] Digit = { 
                '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 
                'D', 'E', 'F' 
            }; 
        char[] ob = new char[2]; 
        ob[0] = Digit[(ib >>> 4) & 0X0F]; 
        ob[1] = Digit[ib & 0X0F]; 
        String s = new String(ob); 
        return s; 
    } 
    // 将字节数组转换为十六进制字符串 
    private static String byteArrayToHexString(byte[] bytearray) { 
        String strDigest = ""; 
        for (int i = 0; i < bytearray.length; i++) { 
            strDigest += byteToHexString(bytearray[i]); 
        } 
        return strDigest; 
    } 
    // 计算sha-1摘要,返回相应的字节数组 
    public byte[] getDigestOfBytes(byte[] byteData) { 
        process_input_bytes(byteData); 
        byte[] digest = new byte[20]; 
        for (int i = 0; i < digestInt.length; i++) { 
            intToByteArray(digestInt[i], digest, i * 4); 
        } 
        return digest; 
    } 
    // 计算sha-1摘要,返回相应的十六进制字符串 
    public String getDigestOfString(byte[] byteData) { 
        return byteArrayToHexString(getDigestOfBytes(byteData)); 
    } 
    public static void main(String[] args) { 
        String data = "123456"; 
        System.out.println(data); 
        String digest = new SHA1().getDigestOfString(data.getBytes()); 
        System.out.println(digest);
       
       // System.out.println( ToMD5.convertSHA1(data).toUpperCase());
    } 
} 
/**
 * Ticket封装类
 * @author lh
 */
public class Ticket {
	private String errcode;
	private String errmsg;
	private String ticket;
	private String expires_in;
	//省略get,set方法
}
/**
 * Signature封装类
 * @author lh
 */
public class SignatureInfo {
	private String signature;
	private String timestamp;
	private String noncestr;
	private String url;
	//省略get,set方法
} 

获取ticket

/**
 * 获取ticket
 * @param accessToken
 * @return
 */
public static Ticket getTicket(String accessToken){
	Ticket ticket = new Ticket();
	String getTicket = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi";
	String url = getTicket.replace("ACCESS_TOKEN",accessToken);
	JSONObject jsonObject = httpRequest(url, "POST", null);
	if (null != jsonObject) {
		if (0 != jsonObject.getInt("errcode")) {
			log.error("获取ticket失败 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg"));
		}else{
			ticket.setErrcode(jsonObject.getString("errcode"));
			ticket.setErrmsg(jsonObject.getString("errmsg"));
			ticket.setExpires_in(jsonObject.getString("expires_in"));
			ticket.setTicket(jsonObject.getString("ticket"));
		}
	}
	return ticket;
}

获取Signature方法

/**
 * 签名算法
 * @param ticket
 * @return
 */
public static SignatureInfo getSignature(SignatureInfo sign,Ticket ticket){
	String data = "jsapi_ticket="+ticket.getTicket()+"&noncestr="+sign.getNoncestr()+"×tamp="+sign.getTimestamp()+"&url="+sign.getUrl();
	String signature =  new SHA1().getDigestOfString(data.getBytes()); 
	sign.setSignature(signature);
	log.info("signature="+sign.getSignature());
	return sign;
}

最后综合上面方法,封装主函数

public String jssdk_demo(HttpServletRequest request,HttpServletResponse response){
	String param = request.getQueryString();//获取请求参数
	String url = request.getServletPath();//获取请求路径(不带参数)
	if(param!=null){
		url = url+"?"+param;//组合成完整请求URL
	}
	String projectnameP = request.getContextPath();
    String projectName = projectnameP.substring(projectnameP.lastIndexOf('/')+1,projectnameP.length());  //获取工程名,如testW
	if(!"".equals(projectName)){
		projectName ="/"+projectName;
	}
	String port = String.valueOf(request.getServerPort());//获取端口号
	if(!"80".equals(port)){//不是80端口时需加端口号
		port = ":"+port;
	}else{
		port = "";
	}
	String strBackUrl = "http://" + request.getServerName()+port+projectName+url;//完整的请求路径http://192.168.1.117/testW/+路径
	AccessToken token = null;
	if(TimedTask.accessToken==null || TimedTask.accessToken.getToken()==""){//token失效,重新获取,获取方法参考第二篇博文,在这由于篇幅问题暂不列出
		token = WeixinUtil.getAccessToken(TimedTask.appid, TimedTask.appsecret);/
	}else{
		token = TimedTask.accessToken;
	}
	Ticket ticket = null;
	if(TimedTask.ticket ==null || TimedTask.ticket.getTicket()==""){
		ticket = WeixinUtil.getTicket(token.getToken());//获取ticket
	}else{
		ticket = TimedTask.ticket;
	}
	SignatureInfo siInfo = new SignatureInfo();
	siInfo.setNoncestr(RandomStringUtils.randomAlphanumeric(20));//随机字符串
	siInfo.setTimestamp(String.valueOf(System.currentTimeMillis()));//随机时间截
	siInfo.setUrl(strBackUrl);
	siInfo = WeixinUtil.getSignature(siInfo, ticket);
	request.setAttribute("siInfo",siInfo);
	return "weixin/jssdk_demo";
}

到此需要准备的数据就已经全部完成了,现在我们看看前台jssdk_demo.jsp页面是如何调用的

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%>
<c:set var="BS" value="${pageContext.request.contextPath}"></c:set>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>jssdk_demo</title>
<script type="text/javascript" src="${BS}/js/jquery-1.7.2.min.js"></script>
<script type="text/javascript" src="${BS}/js/weixin/jweixin-1.2.0.js"></script>
<link href="${BS}/css/weixin/weixinStyle.css" type="text/css" rel="stylesheet" />
<link href="${BS}/css/weixin/weixinmain.css" type="text/css" rel="stylesheet"/>
//百度地图没有密匙的可以去官网申请
<script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=密匙"></script>
<script type="text/javascript" src="http://developer.baidu.com/map/jsdemo/demo/convertor.js"></script> 
<script type="text/javascript" src="https://3gimg.qq.com/lightmap/components/geolocation/geolocation.min.js"></script>
</head>
<input type="hidden" id="timestamp" value="${siInfo.timestamp}">
<input type="hidden" id="nonceStr" value="${siInfo.noncestr}">
<input type="hidden" id="signature" value="${siInfo.signature}">
<input type="hidden" id="longitude" value="">
<input type="hidden" id="latitude" value="">
<input type="hidden" id="weixinOperId" value="微信appid">
<script type="text/javascript">
var phoneWidth = parseInt(window.screen.width);
var phoneScale = phoneWidth/640;
var ua = navigator.userAgent;
if (/Android (\d+\.\d+)/.test(ua)){
    var version = parseFloat(RegExp.$1);
    if(version>2.3){
        document.write("<meta name=\"viewport\" content=\"width=device-width,initial-scale=1.0, minimum-scale = 1.0, maximum-scale = "+phoneScale+", target-densitydpi=device-dpi\">");
    }else{
        document.write("<meta name=\"viewport\" content=\"width=device-width, target-densitydpi=device-dpi\">");
    }
}else{
    document.write("<meta name=\"viewport\" content=\"width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no,target-densitydpi=device-dpi\">");
}
$(function(){
	$(".nav a").click(function(){
		$('.nav a').removeClass('active');
		$(this).addClass('active');
		var nav = $(this).attr("nav");
		$("section div[class='desc']").each(function(i,val){
			if($(this).attr("nav")==nav){
				$(this).show();
			}else{
				$(this).hide();
			}
		});
	});
});
var signature = $("#signature").val();
var nonceStr = $("#nonceStr").val();
var timestamp = $("#timestamp").val();
var weixinOperId = $("#weixinOperId").val();
wx.config({
    debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
    appId: weixinOperId, // 必填,公众号的唯一标识
    timestamp:timestamp, // 必填,生成签名的时间戳
    nonceStr: nonceStr, // 必填,生成签名的随机串
    signature:signature,// 必填,签名
    jsApiList: [ 
        'openLocation',
		'getLocation'
    ] // 必填,需要使用的JS接口列表,所有JS接口列表见官方文档附录2
});
wx.ready(function(){
	getLocation();
});
wx.error(function(res){
	//alert("error");
});
</script>
<script type="text/javascript">
$(function () {
	$("#wdialogTitle2").text("信息提示");
    $("#wdialogConfirm2").click(function(i,val){
    	$("#wdialog2").hide();
    });
    $(".warn_message").text("");
    //刷新定位
    $(".SelectCityWrap .cityTit .r").click(function () {
        $(this).addClass("hover");
        getLocation();
    });
    $("b.search").click(function () {
        searchMap($("#indexSearchBox").val());
        return false;
    });
});

var latitude,longitude;
//获取当前地址
function getLocation(){
	wx.getLocation({
	    type: 'gcj02', // 默认为wgs84的gps坐标,如果要返回直接给openLocation用的火星坐标,可传入'gcj02'
	    success: function (res) {
	        latitude = res.latitude; // 纬度,浮点数,范围为90 ~ -90
	        longitude = res.longitude; // 经度,浮点数,范围为180 ~ -180。
	        var speed = res.speed; // 速度,以米/每秒计
	        var accuracy = res.accuracy; // 位置精度
	        getAddressInfo2(longitude,latitude);
	    },cancel: function (res){
	        $("#wdialogContent2").text("用户拒绝授权获取地理位置");
        	$("#wdialog2").show();
	    }
	});
}

var addId = "choseAdd";
var longiText = "longitude";
var latiText = "latitude";
//打开百度地图并标记当前定位地址
function showMapArea(){
	var myGeo = new BMap.Geocoder();
	var pt = new BMap.Point(longitude,latitude);
 	translateCallback2 = function (point){
 		createBaiduMap(point.lng,point.lat,1);
	};
    setTimeout(function(){
    	BMap.Convertor.translate(pt,2,translateCallback2);     //火星经纬度转成百度坐标,2变成0时,则是默认的wgs84的gps坐标转换成百度坐标
	}, 100);
}
//调用百度地图API,经纬度转化成实际地址
function getAddressInfo2(lon,lat) {
	var myGeo = new BMap.Geocoder();
	var pt = new BMap.Point(lon,lat);
 	translateCallback2 = function (point){
		myGeo.getLocation(point, function(rs) {
			var addComp = rs.addressComponents;
			var addr = addComp.province+ addComp.city + addComp.district+ addComp.street+ addComp.streetNumber;
			$("#nowAdd").text(addr);
		});
	};
    setTimeout(function(){
    	BMap.Convertor.translate(pt,2,translateCallback2);     //火星经纬度转成百度坐标
	}, 100);
}
function returnAdd(){
	$("#addressArea").show();
	$("#mapArea").hide();
}
function confirmC(){
	var address = $("#choseAdd").text();
	var longiText = $("#longitude").val();
	var latiText = $("#latitude").val();
	if(latiText=="" || longitude==""){
		$("#wdialogContent2").text("请先选择您当前位置");
     	$("#wdialog2").show();
	}
}
function getNavi(){
	wx.openLocation({
	    latitude: latitude, // 纬度,浮点数,范围为90 ~ -90
	    longitude: longitude, // 经度,浮点数,范围为180 ~ -180。
	    name: '我现在在这里', // 位置名
	    address: $("#nowAdd").text(), // 地址详情说明
	    scale: 20, // 地图缩放级别,整形值,范围从1~28。默认为最大
	    infoUrl: 'https://www.baidu.com/' // 在查看位置界面底部显示的超链接,可点击跳转
	});
}
</script>
<body>
	<div  id="addressArea" style="min-height:526px;">
		<section class="SelectCityWrap" style="width:98%;">
		    <h3 class="cityTit" style="width:100%;background:#DDDDDD;">
		        <span class="l left" style="max-width:80%;height:45px;overflow:hidden;">当前地址:<span class="val" style="height:45px;max-height:45px;overflow:hidden;" id="nowAdd">${nowAdd}</span></span>
		        <span class="r right"></span>
		    </h3>
		    <section class="content">
				<div class="nav">
			    	<a class=""  nav="nav_1" onclick="getNavi()">当前地址导航</a>
			    	<a nav="nav_2" onclick="showMapArea()">地图选择</a>
			    </div>
				<div class="desc" nav="nav_1">
			    </div>
				<div class="desc" nav="nav_2" style="display:none;width:100%;">
					<section  class="SelectCityWrap" style="width:100%;">
						<h3 class="cityTit" style="text-align:left;width:100%;background:#DDDDDD;">
							<span class="" style="padding-left:5px;">已选地址:<span class="val" id="choseAdd">点击地图可选择地址</span></span>
						</h3>
						<!-- 搜索 -->
						<div style="height:auto;" class="indexSearch">
							<div class="content search">
								<input type="search" id="indexSearchBox" placeholder="点击地图可选择地址"  style="height: 38px;line-height:35px;width:100%;max-width:570px;padding-left:10px;font-size: 16px;" class="left">
								<span></span>
								<b class="search"></b>
							</div>
						</div>
						<!-- 搜索 end-->
						<div id="container" style="width:100%;height:300px;"></div >
						<section id="r_content" style="margin-bottom:55px;">
							<div class="r_shadow">
								<div class="r_searchlist positiolist" id="search-result"></div>
							</div>
						</section>
					</section> 	          
			    </div>
			</section>
		</section>
	</div>
	<div  id="mapArea" style="min-height:526px;display:none;">
		<header id="r_header" class="r_title">
		    <a class="r_returnbk" onclick="returnAdd()">
		        <img src="${BS}/images/weixin/r_icon7.png" alt="">
		    </a>
		    <a style="float:right;padding-right:12px;" onclick="confirmC()">确定</a>
		</header>
		<section  class="SelectCityWrap">
			<!-- 搜索 -->
		    <div style="height:auto;" class="indexSearch">
		        <div class="content search">
		        	<input type="search" id="indexSearchBox" placeholder="点击地图可选择地址"  style="height: 38px;line-height:35px;width:100%;max-width:570px;padding-left:10px;font-size: 16px;" class="left">
		            <span></span>
		            <b class="search"></b>
		        </div>
		    </div>
		    <!-- 搜索 end-->
			<div id="container" style="width:100%;height:300px;"></div >
			<section id="r_content">
		        <div class="r_shadow">
		            <div class="r_searchlist positiolist" id="search-result">
		            </div>
		        </div>
		    </section>
		</section>
	</div>
	<script type="text/javascript" src="${BS}/js/weixin/mapLocation.js"></script>
</body>
</html>

mapLocation.js,为封装好的百度地图的方法,具体看各自需求可进行修改:

function getHtml5Location() {
	if(navigator.geolocation) {
		// navigator.geolocation.watchPosition(updateLocation, handleLocationError, {
		navigator.geolocation.getCurrentPosition(updateLocation, handleLocationError,{
	        // 指示浏览器获取高精度的位置,默认为false
	        enableHighAcuracy: true,
	        // 指定获取地理位置的超时时间,默认不限时,单位为毫秒
	        //timeout: 5000,
	        // 最长有效期,在重复获取地理位置时,此参数指定多久再次获取位置。
	        maximumAge: 20000
   		});
	}else{
		$("#wdialogContent2").text("无法获取您当前地理位置");
     	$("#wdialog2").show();
	}
}
function updateLocation(position) {
	var latitude = position.coords.latitude;
	var longitude = position.coords.longitude;
	var accuracy = position.coords.accuracy;
	// 如果accuracy的值太大,我们认为它不准确,不用它计算距离
	if (accuracy >= 1000) {
		return;
	}
	var pt = new BMap.Point(longitude,latitude);
	setTimeout(function(){
		BMap.Convertor.translate(pt,0,translateCallback);     //真实经纬度转成百度坐标
	}, 100);
	translateCallback = function (point){
		createBaiduMap(point.lat,point.lng,1);
	};
}

function handleLocationError(error) {
	switch (error.code) {
		case 0:
			$("#wdialogContent2").text("尝试获取您的位置信息时发生错误:"+ error.message);
     		$("#wdialog2").show();
			break;
		case 1:
			$("#wdialogContent2").text("用户拒绝了获取位置信息请求");
     		$("#wdialog2").show();
			break;
		case 2:
			$("#wdialogContent2").text("浏览器无法获取您的位置信息:"+ error.message);
     		$("#wdialog2").show();
			break;
		case 3:
			$("#wdialogContent2").text("获取您位置信息超时");
     		$("#wdialog2").show();
			break;
	}
}
/**
 * 传人坐标获得详细地址
 * @param lat
 * @param lon
 */
function getAddressInfo(lon,lat,type) {
	var myGeo = new BMap.Geocoder();
	var pt = new BMap.Point(lon,lat);
 	translateCallback2 = function (point){
		myGeo.getLocation(point, function(rs) {
			var addComp = rs.addressComponents;
			//rs.surroundingPois;//附近地址
			var addr = addComp.province+ addComp.city + addComp.district+ addComp.street+ addComp.streetNumber;
			searchMap(addr);
		});
	};
    setTimeout(function(){
    	if(type==1){
    		BMap.Convertor.translate(pt,0,translateCallback2);     //真实经纬度转成百度坐标
    	}else{
    		translateCallback2(pt);
    	}
	}, 100);
}
var map = null;
function setMapEvent(){
    map.enableDragging();//启用地图拖拽事件,默认启用(可不写)
    map.enableScrollWheelZoom();//启用地图滚轮放大缩小
    map.enableDoubleClickZoom();//启用鼠标双击放大,默认启用(可不写)
    map.enableKeyboard();//启用键盘上下左右键移动地图
}
var marker = null;
function createBaiduMap(longitude, latitude,type) { 
	if(map==null){
		map =new BMap.Map("container"); 
	}
	setMapEvent();
	mSearchManager.clear();
	var	pt= new BMap.Point(longitude,latitude);  
	translateCallback = function (point){
		var	point= new BMap.Point(point.lng, point.lat);  
		map.setCenter(point);
	    map.centerAndZoom(point, 16);  
	    // 添加带有定位的导航控件
	    var navigationControl = new BMap.NavigationControl({
	       // 靠左上角位置
	       anchor: BMAP_ANCHOR_TOP_LEFT,
	       // LARGE类型
	       type: BMAP_NAVIGATION_CONTROL_LARGE,
	       // 启用显示定位
	       enableGeolocation: true
	    });
	    map.addControl(navigationControl);  
	    marker = new BMap.Marker(point); //标注  
	    marker.enableDragging();
	    marker.addEventListener("dragend",getAttr);
		function getAttr(){
			var p = marker.getPosition();       //获取marker的位置
			getAddressInfo(p.lng,p.lat);
		}
	    map.clearOverlays();
	    map.addOverlay(marker);
	    map.addEventListener("click", function(e){ 
	    	var gc = new BMap.Geocoder(); 
	    	var pt = new BMap.Point(e.point.lng,e.point.lat); 
	    	document.getElementById(longiText).value = e.point.lng;
	    	document.getElementById(latiText).value = e.point.lat;
	    	window.map.removeOverlay(marker);
    	    marker = new BMap.Marker(e.point);//创建一个覆盖物  
	        map.addOverlay(marker);//增加一个标示到地图上  
	    	var dress = gc.getLocation(pt, function(rs){
	    		var addComp = rs.addressComponents;
    			var address = addComp.province+addComp.city+addComp.district+addComp.street+addComp.streetNumber;
    			if(typeof(addId)!="undefined" && addId !=null){
    				$("#"+addId).text(address);
    			}
    			searchMap(address);
    		});
	    });
	    // 添加定位控件
//	    var geolocationControl = new BMap.GeolocationControl();
//	    geolocationControl.addEventListener("locationSuccess", function(e){
//	    	  window.map.removeOverlay(marker);
//	    	  marker = new BMap.Marker(e.point);//创建一个覆盖物  
//	          map.addOverlay(marker);//增加一个标示到地图上  
//	          map.panTo(e.point); 
		      // 定位成功事件
//		      var address = '';
//		      address += e.addressComponent.province;
//		      address += e.addressComponent.city;
//		      address += e.addressComponent.district;
//		      address += e.addressComponent.street;
//		      address += e.addressComponent.streetNumber;
//		      searchMap(address);
	    	 //getLocation();
//	    });
//	    geolocationControl.addEventListener("locationError",function(e){
//	        // 定位失败事件
//	        alert(e.message);
//	    });
	    //地图拖动事件
	    /*map.addEventListener("dragging", function(evt){
	       var offsetPoint = new BMap.Pixel(evt.offsetX, evt.offsetY); 
	    });*/
//	    map.addControl(geolocationControl);
	    // 添加带有定位的导航控件
	};
    setTimeout(function(){
    	if(type==1){
    		translateCallback(pt);
    	}else{
    		BMap.Convertor.translate(pt,0,translateCallback);     //真实经纬度转成百度坐标
    	}
	}, 100);
} 
var mSearchManager = new SearchManager();
var isR = false;
function SearchManager(){
	this.SearchResultList = new Array();
	this.showSearchResult = function(poi){
		var index = this.SearchResultList.length;
		var marker = new BMap.Marker(poi.point);
        var a=document.createElement("a");  
        var p=document.createElement("P");
        this.SearchResultList[index] = new KzSearchResult( marker , poi , a , p);
        var address = "";
		if(this.SearchResultList[index].poi.province!=undefined && this.SearchResultList[index].poi.province!=null
				&& this.SearchResultList[index].poi.province !=""){
			address = this.SearchResultList[index].poi.province;
		}
		if(this.SearchResultList[index].poi.city!=undefined && this.SearchResultList[index].poi.city!=null
				&& this.SearchResultList[index].poi.city !=""){
			address +=this.SearchResultList[index].poi.city;
		}
    	var div = document.getElementById("search-result");
        a.href="javascript:mSearchManager.zoomto("+index+")";
        var $a = $("<a style=\"padding-left:10px;\" href=\"javascript:mSearchManager.zoomto("+index+")\"></a>");
        var section = $("<section class=\"listbox nobg list\" style=\"height:60px;\"></section>");
        var div1 = $("<div class=\"jobname\" style=\"height:25px;line-height:25px;\">"+poi.title+"</div>");
        var div2 = $("<div class=\"time\" style=\"height:25px;line-height:25px;color:#026AFF;\"></div>");
        var div3 = $("<div class=\"box1\" style=\"height:35px;line-height:35px;\">"+address+poi.address+"</div>");
        $a.append(div1).append(div2).append(div3);
        section.append($a);
        $("#search-result").append(section);
	};
	this.clear = function(){
		var div = $("#search-result section");
		div.remove();
		window.map.removeOverlay(marker);
		this.SearchResultList.length = 0;
	};
	this.clear2 = function(){
		var div = $("#search-result section");
		div.remove();
		this.SearchResultList.length = 0;
	};
	this.zoomto = function (index){
		$(".time").each(function(i,val){
			if(i==index){
				$(this).text("当前位置");
			}else{
				$(this).text("");
			}
		});
		window.map.removeOverlay(marker);
		marker = new BMap.Marker(this.SearchResultList[index].poi.point);
		window.map.addOverlay(marker);
		window.map.centerAndZoom(this.SearchResultList[index].poi.point, 16);
		document.getElementById(longiText).value = this.SearchResultList[index].poi.point.lng;
		document.getElementById(latiText).value = this.SearchResultList[index].poi.point.lat;
		if(typeof(addId)!="undefined" && addId !=null){
			document.getElementById(addId).innerHTML = this.SearchResultList[index].poi.title;
		}
	};	
}
function KzSearchResult(m , b ,a , p){
	this.marker = m;
	this.poi = b;
	this.a = a;
	this.p = p;
}
function searchMap(area) {
   if(map==null){
		map =new BMap.Map("container"); 
   }
   var ls = new BMap.LocalSearch(map);
   ls.setSearchCompleteCallback(function(rs) {
	  mSearchManager.clear2();
      if(ls.getStatus() == BMAP_STATUS_SUCCESS) {
    	for(var index=0;index<rs.getCurrentNumPois();index++){
	        var poi = rs.getPoi(index);
	        if (poi) {
	        	mSearchManager.showSearchResult(poi);
	        }
      	}
      }
   });
   ls.search(area);
}

本文也发布到另外一个网站,如果只有那边才有帐号的,有需要的可以收藏一下微信JS-SDK之地理位置的获取,集成百度地图实现在线地图搜索

到此该篇博文已经讲解完毕,如有问题,欢迎大家指出,一起探讨

posted @ 2017-05-15 10:07  半山闲人  阅读(1200)  评论(0编辑  收藏  举报