Uni-app 实现定位功能
我做这个定位功能的实现使用的技术是:uni-app+uView, 定位的功能是使用腾讯地图小程序定位。通过获取经纬度的方式进行获取地理信息,我们可以直接调用腾讯定位的API,然后获取地理信息。通过uView的UI可现成技术进行实现。具体代码实现在每一个模块中有对应的代码
使用到的文档地址
腾讯地图SDK官方文档使用地址
uView官方文档使用地址
qqmap-wx-jssdk.min.js下载地址
需求和实现功能截图:
实现功能样式
首页定位信息采集
代码实现:
将这个头部定位的信息栏目进行封装一个组件,因为这个页面在多个地方使用到了;通过传递city,area,city_code 进行数据响应。(
search-bar.vue
在下面有这组件)
<template>
<view>
<!-- 该部分多个地方使用,封装了一个组件 -->
<search-bar v-on:pinitJob="Ssearch" :swiperlist="swiperlist" :placeholder="'搜索企业、职位'" :city="city" :area="area" :city_code="city_code"></search-bar>
</view>
</template>
<script>
// 引入定位系统的sdk ,可以通过我上述提供的资源下载地址进行下载
let QQMapWX = require('../../static/js/qqmap-wx-jssdk.min.js');
// 在最外层创建一个全局变量
let qqmapsdk;
export default {
data(){
return {
city:'', // 城市
area:'', // 区/县
city_code: '', // 城市id
}
},
onLoad(options) {
qqmapsdk = new QQMapWX({
// key: 'G5KBZ-xxxx-xxx-3KPRK-STFSA'
// 自己的定位APK秘钥
key: 'MRJBZ-xxxx-xxxx-xxxx-2DJHZ-xxxxx'
});
this.getCurrentLocation();
},
methods:{
// 获取当前位置
getCurrentLocation() {
var that = this;
uni.getLocation({
type: 'wgs84',
geocode: true,
success: (res) => {
console.log("获取经纬度成功");
this.latitude = res.latitude;
this.longitude = res.longitude;
// 解析地址
qqmapsdk.reverseGeocoder({
location: {
latitude: that.latitude,
longitude: that.longitude
},
success: function(res) {
that.$nextTick(function() {
// 可以根据自己的需要进行添加
this.city_code = res.result.ad_info.city_code; // 市区
this.city = res.result.address_component.city; // 市
this.area = res.result.address_component.district; // 区
this.address = [this.city, this.area]
that.getJobList()
})
// console.log(province, city, area)
},
fail: function(res) {
this.$refs.uToast.show({
title: '定位失败',
type: 'error',
icon: 'none'
})
console.log(res);
},
complete: function(res) {
console.log(res)
}
})
},
fail: (err) => {
uni.showToast({
title: '获取经纬度失败',
icon: 'none'
})
console.log("获取经纬度失败");
console.log(err);
},
complete: () => {}
})
},
}
}
</script>
search-bar 组件 => search-bar.vue
<template>
<view class="page">
<view class="title">
<!-- <view style="display: flex; align-items: flex-end;" data-url="/subPackage/pages/switch_city/switch_city" @tap.stop="navTo"> -->
<view style="display: flex; align-items: flex-end;">
<view style="white-space: nowrap;" @click="goLocaltion(city,area,city_code)">{{city}}-{{area==''? '暂未选择区/县': area}}</view>
<view class="rbtriangle"></view>
</view>
<view class="search_ipt" :class="{hasresume:isresume == false}">
<text class="iconfont iconsearch" style="margin-right: 10rpx;"></text>
<input type="text" :placeholder="placeholder" v-model="keywords" confirm-type="搜索"
@confirm="initJob(keywords)" />
</view>
<image src="../../static/images/intro.png" :data-url="'/pages/historyCompany/historyCompany?type=1'"
@tap.stop="navTo" v-show="isresume"></image>
</view>
<xunlan_swiper :data="swiperlist" :height="'280'" v-if="isshow"></xunlan_swiper>
</view>
</template>
<script>
export default {
data() {
return {
keywords: '',
}
},
props: {
isshow: {
default: true,
type: Boolean
},
swiperlist: {
default: ()=>[],
type: Array
},
isresume: {
default: true,
type: Boolean
},
placeholder: {
default: 0,
type: String
},
city:{
default: '',
type:String
},
area:{
default: '',
type:String
},
city_code:{
default:'',
type:String
}
},
methods: {
// 直接进行跳转
navTo(e) {
let url = e.currentTarget.dataset.url;
uni.navigateTo({
url: url
})
},
initJob() {
this.$emit("pinitJob", this.keywords)
},
// 页面跳转进行修改数据
goLocaltion(city,area,city_code) {
uni.navigateTo({
// 传递需要的值,通过ES6进行拼接
url: `../../pages/index/xxxx?city=${city}&area=${area}&city_code=${city_code}`
})
}
}
}
</script>
<style lang="scss" scoped>
// 样式
.page {
position: relative;
background-color: #FFFFFF;
}
.title {
display: flex;
align-items: center;
justify-content: space-between;
padding: 20rpx;
font-size: 26rpx;
color: #474754;
image {
width: 80rpx;
height: 80rpx;
}
}
.rbtriangle {
width: 0;
height: 0;
border-bottom: 10rpx solid black;
border-left: 10rpx solid transparent;
margin: 0 20rpx;
}
.search_ipt {
display: flex;
align-items: center;
width: 396rpx;
height: 80rpx;
padding: 10rpx;
border-radius: 14rpx;
background-color: #F5F6FA;
}
.hasresume {
width: 500rpx;
}
</style>
进入定位页面更改位置信息(切换城市),更改该程序的地理信息,关键字搜索
切换城市和获取区域的信息地理位置,关键字搜索
我们使用uView自带的样式进行布局使用,通过点击按钮进入到这个页面(可携带参数),以我这个为例的话,我是传递
city,city_code,area
三个值通过onLoad(options)
获取到这三个值,然后拿到选择区/县
需要获取到city_code 的值请求到对应的区域。在搜索当中,可以通过用户提供的关键字在失去焦点时候进行模糊搜索,并且返回!
<template>
<view class="page">
<view class="title">
<u-search placeholder="请输入城市名称" v-model="searchVal" :show-action="false" @focus="focusChange()" @blur="clearChange()" @change="searchChange(searchVal)"
:dataCity="dataCity">
</u-search>
</view>
<!-- 查询出来的列表 -->
<view class="content bg-white" v-if="contentFlag == true">
<view v-for="(searchItem,index) in seachCityList" :key="index">
<view class="search-city-name" @click="searchChangeArea(searchItem.id,searchItem.fullname)">
{{searchItem.fullname}}
</view>
</view>
</view>
<!-- 所有城市列表 -->
<view class="content" v-if="contentFlag == false">
<view class="header">
<view class="w45 color2F308A">
<image src="../../../static/images/location1_f.png" mode=""></image> <text>{{city}} {{area}}</text>
</view>|
<view class="w45" @click="changeArea(city_code)">
<image src="../../../static/images/select.png" mode=""></image><text
@click="show = true">选择区/县</text>
</view>
<view class="selectArea">
<u-select v-model="show" mode="single-column" :list="list" @confirm="confirm" @cancel="cancel">
</u-select>
</view>
<view class="text-content">根据城市选择地点</view>
</view>
<view class="index-list" :scrollTop="scrollTop">
<view class="city-list">
<view class="current-city-box">
<text class="current-city-name">{{city}}</text>
<text class="current-city-btn">当前城市</text>
</view>
</view>
<u-index-list>
<view v-for="(item, index) in indexList" :key="index">
<!-- 这里的key需要绑定item.keywods或者唯一id,不然会出现点击城市获取的city_code有差异 -->
<u-index-anchor :use-slot="true" :index="item.keywords">
<view class="anchor-text city-fullname" v-for="(cityItem,i) in item.list" :key="cityItem.id"
@click="changeCityById(cityItem.id,cityItem.fullname)">
{{cityItem.fullname}}
</view>
</u-index-anchor>
</view>
</u-index-list>
</view>
</view>
</view>
</template>
<script>
let Config = require('../../common/config.js')
let QQMapWX = require('../../../static/js/qqmap-wx-jssdk.min.js');
let qqmapsdk = Config.map_global_key
let setTime = null;
export default {
data() {
return {
keywords: '',
searchVal: '', // 搜索内容
indexList: [],
city: '', // 市
area: '', // 区
scrollTop: 0,
show: false, // 模态框控制
list: [],
city_code: '',
seachCityList:[], // 模糊查询的数组
contentFlag: false
}
},
onLoad(options) {
console.log('onLoad--options', options)
// 获取传递的值
this.city = options.city
this.area = options.area
// 截取并且赋值city_code
this.city_code = this.subStringCode(options.city_code)
},
onUnload() {
let pages = getCurrentPages();
console.log(pages[0]);
pages[0].$vm.area = this.area
pages[0].$vm.city = this.city
pages[0].$vm.city_code = this.city_code
},
onShow() {
// 与首页一致
qqmapsdk = new QQMapWX({
key: 'MRJBZ-xxxx-xxxx-GBN4H-2DJHZ-xxxxx'
});
// 获取市的列表
this.getCityList().then(res => {
this.indexList = res
})
// 进入页面获取对应市的区
this.changeArea(this.city_code)
},
methods: {
// 获取城市列表
getCityList() {
let fir = []
let that = this
let municipality = []
return new Promise((resolve, reject) => {
qqmapsdk.getCityList({
success(res) {
if (res.status == 0) {
// resolve(res.result)
this.indexList = res.result
let myCityList = res.result
res.result.map((item, index) => {
// console.log(item);
let cityfirdtNumber = ['a', 'b', 'c', 'd', 'e', 'f', 'g',
'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q',
'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'
]
if (index == 0) {
item.map(e => {
// if (!e.fullname.includes('省')) {
// fir.push(e)
// }
if (e.fullname.includes('市')) {
municipality.push(e.cidx)
}
})
}
// console.log(fir, "fir", municipality);
if (index == 1) {
Array.prototype.push.apply(item, fir)
// console.log(item, cityfirdtNumber);
let cityGropp = {}
for (let i = 0; i < cityfirdtNumber.length; i++) {
let city = []
item.map((e, myIndex) => {
let str = e.pinyin.join('')[0]
// console.log(str);
//直辖市过滤其中的区
for (let j = 0; j < municipality
.length; j++) {
let muvity = municipality[j]
if (myIndex <= muvity[muvity
.length - 1] && myIndex >=
muvity[0]) {
return
}
}
if (str == cityfirdtNumber[i]) {
// if (e.fullname.includes('自治') || e.fullname.includes('地区') || e.fullname.includes('市') || e.fullname.includes('行政')) {
let objs = {
fullname: e.fullname,
name: e.name,
pinyin: e.pinyin,
id: e.id,
longPin: e.pinyin.join('')
}
city.push(objs)
// }
}
})
cityGropp[cityfirdtNumber[i]] = city
}
// console.log(cityGropp, "cityGropp");
let cityText = []
let indexList = []
let num = 0
for (const key in cityGropp) {
let obj = {}
if (cityGropp[key].length > 0) {
indexList.push(key.toUpperCase())
obj.keywords = key.toUpperCase()
obj.list = cityGropp[key]
num += cityGropp[key].length
cityGropp[key].sort((a, b) => a.longPin
.charCodeAt(0) - b.longPin.charCodeAt(0)
); //a~z 排序
}
if (obj.keywords) {
cityText.push(obj)
}
}
resolve(cityText)
}
})
}
},
fail(err) {
reject(err)
}
})
})
},
//选择城市下的区县
getDistrictByCityId(id) {
console.log('id', id)
return new Promise((resolve, reject) => {
qqmapsdk.getDistrictByCityId({
id,
success(res) {
if (res.status == 0) {
// console.log(res, 1);
resolve(res.result)
}
},
fail(err) {
reject(err)
}
})
})
},
// 截取cityCode后六位
subStringCode(str) {
let res = str.substring(str.length - 6, str.length)
return res
},
// 选择地区
async changeArea(cityCode) {
await this.getDistrictByCityId(cityCode).then(res => {
let newArr = []
res.map(item => {
item.map(e => {
e.label = e.fullname
e.value = e.id
let obj = {
label: e.fullname,
value: e.id
}
newArr.push(obj)
})
})
console.log(newArr)
this.list = newArr;
})
},
// 选择确定按钮
confirm(e) {
e.map(item => {
this.area = item.label
})
// 返回上一页
uni.navigateBack()
},
// 点击获取城市信息
changeCityById(id,value) {
console.log('查看value',value)
console.log('查看id,',id,)
this.city_code = id
this.city = value
this.area = ''
this.list = []
this.changeArea(id)
// 防止用户过度点击
uni.showLoading({
title: "加载中"
})
setTimeout(() => {
uni.hideLoading()
}, 200)
},
// 关闭
cancel(e) {
e.map(item => {
console.log('关闭e', e)
// this.city_code = item.value
})
},
// 帮助用户快速查询
getSuggestion(params) {
console.log('关键字搜索内容', params)
return new Promise((resolve, reject) => {
qqmapsdk.getSuggestion({
keyword: params,
success(res) {
if (res.status == 0) {
// console.log(res, 1);
resolve(res.data)
}
},
fail(err) {
reject(err)
}
})
})
},
// 获取焦点
focusChange() {
this.contentFlag = true
},
// 没有数据时候
clearChange() {
this.contentFlag = false
},
// 模糊查询选择函数
searchChangeArea(id,value) {
this.city = value
this.changeArea(id)
this.area = ''
this.getDistrictByCityId(id).then(res => {
let newArr = []
res.map(item => {
item.map(e => {
e.label = e.fullname
e.value = e.id
let obj = {
label: e.fullname,
value: e.id
}
newArr.push(obj)
})
})
console.log(newArr)
this.seachCityList = newArr;
})
},
// 市区焦点模糊查询
searchChange(value) {
this.contentFlag = true
let that = this
console.log("value", value)
setTime&&clearTimeout(setTime)
setTime = setTimeout(() =>{
let arr = []
that.indexList.map(item => {
// console.log(item.list);
item.list.map(e => {
if ((value && e.fullname.indexOf(value) != -1) || e.longPin.indexOf(value) != -
1) {
console.log(e);
// that.selectArea(e.id)
arr.push(e)
}
})
})
this.seachCityList = arr
console.log('arr==>',JSON.parse(JSON.stringify(arr)))
uni.showLoading({
title:'加载数据中',
icon:'none'
})
},500)
}
}
}
</script>
<style lang="scss" scoped>
.page {
width: 100%;
height: 100%;
margin: 0 auto;
background-color: whitesmoke !important;
.title {
width: 100%;
padding: 20rpx 0;
margin: 0 auto;
background-color: #fff;
position: relative;
}
.content {
width: 90%;
margin: 0 auto;
.header {
width: 100%;
background-color: #FFFFFF;
border-radius: 10px;
margin-top: 10px;
padding: 10px 0;
.w45 {
width: 45%;
display: inline-block;
text-align: center;
height: 60rpx;
line-height: 60rpx;
image {
width: 25rpx;
height: 25rpx;
margin-right: 10rpx;
}
text {
height: 30rpx;
line-height: 30rpx;
}
}
.color2F308A {
color: #2F308A;
font-weight: bold;
}
}
.text-content {
font-weight: bold;
font-size: 28rpx;
color: #111111;
text-align: left;
padding: 24rpx 0;
background-color: #F7F9FC;
}
}
.index-list {
width: 90%;
height: 100%;
margin: 0 auto;
background-color: #FFF !important;
border-radius: 10px;
.city-list {
width: 80%;
position: relative;
margin-left: 10px;
.current-city-box {
padding: 30rpx 0;
.current-city-name {
color: #111111;
font-size: 30rpx;
font-weight: 500;
}
.current-city-btn {
margin-left: 10rpx;
font-size: 20rpx;
background-color: rgba(77, 185, 213, .2);
color: #4DB9D5;
padding: 4rpx 12rpx;
border-radius: 8rpx;
}
}
}
.city-keywords {
width: 100%;
height: 50rpx;
line-height: 50rpx;
font-weight: bold;
font-size: 32rpx;
background-color: whitesmoke;
}
.city-fullname {
width: 100%;
height: 80rpx;
line-height: 80rpx;
font-size: 28rpx;
font-weight: bold;
background-color: #FFFFFF;
border-bottom: solid 0.4px #ECECEC;
}
}
}
// 样式穿透,修改u-view组件的背景色
.page /deep/ .u-index-anchor-wrapper .u-index-anchor {
background-color: #fff;
}
.page /deep/ .u-search {
width: 90%;
margin: 0 auto !important;
}
.bg-white {
background-color: #FFF;
width: 100%;
height: 100vh;
.search-city-name {
width: 100%;
height: 60rpx;
line-height: 60rpx;
text-indent: 1em;
font-size: 28rpx;
font-weight: 600;
border-bottom: 1px solid #C0C0C0;
}
}
</style>
切换城市页面
切换该城市的区域
关键字搜索功能实现