HTML5獲取定位簡(jiǎn)單方案

由來(lái)

一個(gè)客戶提出一個(gè)需求,想在xiunobbs中實(shí)現(xiàn),發(fā)帖時(shí)顯示 定位信息,然后在查看時(shí) 可以實(shí)現(xiàn),如果是Android或IOS端安裝了百度地圖APP的可以喚起,否則就和網(wǎng)頁(yè)P(yáng)C端的一樣,直接跳轉(zhuǎn)到網(wǎng)頁(yè)版的百度地圖并定位到改點(diǎn)。

簡(jiǎn)單實(shí)現(xiàn)步驟:

  • 發(fā)帖時(shí)增加按鈕,可以選擇是否獲取定位
  • 使用HTML5 自帶的api來(lái)獲取 https://developer.mozilla.org/zh-CN/docs/Web/API/Geolocation/Using_geolocation
  • 將獲取到的經(jīng)緯度數(shù)值 通過(guò) 百度JavaScript API來(lái)逆向解析,得到省、市、縣、街道等信息。
  • 查看帖子時(shí),將經(jīng)緯度再次拼接成URI,供客戶端喚起服務(wù)。

大致步驟如上吧,具體如何制作的xiunobbs插件這里就不談了。

geolocation對(duì)象

Geolocation:https://developer.mozilla.org/zh-CN/docs/Web/API/Geolocation

該對(duì)象有三個(gè)方法:

增加按鈕

這個(gè)不是本篇主要內(nèi)容,也就一筆帶過(guò)吧。

image.png

hook了post_message_after.htm 這個(gè)位置加入了

<div class="form-group">
    <button class="btn-primary get-location">使用位置</button><span class="ml-2 badge badge-pill badge-secondary icon-location-arrow location-str d-none">Secondary</span>
</div>
<input type="hidden" name="location" value="" id="location">

獲取當(dāng)前定位

利用getCurrentPosition()方法來(lái)獲取位置得到經(jīng)緯度。

語(yǔ)法

navigator.geolocation.getCurrentPosition(success, error, options)

參數(shù)

  • success

    成功得到位置信息時(shí)的回調(diào)函數(shù),使用Position 對(duì)象作為唯一的參數(shù)。

  • error 可選

    獲取位置信息失敗時(shí)的回調(diào)函數(shù),使用 PositionError 對(duì)象作為唯一的參數(shù),這是一個(gè)可選項(xiàng)。

  • options 可選

    一個(gè)可選的PositionOptions 對(duì)象。

于是簡(jiǎn)單寫(xiě)了下代碼

$(".get-location").click(function () {
    // $(this).preventDefault();
    var options = {
        enableHighAccuracy : true,
        maximumAge : 1000
    };
    // alert('this is getLocation()');
    if (navigator.geolocation) {
        //瀏覽器支持geolocation
        console.log('support');
        $(".location-str").removeClass("d-none");
        $(".location-str").text("正在獲取中……")
        navigator.geolocation.getCurrentPosition(onSuccess, onError, options);
    } else {
        //瀏覽器不支持geolocation
        alert('您的瀏覽器不支持地理位置定位');
    }
    return false;

});

onSuccess和onError分別如下

function onSuccess(position) {
    // 用戶位置字符串
    var locationStr = "";
    //返回用戶位置
    //經(jīng)度
    var longitude = position.coords.longitude;
    //緯度
    var latitude = position.coords.latitude;
    $(".location-str").text('當(dāng)前地址的經(jīng)緯度:經(jīng)度' + longitude + ',緯度' + latitude);
    

}

function onError(error) {
    switch (error.code) {
        case 1:
            alert("位置服務(wù)被拒絕");
            break;
        case 2:
            alert("暫時(shí)獲取不到位置信息");
            break;
        case 3:
            alert("獲取信息超時(shí)");
            break;
        case 4:
            alert("未知錯(cuò)誤");
            break;
    }
    

}

這樣簡(jiǎn)單的就能獲取到經(jīng)緯度了。

結(jié)合百度地圖逆向解析

JavaScript API:http://lbsyun.baidu.com/index.php?title=jspopular/guide/geocoding

API v2.0類(lèi)參考:http://lbsyun.baidu.com/cms/jsapi/reference/jsapi_reference.html

它給出的示例代碼如下

var map = new BMap.Map("l-map");   // 這個(gè)是顯示的div class類(lèi)名 如果不顯示無(wú)需寫(xiě)   
map.centerAndZoom(new BMap.Point(116.404, 39.915), 11);      
// 創(chuàng)建地理編碼實(shí)例      
var myGeo = new BMap.Geocoder();      
// 根據(jù)坐標(biāo)得到地址描述    
myGeo.getLocation(new BMap.Point(116.364, 39.993), function(result){      
    if (result){      
    alert(result.address);      
    }      
});
image.png
image.png

完善一下之前的onSuccess函數(shù)

function onSuccess(position) {
    // 用戶位置字符串
    var locationStr = "";
    //返回用戶位置
    //經(jīng)度
    var longitude = position.coords.longitude;
    //緯度
    var latitude = position.coords.latitude;
    $(".location-str").text('當(dāng)前地址的經(jīng)緯度:經(jīng)度' + longitude + ',緯度' + latitude);
    
    var point = new BMap.Point(longitude, latitude);
    var gc = new BMap.Geocoder();
    gc.getLocation(point, function(rs) {
        locationStr = rs.address;
        $(".location-str").text(locationStr);
        $("#location").val(locationStr + "|" + longitude + "|" + latitude);
        console.log($("#location").val());
    });
    
}

將之前獲取到的經(jīng)緯度,傳參進(jìn)入,調(diào)用這個(gè)方法,然后拿到解析后的address地址內(nèi)容。將id為location的這個(gè)內(nèi)容賦值為address字符串內(nèi)容。(這個(gè)是為了提交到后端,下次讀取帖子時(shí)可以拿到。PS:這里得注意下XSS)

顯示效果:

image.png

(PC端不準(zhǔn),還有其他因素,結(jié)果定位到洛杉磯了):)

點(diǎn)擊喚起百度地圖APP

簡(jiǎn)單的定位也拿到了,然后該顯示了。

hook顯示位

這里還是簡(jiǎn)單帶過(guò)下顯示的地方,hook了thread_plugin_before.htm這個(gè)點(diǎn)。

<?php if($first['location']!=''){
list($location_str,$lng,$lat) = explode('|',$first['location']);

// 網(wǎng)頁(yè)版
$baidu_pc_map_url = 'http://api.map.baidu.com/geocoder?location='.$lat.','.$lng.'&output=html&src=webapp.baidu.openAPIdemo';
// 安卓端
$android_url = 'bdapp://map/geocoder?location='.$lat.','.$lng.'&src=andr.baidu.openAPIdemo';
// IOS端
$ios_url = 'baidumap://map/geocoder?location='.$lat.','.$lng.'&src=ios.baidu.openAPIdemo';
?>
<div>

    <span class="d-inline-block badge badge-pill badge-secondary icon-location-arrow location-str d-none"><a
            href="<?php echo $baidu_pc_map_url;?>" style="text-decoration: none;color: #fff;" id="location_url"><?php echo $location_str;?></a></span>
</div>
<?php } ?>

下面的js操作是hook的thread_js.htm。

喚起應(yīng)用

百度地圖調(diào)起:http://lbsyun.baidu.com/index.php?title=uri

喚起的邏輯簡(jiǎn)單如下:

  • PC端:直接顯示百度地圖web地址
  • Mobile端:
    • Android端:Android的百度地圖APP
    • IOS|iPhone|iPad端:iOS的百度地圖APP

利用uri的反向地址解析來(lái)完成,從手冊(cè)中可以查到三個(gè)分別是

  • http://api.map.baidu.com/geocoder 網(wǎng)頁(yè)
  • bdapp://map/geocoder?location 安卓
  • baidumap://map/geocoder?location IOS

然后就是利用JavaScript來(lái)判斷下:

<script>
    var browser={
        versions:function(){
            var u = navigator.userAgent, app = navigator.appVersion;
            return {//移動(dòng)終端瀏覽器版本信息
                trident: u.indexOf('Trident') > -1, //IE內(nèi)核
                presto: u.indexOf('Presto') > -1, //opera內(nèi)核
                webKit: u.indexOf('AppleWebKit') > -1, //蘋(píng)果、谷歌內(nèi)核
                gecko: u.indexOf('Gecko') > -1 && u.indexOf('KHTML') == -1, //火狐內(nèi)核
                mobile: !!u.match(/AppleWebKit.*Mobile.*/), //是否為移動(dòng)終端
                ios: !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/), //ios終端
                android: u.indexOf('Android') > -1 || u.indexOf('Linux') > -1, //android終端或者uc瀏覽器
                iPhone: u.indexOf('iPhone') > -1 , //是否為iPhone或者QQHD瀏覽器
                iPad: u.indexOf('iPad') > -1, //是否iPad
                webApp: u.indexOf('Safari') == -1 //是否web應(yīng)該程序,沒(méi)有頭部與底部
            };
        }(),
        language:(navigator.browserLanguage || navigator.language).toLowerCase()
    }



    $("#location_url").click(function (event) {
        event.preventDefault();
        var web_scheme = "<?php echo $baidu_pc_map_url;?>";
        var scheme = '';
        if(browser.versions.mobile || browser.versions.ios || browser.versions.android ||
            browser.versions.iPhone || browser.versions.iPad){
            console.log('mobile');
            if (browser.versions.ios || browser.versions.iPhone || browser.versions.iPad) {
                scheme = "<?php echo $ios_url;?>";

            }else if (browser.versions.android) {
                scheme = "<?php echo $android_url;?>";
            }
        }else{

            scheme = "<?php echo $baidu_pc_map_url;?>";
            console.log('pc',scheme);

        }
        // 輪詢(xún)判斷能否喚起,如果不能喚起 則使用網(wǎng)頁(yè)版
        window.location.href = scheme;
        var startTime = Date.now();
        var count = 0;
        var endTime = 0;
        var t = setInterval(function () {
            count += 1;
            endTime = Date.now() - startTime;
            if (endTime > 800) {
                clearInterval(t);
            }
            if (count < 30) return;
            if (!(document.hidden || document.webkitHidden)) {
                window.location.href = web_scheme;
            }
        }, 20);
    })
</script>

然后就可以喚起應(yīng)用并顯示標(biāo)注了地圖上的點(diǎn)。

Reference

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容