超详细小程序定位地图模块全系列开发教学


Posted in Javascript onNovember 24, 2020

前言:如果想最大化吸取本文经验,须有小程序开发基础,本文细节比较多(多看注释的提醒内容),请耐心理解,多动手尝试,收获会更加丰富

1.定位系统使用场景及概述

如美团外卖小程序

超详细小程序定位地图模块全系列开发教学

点定位

超详细小程序定位地图模块全系列开发教学

点搜索

超详细小程序定位地图模块全系列开发教学

显而易见,随便一个电商小程序都需要用到定位服务,那么今天我们做一个类似的定位模块
定位模块总览
外部页面

超详细小程序定位地图模块全系列开发教学

内部页面(下文说的内外部页面就是指这两个)

超详细小程序定位地图模块全系列开发教学

好了接下来我们开始动手

2.定位外部模块样式

效果

超详细小程序定位地图模块全系列开发教学

代码

//wxml
<view bindtap="getLocation" class="location">
 <image src="../../img/location.png"></image>
 <view>{{location}}</view>
</view>
//wxss
.location{
 font-size: 17px;
 width: 100%;
 background:rgb(196, 228, 123);
 display: flex;
 /* 对于两个块元素 */
 /* 垂直居中 */
 align-items: center;
 /* 水平居中 */
 justify-content: center;
}
.location image{
 width: 23px;
 height: 23px;
}

先不用管上面的{{location}},它是我们之后要从全局变量传过来的位置信息,定位符号是用image图片放进去的,我们用flex布局让图片和文字在同一行居中显示(见注释)

3.定位模块内部样式

效果

超详细小程序定位地图模块全系列开发教学

代码(分五个小模块,见注释)

//wxml
//搜索模块
<view class="header">
 <view class="search">
<image src="../../img/sousuo.png"></image>
 </view>
 <view class="input">
<input type="text" placeholder=" 请输入你想要的内容" placeholder-class="placeholder" bindinput="bindInput" bindfocus="bindFocus" auto-focus="{{autoFocus}}"></input>
 </view>
</view>
//定位模块
<view class="dw">
<button size="mini" bindtap="getCity">
 <image src='../../img/location.png'></image>
 <text>定位</text>
 </button>
</view>
//当前位置模块
<view >当前所在位置</view>
<button size="mini" bindtap="nowCity" class='nowcity'>{{city}}</button>
//热门城市模块
<view class="hotcity">热门城市</view>
<view wx:for="{{hotcity}}" wx:key='index' class="hotcity1">
 <!-- 用了view循环之后要把view设置为inline元素,不然5个view会分成5行显示 -->
<button size="mini" bindtap="hotCity" data-hotcityindex='{{index}}'>{{item.cityName}}</button>
</view>
//地图模块
<view class="map">
<map longitude="{{longitude}}" latitude="{{latitude}}" scale="14"></map>
</view>

由于我的搜索框是用了自定义组件里面的搜索组件,我是在组件的基础上改出来的,原组件是这样的

超详细小程序定位地图模块全系列开发教学

我们需要把搜索图标隐藏,我们直接设置它的透明度为0,然后把我们的定位文字跟图标通过定位直接定位到搜索框的左边,所以样式的代码如下(代码太多不好找的话可以Ctrl+F直接搜索)

//wxss
.dw{
 color:rgb(0, 0, 0);
 position: absolute;
 top: 14px;
 left: -2px;
}
.dw button{
 background: white;
 padding-right: 0;
 display: flex;
 align-items: center;
 font-weight: 600 !important;
}
.nowcity{
 font-weight: normal;
}
.dw image{
 width: 23px;
 height: 23px;
}
page{
 padding: 10px;
}
.hotcity1 button{
 margin: 10px;
 margin-bottom: 0;
 font-weight: 500 !important;
  border-radius: 10px !important;
}
.hotcity{
 margin-top: 6px;
 
}
.map_container{
 position: absolute;
 top: 0;
 bottom: 0;
 left: 0;
 right: 0;
}
.header{
 display: flex;
}
.search{
flex:1;
height: 40px;
text-align: center;
background: #fff;
}
.input{
 flex:9;
 height: 40px;
 background: #fff;
}
.input input{
 background: #f1f1f1;
height: 30px;
margin-top: 5px;
margin-bottom: 5px;
margin-right: 8px;
border-radius: 10px;
}
.search image{
 width: 70%;
 height: 25px;
 padding-top: 9px;
 padding-left: 5px;
}
.placeholder{
 font-size: 14px;
}
.search image{
 opacity: 0;
}
.input{
 flex:4;
}
.input input{
position: relative;
right: 0px;
}
.hotcity1{
 display: inline;
}
.map{
 position: relative;
}
map{
 border:5px solid green;
 text-align: center;
 margin: 10px auto;
position: relative;
right: 10px;
 width: 90%;
 height: 150px;
}

然后我们的搜索里面点击搜索还会跳转到新的搜索页面,效果如下

超详细小程序定位地图模块全系列开发教学

这里我们可以直接复用上面的搜索组件,样式代码就不再贴出来了,这个模块要将搜索自动匹配的地点名称用循环的方式显示出来,代码如下

//wxml
<import src="../templates/search/search" />
<template is="search"></template>
<view bindtouchstart="bindSearch" data-keywords="{{i.name}}"
 class="text_box" wx:for="{{tips}}" wx:for-item="i" wx:key='index'>
 {{i.name}}
</view>
//wxss
@import '../templates/search/search.wxss';
.text_box{
 margin: 10px 25px;
 border-bottom:1px solid #c3c3c3;
 padding-bottom:10px
}

4.外部跳转

当我们点击外部的位置信息,就跳转到内部的定位模块,刚刚我们在上面给外部的标签设置了触摸事件getLocation,接下来只要到js里面设置点击跳转(navigateTo)就可以了,但由于我们的位置信息是用全局变量赋值的,所以我们要在app.js设置一个全局变量,代码如下

//app.js
App({
 globalData: {
  city:'暂未定位',
  userInfo:'无'
 },
 )}
//外部js
// 引入app.js
const app=getApp()
const appG=app.globalData
 data: {
//这里要初始化location,并将全局变量赋值给它
aboutList:'',
location:appG.city
 },
 Page({
 //定义触摸事件
 getLocation(){
 wx.navigateTo({
 //跳转到内部定位页面
  url: '../location/location',
 }) 
},
)}

5.点击定位

做这个功能之前我们需要先考虑用什么地图接口,常用的有百度地图,腾讯地图,高德地图,本文选用高德地图接口作为演示,搜索https://lbs.amap.com/,注册,进入控制台,创建新应用,

超详细小程序定位地图模块全系列开发教学

再添加key

超详细小程序定位地图模块全系列开发教学

这个key就像我们小程序调用接口时的验证码,有了它我们才能从高德调取位置的数据,然后我们点击key后面的设置,再点击微信小程序SDK

超详细小程序定位地图模块全系列开发教学

进去之后点这两个,下载amap-wx.js 文件,然后在你的小程序目录里面创建一个libs文件,把这个amap-wx.js扔进去

超详细小程序定位地图模块全系列开发教学

接下来我们来到内部定位页面的js文件,因为这里要对全局变量进行修改来达到修改页面数据的效果,所以也要引入app.js,并把全局变量初始化到data里面,除此之外我们要引入高德的文件来实现高德接口的调用,在data里面我们这里顺便把等会要用到的热门城市等数据一并初始化了

const app=getApp()
const appG=app.globalData
//key里面填高德控制台里面给你的key
const myAmapFun = new amapFile.AMapWX({key:'xxxxxxxxxx'});
 data: {
city:appG.city,
hotcity:[
 {'cityName':'北京市',longitude:'116.395645038',latitude:'39.9299857781'},
 {'cityName':'上海市',longitude:'121.487899486',latitude:'31.24916171'},
 {'cityName':'广州市',longitude:'113.307649675',latitude:'23.1200491021'},
 {'cityName':'深圳市',longitude:'114.025973657',latitude:'22.5460535462'},
 {'cityName':'武汉市',longitude:'114.316200103',latitude:'30.5810841269'},
],
tips: {},//搜索自动匹配的内容
longitude:'116.4',//经度(初始值在北京)
latitude:'39.9'//纬度(初始值在北京)
}

然后我们给定位按钮设置点击事件getCity,这里用到高德地图里面的获取地址描述数据方法,教程可以参考刚刚高德控制台微信SDK里面的教程(下面搜索自动匹配提示的教程也一样)

超详细小程序定位地图模块全系列开发教学

此外我们我们还要在小程序后台给高德的接口添加域名,操作步骤为
登录微信公众平台,“设置“?>"开发设置"设置request合法域名,将https://restapi.amap.com 中添加进去,这样我们才能请求到高德的数据

代码

getCity(){
 myAmapFun.getRegeo({
  success: data=>{
   // that.setData({
   //  city:data[0].desc.slice(0,2)
   // })
   appG.city=data[0].desc
   wx.getLocation({
    success:res=>{
this.setData({
  latitude:res.latitude,
  longitude:res.longitude
})
wx.setStorageSync('city', appG.city)
wx.setStorageSync('latitude', res.latitude)
wx.setStorageSync('longitude', res.longitude)
    }
   })
  },
  fail: function(info){
   //失败回调
   console.log(info)
  }
 })
},

getRegeo方法的成功回调函数里的参数包含了定位后的位置信息(可以自己输出一下),我们把它赋值给全局变量,然后再用setData再次把全局变量appG.city赋值给data里面的city(因为appG.city已经改变了,要重新赋值页面才会更新),除此之外我们还要把获取到的位置信息同步缓存起来,下次进入页面的时候在onLoad里面先判断有没有缓存的数据,如果有就直接使用缓存的数据,没有就用默认值,代码如下

onLoad: function (options) {
  // 进页面先看有无缓存数据,如果没有再读默认值,onLoad里面可以取到this.data
  const latitude=wx.getStorageSync('latitude')
  const longitude=wx.getStorageSync('longitude')
  const city=wx.getStorageSync('city')
  //用了三目运算符,不习惯也可以使用if
  latitude&&longitude&&city?
  this.setData({
   latitude:latitude,
   longitude:longitude
  }):false
 },

6.未定位时弹出定位框

给当前位置标签添加点击事件,判断当位置信息为初始值暂未定位时,弹出是否定位的选择框,当用户点击确定时,执行一次getCity函数即可,效果如下

超详细小程序定位地图模块全系列开发教学

代码

nowCity(){
 if(this.data.city!='暂未定位'){
  wx.switchTab({
   url: '../about/about',
  })
 }else{
  wx.showModal({
   title: '暂未定位',
   content: '现在要进行定位吗',
   success: (res)=>{
    if (res.confirm) {
     this.getCity()
    } else if (res.cancel) {
     return false
    }
   }
  })
 }
},

7.热门城市点击跳转,更新数据

超详细小程序定位地图模块全系列开发教学

当我们点击热门城市里面的按钮时,跳转到外部页面,并且把对应热门城市名称更新到全局的city来传到外部页面显示,同时还要更新全局中的经纬度数据,对于经纬度只要更新缓存即可,下一次进入内部定位页面时再判断缓存中有无定位数据,如果有就直接用,city数据是更新+缓存,代码如下

hotCity(e){
 const index=e.currentTarget.dataset.hotcityindex
 //更新
 appG.city=this.data.hotcity[index].cityName
 //缓存
  wx.setStorageSync('city', appG.city)
 wx.setStorageSync('latitude', this.data.hotcity[index].latitude)
 wx.setStorageSync('longitude', this.data.hotcity[index].longitude)
 //跳转
wx.reLaunch({
 url: '../about/about',
 success:()=>{
  // 不要把数据的更新写在这里,要在跳转之前就写好,因为这个回调函数是在跳转的页面所有函数
  // 执行完之后才执行的,会导致数据两次跳转次才更新
 }
})
},

上述代码中注意要在热门城市的循环标签用data-hotcityindex="{{index}}"把下标传到js中,再在js中用e.currentTarget.dataset.hotcityindex去取出来用,这个下标用来对应热门城市数组的每一个对象,这样我们就可以用this.data.hotcity[index].cityName来获取被点击的城市的名称,再把它更新到appG.city中,注意跳转的时候不能用wx.switchTab,因为从外部页面进来的时候已经打开了外部页面,那么用wx.switchTab的时候只会执行外部页面的onShow函数,而不会执行onLoad,会导致页面数据无法更新

8.搜索跳转和输入自动匹配地名

搜索跳转新页面(给内部定位页面设置聚焦事件)

bindFocus(e){
 wx.navigateTo({
  url: '../locationSearch/locationSearch',
 })
},

注意内部页面的搜索框不是自动聚焦的,而跳转到新的搜索页面的搜索框是会自动聚焦的,这一点我们可以通过在搜索组件的input标签添加auto-focus="{{autoFocus}}",再控制autoFocus的值来控制是否自动聚焦,代码如下

<template is="search" data="{{autoFocus}}"></template>

注意data="{{xxx}}"是自定义组件特有的传参方式,可以把js里面的值传到组件中使用不过我们得先在搜索页面的js的data中给autoFocus赋值,这里顺便把保存自动匹配的地名的值tips也初始化了

data: {
autoFocus:true,
tips:{}
 },

接下来我们写输入自动匹配地名,同样在搜索页面的js引入全局变量和高德js文件

const amapFile = require('../../libs/amap-wx.js');
const app=getApp()
const appG=app.globalData
const myAmapFun = new amapFile.AMapWX({key:'0c2c8f2007702caa7e0498d6ad072f83'});

然后我们来监听用户的输入行为,设置为bindInput函数

<input type="text" placeholder=" 请输入你想要的内容" placeholder-class="placeholder"
 bindinput="bindInput" bindfocus="bindFocus" auto-focus="{{autoFocus}}"></input>

搜索页面的js中定义bindInput

bindInput(e){
 myAmapFun.getInputtips({
  // keywords为必填,不然无法获得tips,也就不会进入success函数
  keywords:e.detail.value,
  success:data=>{
 this.setData({
  tips:data.tips
 })
  }
 })
},

上面的getInputtips就是我们第5点中讲到的微信小程序SDK中的获取提示词里面的方法,可以自己去看高德的教程,此处不再赘述,上面的keywords的值就是用户输入的内容,接口会根据这个去寻找对应匹配的地名并返回在success函数的参数中,我们只需要在成功回调函数中更新tips就可以了,那么此时假如我们输入武汉,效果如下

超详细小程序定位地图模块全系列开发教学

那么当我们点击自动匹配的地名的时候,需要返回到外部页面,并且更新数据,更新缓存,思路和上面的跳转方法是一样的,代码如下

bindSearch(e){
 const location=this.data.tips[e.currentTarget.dataset.searchindex]
 wx.setStorageSync('city', location.name)
 if(location.location.length!=0){
  const longitude=location.location.split(',')[0]
  const latitude=location.location.split(',')[1]
 wx.setStorageSync('latitude', latitude)
 wx.setStorageSync('longitude', longitude)
 wx.reLaunch({
  url: '../about/about',
   success:()=>{
       appG.city=e.currentTarget.dataset.keywords  
  }
 })
 }else{
  wx.reLaunch({
   url: '../about/about',
    success:()=>{
        appG.city=e.currentTarget.dataset.keywords  
        setTimeout(()=>{wx.showToast({
         title: '暂无经纬度数据',
        // 提示延迟时间,不能用字符串
         duration:2000,
         icon:'none'
        })
       },500);
   }
  })
 }

由于不是每一个自动匹配的地点都有经纬度,所以我们对没有经纬度的地名做业务退步处理,仅提醒暂无经纬度的数据,(有时候业务退一小步,技术就有一大步的发挥空间?《大型网站技术架构》——李智慧),细心的你们肯定注意到上面用了定时器,因为如果不使用定时器,这个弹框是不会显示出来的,这个函数在页面加载完成之前就已经执行了,所以我们给他来一个定时器作为异步函数延迟执行,才能有弹框

9.对整个模块的优化和思考

对上述代码,笔者开发完之后发现了如下问题:
代码冗余严重,主要表现在多次使用缓存的api,重复量的地方很多
整个模块内部互相调用复杂,高耦合,低拓展
某些地方把简单的逻辑复杂化了,代码不够整洁
对于上述问题,笔者有如下思考:
通过封装缓存api来减少不必要的代码量,提高代码整洁度
对整个模块重新构思,提高可拓展性和可复用性(由于笔者水平有限,暂时搁置)
模块从开发开始到开发完成需要不断的演化和改进,这个过程才是让开发者成长的关键

到此这篇关于超详细小程序定位地图模块全系列开发教学 的文章就介绍到这了,更多相关小程序定位地图内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
javascript hashtable 修正版 下载
Dec 30 Javascript
js身份证判断方法支持15位和18位
Mar 18 Javascript
javascript使用shift+click实现选择和反选checkbox的方法
May 04 Javascript
jQuery实现文件上传进度条特效
Aug 12 Javascript
JQuery zClip插件实现复制页面内容到剪贴板
Nov 02 Javascript
每天一篇javascript学习小结(Boolean对象)
Nov 12 Javascript
jQuery实现带分组数据的Table表头排序实例分析
Nov 24 Javascript
Vue单页应用引用单独的样式文件的两种方式
Mar 30 Javascript
vue 实现axios拦截、页面跳转和token 验证
Jul 17 Javascript
最适应的vue.js的form提交涉及多种插件【推荐】
Aug 27 Javascript
一个因@click.stop引发的bug的解决
Jan 08 Javascript
微信小程序中如何使用flyio封装网络请求
Jul 03 Javascript
JavaScript实现移动端拖动元素
Nov 24 #Javascript
小程序组件传值和引入sass的方法(使用vant Weapp组件库)
Nov 24 #Javascript
js实现抽奖功能
Nov 24 #Javascript
前端 javascript 实现文件下载的示例
Nov 24 #Javascript
如何使用 JavaScript 操作浏览器历史记录 API
Nov 24 #Javascript
JavaScript实现鼠标移入随机变换颜色
Nov 24 #Javascript
原生js实现表格循环滚动
Nov 24 #Javascript
You might like
融入意大利的咖啡文化
2021/03/03 咖啡文化
冰滴咖啡制作步骤
2021/03/03 冲泡冲煮
坏狼的PHP学习教程之第2天
2008/06/15 PHP
PHP中foreach()用法汇总
2015/07/02 PHP
laravel 实现根据字段不同值做不同查询
2019/10/23 PHP
JS动态调用方法名示例介绍
2013/12/18 Javascript
jquery实现文本框数量加减功能的例子分享
2014/05/10 Javascript
js中自定义方法实现停留几秒sleep
2014/07/11 Javascript
JS+CSS实现六级网站导航主菜单效果
2015/09/28 Javascript
javascript学习笔记_浅谈基础语法,类型,变量
2016/09/19 Javascript
利用CSS、JavaScript及Ajax实现图片预加载的三大方法
2017/01/22 Javascript
javaScript+turn.js实现图书翻页效果实例代码
2017/02/16 Javascript
基于Vue.js 2.0实现百度搜索框效果
2020/12/28 Javascript
js神秘的电报密码 哈弗曼编码实现
2019/09/10 Javascript
vue项目初始化到登录login页面的示例
2019/10/31 Javascript
Vue 构造选项 - 进阶使用说明
2020/08/14 Javascript
Vue.js原理分析之nextTick实现详解
2020/09/07 Javascript
vscode 调试 node.js的方法步骤
2020/09/15 Javascript
[01:08]DOTA2次级职业联赛 - Shield战队宣传片
2014/12/01 DOTA
Python实例一个类背后发生了什么
2016/02/09 Python
python中pika模块问题的深入探究
2018/10/13 Python
python单线程文件传输的实例(C/S)
2019/02/13 Python
python整合ffmpeg实现视频文件的批量转换
2019/05/31 Python
基于SQLAlchemy实现操作MySQL并执行原生sql语句
2020/06/10 Python
Python matplotlib 绘制双Y轴曲线图的示例代码
2020/06/12 Python
Ryderwear美国官网:澳大利亚高端健身训练装备品牌
2018/04/24 全球购物
Bluebella德国官网:英国性感内衣和睡衣品牌
2019/11/08 全球购物
外贸公司实习自我鉴定
2013/09/24 职场文书
晚会邀请函范文
2014/01/24 职场文书
股权投资意向书
2014/04/01 职场文书
三好学生事迹材料
2014/12/24 职场文书
房地产销售员岗位职责
2015/04/11 职场文书
单位综合评价意见
2015/06/05 职场文书
Mysql 如何批量插入数据
2021/04/06 MySQL
windows11怎么查看wifi密码? win11查看wifi密码的技巧
2021/11/21 数码科技
Apache自带的ab压力测试工具的实现
2022/07/23 Servers