微信小程序实现按字母排列选择城市功能


Posted in Javascript onNovember 25, 2019

实现效果预览

微信小程序实现按字母排列选择城市功能

实现思想

利用小程序腾讯地图将所有城市查出来,并将其渲染至页面(https://lbs.qq.com/qqmap_wx_jssdk/index.html)(其中字母栏也根据获取到的数据变化)

其中涉及三个交互(点击字母时滚动到相应位置;滑动触摸字母时,需滚动到相应位置,并有当前哪个字母的提示,且有震动感;手动滑动页面时,需将当前对应的字母选中)

滑动触摸字母时,首先要得到所有字母所在块的高度,再平均的获取到每个字母的高度。当触摸滚动时,拿到pageY(距离文档左上角的距离,具体解释官网有https://developers.weixin.qq.com/miniprogram/dev/framework/view/wxml/event.html#touches)

计算出所有字母内容的高度,并存为一个数组

利用pageY计算出可能到达的字母位置的下标(pageY-字母栏的top值/每个字母的高度)

将计算出的下标所对应的字母内容高度赋值给scroll-top值

手动滚动列表时,根据滚动的距离计算出当前滚动的下标值,将字母数组的对应的下标值做处理

需要注意setData不能频繁使用,所以在使用的时候,需要做处理和优化

实现知识点

字母滚动到相应位置需使用scroll-view组件中的scroll-into-view 设置其子元素的id值

滑动触摸字母,需使用小程序事件touchmove事件和touchend事件

手动滑动页面时,需使用scroll-view中的scroll-top属性设置竖向滚动条位置

代码

wxml

<!--pages/findHome/selectCity/index.wxml-->
<view class="selectCity">
 <view class="searchCity">
 <input placeholder="输入城市名进行搜索" bindinput="getSuggest" bindfocus="inputFocus"></input>
 </view>
 <view class="cityContainer" style="padding-top: {{searchCity}}px">
 <scroll-view scroll-y="true" scroll-into-view="{{toView}}" scroll-top="{{scrollTop}}" bindscroll="scroll" style="height: 100%" scroll-with-animation="ture">
 <block wx:for="{{citys}}" wx:for-index="key" wx:for-item="value" wx:key="key">
 <view class="cityItem">
  <view class="citytype" id="{{value.id}}">{{key}}</view>
  <block wx:for="{{value.data}}" wx:for-key="i" wx:for-item="ele" wx:key="i">
  <view class="cityDetail" data-name="{{ele.fullname}}" bindtap="confrimCity">{{ele.fullname}}</view>
  </block>
 </view>
 </block> 
 </scroll-view> 
 <view class="cityAZ">
 <block wx:for="{{letter}}" wx:key="{{id}}">
 <view bindtap="letterClick" class="AZ {{!touchFlag && activeAZ == item.id ? 'activeAZ' : ''}}" data-id="{{item.id}}" catchtouchmove="whenTouch" catchtouchend="touchEnd" id="{{item.id}}">{{item.name}}
 <view class="AZInfo" wx:if="{{touchFlag && activeAZ == item.id}}">
  {{item.name}}
  <view class="trigle"></view>
 </view>
 </view>
 </block>
 </view>
 </view>
</view>

wxss

/* pages/findHome/selectCity/index.wxss */
.selectCity {
 width: 100vw;
 height: 100vh;
}
.searchCity {
 height: 70rpx;
 line-height: 70rpx;
 width: 100%;
 padding: 0 24rpx;
 position: fixed;
 top: 0;
 left: 0;
 background: #fff;
 z-index: 10;
}
.cityContainer {
 height: 100%;
}
.cityItem {
 padding: 0 70rpx 0 24rpx;
}
.citytype {
 height: 70rpx;
 background: #F5F5F5;
 line-height: 70rpx;
 padding: 0 24rpx;

}
.cityDetail {
 height: 80rpx;
 line-height: 80rpx;
 padding: 0 24rpx;
 border-top: 1px solid #DCDCDC;
 border-bottom: none;
}
.cityDetail:last-child {
 border-bottom: 1px solid #DCDCDC;
}
.cityAZ {
 position: fixed;
 top: 136rpx;
 right: 0;
 font-size: 28rpx;
 padding: 0 24rpx;
 /* background: #fff; */
 width: 40rpx;
 text-align: center;
}
.AZ {
 position: relative;
 border-radius: 50%;
}
.activeAZ {
 background: orange;
 color: #fff;
}
.AZInfo {
 width: 70rpx;
 height: 70rpx;
 border-radius: 50%;
 text-align: center;
 color: #fff;
 line-height: 70rpx;
 background: orange;
 position: absolute;
 left: -94rpx;
 top: -14rpx;
}
.trigle {
 width: 0;
 height: 0;
 border: 32rpx solid orange;
 border-right: none;
 border-top-color: transparent;
 border-bottom-color: transparent; 
 position: absolute;
 top: 4rpx;
 right: -9rpx;
}

js

// pages/findHome/selectCity/index.js
let cityDatas = require('../../../utils/cityData.js');
let QQMapWX = require('../../../libs/qqmap-wx-jssdk.js');
let qqmapsdk = new QQMapWX({
 key: '4WKBZ-ADX36-MGNS4-E6TFJ-Q6JJE-YBF2A'
});
Page({

 /**
 * 页面的初始数据
 */
 data: {
 citys: {},//获取到的所有城市
 letter: [], //获取到的所有字母
 searchCity: 0,
 toView: '', //点击跳转的id
 scrollTop: '',
 citysHeight: [],//所有字母大模块的top
 azHeight: 0, //每个字母平均的高度
 azTop: 0,
 index: '',
 activeAZ: 'A1',
 touchFlag: false
 },
 letterClick: function (e) {
 this.setData({
 touchFlag: false,
 toView: e.currentTarget.dataset.id
 // activeAZ: e.currentTarget.dataset.id,
 })
 },
 confrimCity() {
 wx.switchTab({
 url: '/pages/findHome/index',
 })  
 },
 whenTouch(e) {
 let index = 0;
 if((e.touches[0].pageY - this.data.azTop) % this.data.azHeight == 0){
 index = (e.touches[0].pageY - this.data.azTop) / this.data.azHeight
 }else {
 index = parseInt((e.touches[0].pageY - this.data.azTop) / this.data.azHeight);
 if(this.data.index !== index && index < this.data.letter.length) {
 this.data.index = index;
 this.setData({
  scrollTop: this.data.citysHeight[index],
  activeAZ: this.data.letter[index].id,
  touchFlag: true
 })
 wx.vibrateShort();
 }
 }
 },
 touchEnd() {
 setTimeout(()=>{
 this.setData({
 touchFlag: false
 })
 },600)
 },
 scroll(e) {
 let scrollHeight = e.detail.scrollTop;
 let index = this.calculateIndex(this.data.citysHeight, scrollHeight);
 if (this.data.index !== index && index < this.data.letter.length) {
 this.setData({
 index: index,
 activeAZ: this.data.letter[index].id,
 touchFlag: false
 })
 }
 },
 calculateIndex(arr, scrollHeight) {
 let index = 0;
 for (let i = 0; i < arr.length; i++) {
 if (scrollHeight >= arr[i - 1] && scrollHeight < arr[i]) {
 index = i - 1;
 break;
 }else if(scrollHeight >= arr[arr.length-1]) {
 index = arr.length - 1;
 break;
 }else if(0 < scrollHeight < arr[0]) {
 index = 0
 }
 }
 return index;
 },
 getSuggest(e) {
 console.log(e)
 },
 /**
 * 生命周期函数--监听页面加载
 */
 onLoad: function (options) {
 let query = wx.createSelectorQuery();
 query.select('.searchCity').boundingClientRect(rect => {
 this.setData({
 searchCity: rect.height
 })
 }).exec();
 qqmapsdk.getCityList({
 success: (res) => {//成功后的回调
 res.result[1].forEach(ele => {
  //如果城市对象中已经存在该字母开头的
  if (this.data.citys[ele.pinyin[0].charAt(0).toUpperCase()]){
  this.data.citys[ele.pinyin[0].charAt(0).toUpperCase()].data.push(ele);
  }else {
  this.data.citys[ele.pinyin[0].charAt(0).toUpperCase()] = {id: '',data: []};
  this.data.citys[ele.pinyin[0].charAt(0).toUpperCase()].id = ele.pinyin[0].charAt(0).toUpperCase()+1;
  this.data.citys[ele.pinyin[0].charAt(0).toUpperCase()].data.push(ele);
  }
 })
 let newArr = Object.keys(this.data.citys).sort();
 let sortCity = {};
 newArr.forEach(ele => {
  this.data.letter.push({name: ele, id: ele+1})
  sortCity[ele] = this.data.citys[ele]
 })
 this.setData({
  citys: sortCity,
  letter: this.data.letter,
  citysHeight: []
 });
 //获取个字母大模块的top值
 query.selectAll('.cityItem').boundingClientRect((rect) => {
  this.data.citysHeight = [];
  rect.forEach(ele => {
  this.data.citysHeight.push(ele.top - this.data.searchCity)
  })
 }).exec();

 //获取已有字母的高度
 let winH = wx.getSystemInfoSync().windowHeight; 
 query.select('.cityAZ').boundingClientRect((rect) => {
  this.data.azHeight = rect.height / this.data.letter.length;
  this.data.azTop = rect.top;
 }).exec();
 },
 fail: function (error) {
 console.error(error);
 },
 complete: function (res) {
 
 }
 });
 this.setData({
 toView: 'A1'
 });

 }
})

总结

以上所述是小编给大家介绍的微信小程序实现按字母排列选择城市,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

Javascript 相关文章推荐
(jQuery,mootools,dojo)使用适合自己的编程别名命名
Sep 14 Javascript
简单的jquery拖拽排序效果实现代码
Sep 20 Javascript
js opener的使用详解
Jan 11 Javascript
jQuery源码解读之hasClass()方法分析
Feb 20 Javascript
3个可以改善用户体验的AngularJS指令介绍
Jun 18 Javascript
jQuery仿淘宝网产品品牌隐藏与显示效果
Sep 01 Javascript
JavaScript、jQuery与Ajax的关系
Jan 24 Javascript
AngularJS中isolate scope的用法分析
Nov 22 Javascript
详解微信小程序缓存--缓存时效性
May 02 Javascript
Layui之table中的radio在切换分页时无法记住选中状态的解决方法
Sep 02 Javascript
vue-router的钩子函数用法实例分析
Oct 26 Javascript
VUE渲染后端返回含有script标签的html字符串示例
Oct 28 Javascript
JS实现点击下拉列表文本框中出现对应的网址,点击跳转按钮实现跳转
Nov 25 #Javascript
jquery使用echarts实现有向图可视化功能示例
Nov 25 #jQuery
如何优雅地在Node应用中进行错误异常处理
Nov 25 #Javascript
jQuery Raty星级评分插件使用方法实例分析
Nov 25 #jQuery
uni-app实现点赞评论功能
Nov 25 #Javascript
js prototype深入理解及应用实例分析
Nov 25 #Javascript
KnockoutJS数组比较算法实例详解
Nov 25 #Javascript
You might like
PHP出错界面
2006/10/09 PHP
详谈PHP文件目录基础操作
2014/11/11 PHP
ThinkPHP3.2.3框架实现执行原生SQL语句的方法示例
2019/04/03 PHP
TP5框架简单登录功能实现方法示例
2019/10/31 PHP
JavaScript高级程序设计阅读笔记(十六) javascript检测浏览器和操作系统-detect.js
2012/08/14 Javascript
cookie.js 加载顺序问题怎么才有效
2013/07/31 Javascript
ajax读取数据后使用jqchart显示图表的方法
2015/06/10 Javascript
遮罩层点击按钮弹出并且具有拖动和关闭效果(两种方法)
2015/08/20 Javascript
javascript从定义到执行 你不知道的那些事
2016/01/04 Javascript
EasyUI Pagination 分页的两种做法小结
2016/07/09 Javascript
浅谈JS继承_借用构造函数 &amp; 组合式继承
2016/08/16 Javascript
巧用Vue.js+Vuex制作专门收藏微信公众号的app
2016/11/03 Javascript
angular.js指令中transclude选项及ng-transclude指令详解
2017/05/24 Javascript
vue实现整屏滚动切换
2020/06/29 Javascript
微信小程序实现自定义动画弹框/提示框的方法实例
2020/11/06 Javascript
[03:59]DOTA2英雄梦之声_第07期_水晶室女
2014/06/23 DOTA
python创建线程示例
2014/05/06 Python
Python接收Gmail新邮件并发送到gtalk的方法
2015/03/10 Python
Win10下Python环境搭建与配置教程
2016/11/18 Python
python使用pil进行图像处理(等比例压缩、裁剪)实例代码
2017/12/11 Python
修复CentOS7升级Python到3.6版本后yum不能正确使用的解决方法
2018/01/26 Python
Python 新建文件夹与复制文件夹内所有内容的方法
2018/10/27 Python
python如何删除列为空的行
2020/07/17 Python
pandas抽取行列数据的几种方法
2020/12/13 Python
详解HTML5中的标签
2015/06/19 HTML / CSS
sleep()方法和wait()方法的区别是什么
2012/11/17 面试题
初三学习计划书范文
2014/04/30 职场文书
国际商务专业毕业生自我鉴定2014
2014/09/27 职场文书
大学生上课迟到检讨书
2014/10/15 职场文书
考试没考好检讨书(精选篇)
2014/11/16 职场文书
超市工作总结范文2014
2014/12/19 职场文书
公务员年度个人总结
2015/02/12 职场文书
2015年七一建党节活动方案
2015/05/05 职场文书
《秦兵马俑》教学反思
2016/02/24 职场文书
《雀魂PONG☆》4月1日播出 PV角色设定情报
2022/03/20 日漫
Nginx 匹配方式
2022/05/15 Servers