小程式實現附近三公里搜尋和地圖路線導航(改版)

沉默的小猴子發表於2018-08-01

##本片部落格主要介紹的是小程式利用地圖搜尋附近三公里資訊並導航路線或者複製路線開啟地圖導航。可以直接在微信內建開啟導航。

開篇先提一下,網上有很多關於小程式搜尋框的,地圖地點資訊檢索的,路線導航的,以及一個找事吧APP模仿的小程式。我也看過這些內容,整理一下,就是我今天要展示的。

慣例,先上整體效果圖:
在這裡插入圖片描述
這是點選藥店,搜尋附近20個藥店資訊。
這裡寫圖片描述
可以列印出20條資訊資料,自己可根據實際情況展示。同時點選搜尋出來的地址資訊,可以複製到手機貼上板,方便在自己手機地圖中導航,因為騰訊自帶的多數人不習慣用。
附上小程式的複製文字的方法:

wx.showModal({
      title: '確定複製地址資訊嗎?',
      content: e.currentTarget.dataset.text,
      success: function (res) {
        if(res.confirm == true){
          wx.setClipboardData({
            data: e.currentTarget.dataset.text,
            success: function (res) {
              wx.getClipboardData({
                success: function (res) {
                  //console.log(res)
                }
              })
            }
          })
        }else{
          wx.showModal({
            title: '抱歉',
            content: '你取消了複製資訊',
            showCancel: false
          })
        }
        
      }
    })

在這裡插入圖片描述
雖然騰訊自帶的不咋地,但是我還是加上地圖導航功能吧,看看效果圖。
在這裡插入圖片描述
在這裡插入圖片描述
在開發工具中不能進行點選,但是在真機上點選就會顯示導航按鈕以及導航地圖選擇。直接使用內建地圖導航,微信官方也有api,這裡奉上程式碼:

copyText: function (e) {
    var that = this,info_detail = e.currentTarget.dataset;
    wx.getLocation({//獲取當前經緯度
      type: 'wgs84', //返回可以用於wx.openLocation的經緯度,官方提示bug: iOS 6.3.30 type 引數不生效,只會返回 wgs84 型別的座標資訊  
      success: function (res) {
        wx.openLocation({//​使用微信內建地圖檢視位置。
          latitude: info_detail.latitude,//要去的緯度-地址
          longitude: info_detail.longitude,//要去的經度-地址
          name: info_detail.title,
          address: info_detail.text
        })
      }
    })
  },

前端程式碼:

<view class="cu-item" wx:for="{{dataArray}}" wx:for-item="item" wx:key>
   <view class='content padding-tb-sm' bindtap='copyText' data-text="{{item.address}}" data-index="{{item}}" data-latitude="{{item.latitude}}" data-longitude="{{item.longitude}}" data-tile="{{item.title}}">
     <view>
       <text class='icon-activityfill text-blue'></text> {{item.id+1}}:{{item.title}}</view>
     <view class='text-gray text-sm'>
       <text class='icon-locationfill'></text> {{item.address}}</view>
   </view>
 </view>

##下面介紹主要方法步驟:
1.引入百度地圖的js,新增個人AK
2.書寫自己的wxSearch方法包
3.頁面佈局和JS寫入
4.最終效果展示

##第一步:百度地圖JS引入

在我的第一篇部落格中我已經介紹過關於百度地圖開發者資訊如何獲取,AK是個人小程式應用專用的ak.

bmap-wx.min.js。這是百度提供給小程式的開發JS。放上下載連結(http://lbsyun.baidu.com/index.php?title=wxjsapi/wxjs-download)。
當然你也可以花點時間,在深入瞭解一下百度地圖資訊檢索開發文件。

var bmap = require('../../utils/bmap-wx.min.js');

在index.js中引入你存放起來的百度地圖JS。
強調一點在百度地圖開發文件中有詳細的說明,這裡我只說一下在JS中的各個引數代表:

var e={query:t.query||"生活服務$美食&酒店",scope:t.scope||1,filter:t.filter||"",coord_type:t.coord_type||2,page_size:t.page_size||20,page_num:t.page_num||0,output:t.output||"json",ak:a.ak,sn:t.sn||"",timestamp:t.timestamp||"",radius:t.radius||2e3,ret_coordtype:"gcj02ll"}

這一段程式碼是百度地圖JS中預設的各個引數存放處,找到這段程式碼,你可以根據自己實際需要來修改各個引數的值,介面展示的資訊結果也會不一樣的。此處的t.query預設請求的是生活服務美食酒店,也可根據個人喜好修改。

##第二步:給頁面新增一個搜尋功能

百度地圖的POI資訊檢索預設是輸出地點的,但是這並不是我們想要的結果。我們需要根據需求,設計自己想要的檢索功能,諸如這樣的:
這裡寫圖片描述
點選各個模組,搜尋對應的資訊;你也可以來個更簡潔的放個搜尋輸入框,讓使用者自己來輸入搜尋。不過,我堅信使用者更傾向於點選搜尋,這樣更一目瞭然,不是嗎。

好了我們來看看這個搜尋方法如何寫入:

這裡的內容是小程式整個搜尋事件的所有可能用到的事件。我們在地圖展示中也會用到的,最基礎的就是wxSearchInput,wxSearchFocus,wxSearchKeyTap,wxSearchAddHisKey,init。將這些方法寫起來,區別於util資料夾。方便其他頁面的呼叫。

##第三步:編寫我們的主要內容
這就是正文內容了。先寫wxml內容吧:

<!--index.wxml-->
<view class="map_container">
  <map class="map" id="map" circles='{{circles}}' longitude="{{longitude}}" latitude="{{latitude}}" scale="15" show-location="true" markers="{{markers}}" bindmarkertap="makertap"></map>
</view>
<!--nearby.wxml-->
<view style="overflow:hidden;">
  <view class="items" wx:for="{{array}}" wx:key="" wx:for-item="item" bindtap="wxSearchFn" bindinput="wxSearchInput" bindfocus="wxSerchFocus" value="{{wxSearchData.value}}" bindblur="wxSearchBlur" data-code="{{item.code}}" data-text="{{item.text}}">
    <image class="item-img" mode="aspectFit" src="{{item.src}}"></image>
    <view class="item-text">{{item.text}}</view>
  </view>
</view>

<!-- 測試地圖選點如下 -->
<view class="cu-bar bg-white solid-bottom margin-top">
  <view class='action'>
    <text class='icon-titles text-orange '></text>{{title}}
  </view>
</view>
<view class="cu-list menu margin-top  margin-indexbottom">
  <view class="cu-item" wx:for="{{dataArray}}" wx:for-item="item" wx:key>
    <view class='content padding-tb-sm' bindtap='copyText' data-text="{{item.address}}" data-index="{{item}}" data-latitude="{{item.latitude}}" data-longitude="{{item.longitude}}" data-tile="{{item.title}}">
      <view>
        <text class='icon-activityfill text-blue'></text> {{item.id+1}}:{{item.title}}</view>
      <view class='text-gray text-sm'>
        <text class='icon-locationfill'></text> {{item.address}}</view>
    </view>
  </view>
</view>
<!--  -->
<include src="../../template/footBar.wxml"></include>
 

想要搜尋的名稱列表我們用wx:for="{{array}}"來迴圈這個item的內容,array的內容儲存在JS的data中就可以了。節省頁面空間。
由於我們將搜尋框替換為卡片點選形式,所以還要在該
item
上來繫結搜尋框的屬性:bindtap=“wxSearchFn” bindinput=“wxSearchInput” bindfocus=“wxSerchFocus” bindblur=“wxSearchBlur”,以及點選卡片傳入搜尋對應的值value="{{wxSearchData.value}}" 。這樣就可以確保每個卡片單獨點選都只會顯示對應的內容,不會亂碼搜尋。

那麼在JS中是什麼樣子呢?JS部分現在做了一些調整修改,所以放上最新的。
下面,寫JS內容:

//獲取應用例項
var App = getApp();
var bmap = require('../../utils/bmap-wx.min.js');
var wxMarkerData = [];
var WxSearch = require('../../wxSearch/wxSearch.js');
var count = 10;
var total = 0;
var code = "2";
Page({
  data: {
    aslect: false,
    bslect: true,
    cslect: true,
    dslect: true,
    eslect: true,
    title: "周邊資訊查詢結果",
    indicatorDots: true,
    vertical: false,
    autoplay: true,
    markers: [],
    latitude: '',
    longitude: '',
    rgcData: {},
    telephone: {},
    test: '',
    interval: 3000,
    duration: 1000,
    array: [{
      code: '1',
      id: 'icon_1',
      src: '../../images/homework.png',
      text: '家政'
    }, {
      code: '2',
      id: 'icon_2',
      src: '../../images/ill.png',
      text: '藥店'
    }, {
      code: '3',
      id: 'icon_3',
      src: '../../images/bank.png',
      text: '銀行'
    }, {
      code: '4',
      id: 'icon_4',
      src: '../../images/dis.png',
      text: '維修'
    }, {
      code: '5',
      id: 'icon_5',
      src: '../../images/wc.png',
      text: '公廁'
    }, {
      code: '6',
      id: 'icon_6',
      src: '../../images/hospital.png',
      text: '醫院'
    }, {
      code: '7',
      id: 'icon_7',
      src: '../../images/addyou.png',
      text: '加油站'
    }, {
      code: '8',
      id: 'icon_8',
      src: '../../images/food.png',
      text: '飯店'
    }, {
      code: '9',
      id: 'icon_9',
      src: '../../images/weed.png',
      text: '營業廳'
    }, {
      code: '10',
      id: 'icon_10',
      src: '../../images/park.png',
      text: '停車場'
    }],
    dataArray: []
  },

  //分類儲存
  makertap: function(e) {
    var that = this;
    var id = e.markerId;
    that.showSearchInfo(wxMarkerData, id);
    that.setData({
      index_id: e.markerId,
    })
    console.log(e)
    this.showSearchInfo(e);
  },
  openPage: function (a) {
    var e = a.currentTarget.dataset.url;
    console.log(e)
    wx.reLaunch({
      url: e,
    })
  },
  onLoad: function(options) {
    var that = this;
    if (options.scene) {
      console.log("has scene");
      var scene = decodeURIComponent(options.scene);
      console.log("scene is ", scene);
      var arrPara = scene.split("&");
      var arr = [];
      for (var i in arrPara) {
        arr = arrPara[i].split("=");
        wx.setStorageSync(arr[0], arr[1]);
        console.log("setStorageSync:", arr[0], "=", arr[1]);
      }
    } else {
      console.log("no scene");
    }

    //初始化的時候渲染wxSearchdata
    WxSearch.init(that, 400, ['家政', '藥店', '公廁', '銀行', '營業廳', '醫院', '超市', '地鐵站', '停車場', '維修', '美食', '飯店']);
    WxSearch.initMindKeys(['家政公司', '保潔公司', '大藥房', '藥店', '免費公廁', '營業廳', '銀行ATM', '三甲醫院', '地下停車場', '地鐵口', '汽車美容', '飯店', '美食廣場', '中石化加油站', '中石油加油站']);
    // 新建百度地圖物件 
    var BMap = new bmap.BMapWX({
      ak: 'jXYZ2cjB0lwQYiI8einLVGGEv7Q0zfDz'
    });
    var fail = function(data) {
      console.log(data)
    };
    var success = function(data) {
      wxMarkerData = data.wxMarkerData;
      that.setData({
        markers: wxMarkerData,
        latitude: wxMarkerData[0].latitude,
        longitude: wxMarkerData[0].longitude,
        dataArray: data.wxMarkerData
      });
    };

    // 發起POI檢索請求 
    BMap.search({
      "query": "",
      fail: fail,
      success: success,
      // 此處需要在相應路徑放置圖片檔案 
      iconPath: '../../images/marker_red.png',
      // 此處需要在相應路徑放置圖片檔案 
      iconTapPath: '../../images/marker_red.png'
    });
  },

  //點選事件
  wxSearchFn: function(e) {
    var that = this;
    total = 0;
    code = e.currentTarget.dataset.code + "";
    var name = e.currentTarget.dataset.text + "";
    this.data.dataArray = [];
    //顯示選擇結果
    this.setData({
      title: "周邊資訊: " + name
    })

    WxSearch.wxSearchAddHisKey(that);

    // 新建百度地圖物件 
    var BMap = new bmap.BMapWX({
      ak: 'jXYZ2cjB0lwQYiI8einLVGGEv7Q0zfDz'
    });

    var fail = function(data) {
      console.log(data)
    };
    var success = function(data) {
      wxMarkerData = data.wxMarkerData;
      that.setData({
        markers: wxMarkerData,
        latitude: wxMarkerData[0].latitude,
        longitude: wxMarkerData[0].longitude,
        dataArray: data.wxMarkerData
      });
    };
    // 發起POI檢索請求 
    BMap.search({
      query: name,
      fail: fail,
      success: success,
      // 此處需要在相應路徑放置圖片檔案 
      iconPath: '../../images/marker_red.png',
      // 此處需要在相應路徑放置圖片檔案 
      iconTapPath: '../../images/marker_red.png'
    });
  },
  wxSerchFocus: function(e) {
    var that = this
    WxSearch.wxSearchFocus(e, that);
  },
  wxSearchBlur: function(e) {
    var that = this
    WxSearch.wxSearchBlur(e, that);
  },
  wxSearchKeyTap: function(e) {
    var that = this
    WxSearch.wxSearchKeyTap(e, that);
  },
  wxSearchDeleteKey: function(e) {
    var that = this
    WxSearch.wxSearchDeleteKey(e, that);
  },
  wxSearchDeleteAll: function(e) {
    var that = this;
    WxSearch.wxSearchDeleteAll(that);
  },
  wxSearchTap: function(e) {
    var that = this
    WxSearch.wxSearchHiddenPancel(that);
  },
  showSearchInfo: function(data, i) {
    console.log("------------", data[i])
    var that = this;
    var Otitle = data[i].title;
    var Oaddress = data[i].address;
    wx.getLocation({//獲取當前經緯度
      type: 'wgs84', //返回可以用於wx.openLocation的經緯度,官方提示bug: iOS 6.3.30 type 引數不生效,只會返回 wgs84 型別的座標資訊  
      success: function (res) {
        wx.openLocation({//​使用微信內建地圖檢視位置。
          latitude: data[i].latitude,//要去的緯度-地址
          longitude: data[i].longitude,//要去的經度-地址
          name: Otitle,
          address: Oaddress
        })
      }
    })
  },
  changeMarkerColor: function(data, i) {
    var that = this;
    var markers = [];
    for (var j = 0; j < data.length; j++) {
      if (j == i) {
        // 此處需要在相應路徑放置圖片檔案 
        data[j].iconPath = "../../images/marker_yellow.png";
      } else {
        // 此處需要在相應路徑放置圖片檔案 
        data[j].iconPath = "../../images/marker_red.png";
      }
      markers[j](data[j]);
    }
    that.setData({
      markers: markers
    });
  },
  goTolocate:function(){
   
  },
  copyText: function (e) {
    var that = this,info_detail = e.currentTarget.dataset;
    wx.getLocation({//獲取當前經緯度
      type: 'wgs84', //返回可以用於wx.openLocation的經緯度,官方提示bug: iOS 6.3.30 type 引數不生效,只會返回 wgs84 型別的座標資訊  
      success: function (res) {
        wx.openLocation({//​使用微信內建地圖檢視位置。
          latitude: info_detail.latitude,//要去的緯度-地址
          longitude: info_detail.longitude,//要去的經度-地址
          name: info_detail.title,
          address: info_detail.text
        })
      }
    })
  },
  onShareAppMessage: function (res) {
    //console.log("使用者點選了確定", res)
    if (res.from === 'button') {
      // 來自頁面內轉發按鈕
      console.log(res.target)
    }
    return {
      title: '美麗生活幫-看看周圍有什麼',
      path: 'pages/index/index',
      success: function (res) {
        // 轉發成功
        
        wx.showShareMenu({
          // 要求小程式返回分享目標資訊
          withShareTicket: true
        });
      },
      fail: function (res) {
        // 轉發失敗
        console.log("使用者點選了取消",res)
      }
    }
  }

})

這裡我們主要就是引入JS後,在data中配置各個陣列資料,然後就是地圖要搜所結果。這裡你可能注意到我用了兩次地圖POI檢索。說明一下,第一次在onload中,是頁面首次載入預設顯示的檢索資訊,所以預設值無需點選,我就儲存在WxSearch.initWxSearch.initMindKeys來進行模糊搜尋匹配。

wxSearchFn來詳細配置我們的搜尋內容和結果,var name = e.currentTarget.dataset.text + “”;,name是我們主要要用的引數,在query:name中進行精確搜尋。

這個搜尋功能可以直接下載工具包,也可以自己封裝。下面是搜尋框的部分屬性。若果是在下載不到或者不會寫的可以看我其他的博文,有介紹分類搜尋功能的。

wxSearch EventHandle 鍵盤輸入時觸發,event.detail = {value, cursor, keyCode},keyCode 為鍵值,2.1.0 起支援,處理函式可以直接 return 一個字串,將替換輸入框的內容。
wxSerchFocus EventHandle 輸入框聚焦時觸發,event.detail = { value, height },height 為鍵盤高度,在基礎庫 1.9.90 起支援

附上頁面樣式表:

/**index.wxss**/
@import "/wxSearch/wxSearch.wxss";

.items {
  float: left;
  width: 20%;
  background-color: #fff;
}

.item-img {
  width: 100%;
  height: 50rpx;
  margin-top: 10rpx;
}

.item-text {
  width: 100%;
  height: 50rpx;
  font-size: 25rpx;
  line-height: 50rpx;
  text-align: center;
}

.map_container {
  height: 300px;
  width: 100%;
}

.map {
  height: 100%;
  width: 100%;
}
.margin-indexbottom{
  padding-bottom:150rpx;
}

如果有不理解或者想要原始碼的,請評論區回覆。

相關文章