微信小程序scroll-view实现左右联动

2022-04-15 0 713

本文实例为大家分享了微信小程序scroll-view实现左右联动的具体代码,供大家参考,具体内容如下

需求:项目中做了一个选择城市的需求,要求全国所有的省市区都按照中文首字母分类并排序,左侧的城市列表和右侧的字母列表实现双向联动。

微信小程序scroll-view实现左右联动

第一步:根据腾讯提供的javascript SDK提供的接口,获取所有的省市区,并将省市区按照首字母进行分类排序。

let _this = this;
_this.mapCtx = wx.createMapContext("myMap");
        // 实例化API核心类
        qqmapsdk = new QQMapWX({
            key: MAP_KEY,
        });
 
        // 获取全国的城市列表
        qqmapsdk.getCityList({
            success: function (res) {
                let list = res.result[0].concat(res.result[1], res.result[2]);
                _this.allCity = list;
                _this.cityList = _this.pySegSort(list);
            },
            fail: function (error) {
                console.error(error);
            },
            complete: function (res) {
                console.log(res);
            },
        });
 
        pySegSort(arr) {
            if (!String.prototype.localeCompare) return null;
            let letters = "*ABCDEFGHJKLMNOPQRSTWXYZ".split("");
            let zh = "阿八嚓哒妸发旮哈讥咔垃痳拏噢妑七呥扨它穵夕丫帀".split("");
            let segs = [];
            let curr;
            letters.forEach(function (item, i) {
                curr = { letter: item, id: item, data: [] };
                arr.forEach(function (item2) {
                    if (
                        (!zh[i - 1] || zh[i - 1].localeCompare(item2.fullname) <= 0) &&
                        item2.fullname.localeCompare(zh[i]) == -1
                    ) {
                        curr.data.push(item2);
                    }
                });
                if (curr.data.length) {
                    curr.data.sort(function (a, b) {
                        return a.fullname.localeCompare(b.fullname);
                    });
                    segs.push(curr);
                }
            });
            return segs;
        },

第二步: 计算各个首字母组成的列表的高度

在使用query.selectAll(‘.cityList’)时应放入setTimeout中异步获取,不然页面还没加载完,获取不到,尝试使用$nextTick()也是没有获取到的。

// 获取热门城市盒子的高度
 let query = wx.createSelectorQuery().in(this);
        query
            .select(".hot-city")
            .boundingClientRect((data) => {
                this.hotCityHeight = data.height;
            })
            .exec();
 
        
        // 获取各个字母分类的块高度
        setTimeout(() => {
            let query = wx.createSelectorQuery().in(this);
            query
                .selectAll(".cityList")
                .boundingClientRect((data) => {
                    console.log(data, "各个城市分类的高度");
                    this.letterBoxHeight = data;
                    this.heightArr = this.getHeiht();
                })
                .exec();
        }, 1000);  // 使用setTimeout进行异步获取,不然获取不到
 
        // 计算每个区域的高度
        getHeiht() {
            let n = this.hotCityHeight;
            let arr = [];
            this.letterBoxHeight.forEach((item) => {
                n = n + item.height;
 
                arr.push(n);
            });
            return arr;
        },

第三步:实现点击右侧,左侧联动。

点击右侧字母列表时,实现左侧城市列表的滚动到可视区域,这时需要 scroll-into-view=”childViewId”

// 点击右侧的字母
letterClick(letter, i) {
            this.letterIndex = i;
            this.currentIndex = i;
            this.childViewId = letter;
            setTimeout(() => {
                this.letterIndex = -1;
            }, 500); // 0.5秒后浮出的首字母圆圈消失
        },

第四步:实现滑动左侧,右侧联动。

当滑动城市列表时,需要判断当前的滚动高度,在哪个字母范围内,在该范围内的字母需高亮。

calculateIndex(arr, scrollHeight) {
   let index = "";
   for (let i = 0; i < arr.length; i++) {
                if (scrollHeight >= this.hotCityHeight && scrollHeight < arr[0]) {
                    index = 0;
                } else if (scrollHeight >= arr[i - 1] && scrollHeight < arr[i]) {
                    index = i;
                }
            }
            return index;
        },
        // 计算滚动距离
        scroll(e) {
            let scrollTop = e.detail.scrollTop;
            let scrollArr = this.heightArr;
            let index = this.calculateIndex(scrollArr, scrollTop);
            this.currentIndex = index;
        },

完成代码如下:

created() {
        let _this = this;
        _this.mapCtx = wx.createMapContext("myMap");
        // 实例化API核心类
        qqmapsdk = new QQMapWX({
            key: MAP_KEY,
        });
 
        // 获取全国的城市列表
        qqmapsdk.getCityList({
            success: function (res) {
                let list = res.result[0].concat(res.result[1], res.result[2]);
                _this.allCity = list;
                _this.cityList = _this.pySegSort(list);
            },
            fail: function (error) {
                console.error(error);
            },
            complete: function (res) {
                console.log(res);
            },
        });
    },
    mounted() {
        // 获取热门城市盒子的高度
        let query = wx.createSelectorQuery().in(this);
        query
            .select(".hot-city")
            .boundingClientRect((data) => {
                this.hotCityHeight = data.height;
            })
            .exec();
 
       
        // 获取各个字母分类的块高度
        setTimeout(() => {
            let query = wx.createSelectorQuery().in(this);
            query
                .selectAll(".cityList")
                .boundingClientRect((data) => {
                    console.log(data, "各个城市分类的高度");
                    this.letterBoxHeight = data;
                    this.heightArr = this.getHeiht();
                })
                .exec();
        }, 1000);
    },
    methods: {
        // 给城市列表根据首字母排序
        pySegSort(arr) {
            if (!String.prototype.localeCompare) return null;
            let letters = "*ABCDEFGHJKLMNOPQRSTWXYZ".split("");
            let zh = "阿八嚓哒妸发旮哈讥咔垃痳拏噢妑七呥扨它穵夕丫帀".split("");
            let segs = [];
            let curr;
            letters.forEach(function (item, i) {
                curr = { letter: item, id: item, data: [] };
                arr.forEach(function (item2) {
                    if (
                        (!zh[i - 1] || zh[i - 1].localeCompare(item2.fullname) <= 0) &&
                        item2.fullname.localeCompare(zh[i]) == -1
                    ) {
                        curr.data.push(item2);
                    }
                });
                if (curr.data.length) {
                    curr.data.sort(function (a, b) {
                        return a.fullname.localeCompare(b.fullname);
                    });
                    segs.push(curr);
                }
            });
            return segs;
        },
        // 点击右侧的字母
        letterClick(letter, i) {
            this.letterIndex = i;
            this.currentIndex = i;
            this.childViewId = letter;
            setTimeout(() => {
                this.letterIndex = -1;
            }, 500);
        },
        // 计算每个区域的高度
        getHeiht() {
            let n = this.hotCityHeight;
            let arr = [];
            this.letterBoxHeight.forEach((item) => {
                n = n + item.height;
 
                arr.push(n);
            });
            return arr;
        },
        calculateIndex(arr, scrollHeight) {
            let index = "";
            for (let i = 0; i < arr.length; i++) {
                if (scrollHeight >= this.hotCityHeight && scrollHeight < arr[0]) {
                    index = 0;
                } else if (scrollHeight >= arr[i - 1] && scrollHeight < arr[i]) {
                    index = i;
                }
            }
            return index;
        },
        // 计算滚动距离
        scroll(e) {
            let scrollTop = e.detail.scrollTop;
            let scrollArr = this.heightArr;
            let index = this.calculateIndex(scrollArr, scrollTop);
            this.currentIndex = index;
        },
}
<scroll-view scroll-y style="height: 1400rpx" :scroll-into-view="childViewId"             @scroll="scroll">
            <!-- 热门城市 -->
            <view class="hot-city">
                <p>热门城市</p>
                <ul>
                    <li
                        v-for="(item, idx) in hotCityList"
                        :key="idx"
                        :class="fixedPosition === item ? 'selected' : ''"
                        @click="selectCity(item)"
                    >
                        {{ item }}
                    </li>
                </ul>
            </view>
            <!-- 字母列表 -->
            <view class="letterAz">
                <view
                    v-for="(item, idx) in letterAz"
                    :key="idx"
                    class="letter-item"
                    :class="currentIndex === idx ? 'selected' : ''"
                    @click="letterClick(item, idx)"
                >
                    {{ item }}
                    <view v-show="letterIndex === idx" class="pop-item">{{ item }}</view>
                </view>
            </view>
            <!-- 城市列表 -->
            <view v-for="(item, idx) in cityList" :key="idx" class="cityList">
                <view :id="item.id" class="city-letter">{{ item.letter }}</view>
                <view v-for="ele in item.data" :key="ele.id" class="city-name" @click="selectCity(ele.fullname)">{{
                    ele.fullname
                }}</view>
            </view>
</scroll-view>
// 热门城市
.hot-city {
    padding: 38rpx 32rpx;
    p {
        font-size: 28rpx;
        line-height: 40rpx;
        color: #999999;
        margin-bottom: 32rpx;
    }
    ul {
        display: flex;
        flex-wrap: wrap;
        & li {
            background: rgba(0, 0, 0, 0.04);
            border-radius: 16rpx;
            font-size: 28rpx;
            color: #000000;
            text-align: center;
            margin: 8rpx;
            padding: 16rpx 46rpx;
        }
        & li.selected {
            background: rgba(45, 200, 77, 0.12);
            border: 0.66rpx solid #046a38;
            color: #046a38;
        }
    }
}
// 字母列表
.letterAz {
    position: fixed;
    right: 29rpx;
    top: 380rpx;
    font-size: 20rpx;
    line-height: 28rpx;
    color: rgba(0, 0, 0, 0.55);
    .letter-item {
        position: relative;
        margin-top: 4rpx;
        .pop-item {
            position: absolute;
            right: 165%;
            bottom: -100%;
            width: 96rpx;
            height: 96rpx;
            background: #ffffff;
            border: 0.66rpx solid rgba(0, 0, 0, 0.12);
            box-sizing: border-box;
            box-shadow: 0 10rpx 24rpx rgba(0, 0, 0, 0.08);
            border-radius: 100%;
            text-align: center;
            line-height: 96rpx;
            font-size: 40rpx;
            color: rgba(0, 0, 0, 0.85);
        }
    }
    .letter-item.selected {
        color: #046a38;
    }
}
// 城市列表
.cityList {
    margin-left: 32rpx;
    margin-right: 66rpx;
    margin-top: 20rpx;
    .city-letter {
        font-size: 28rpx;
        line-height: 40rpx;
        color: #999999;
    }
    .city-name {
        font-size: 28rpx;
        line-height: 40rpx;
        color: #000000;
        padding: 32rpx 0;
        border-bottom: 2rpx solid rgba(0, 0, 0, 0.12);
    }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持NICE源码。

免责声明:
1、本网站所有发布的源码、软件和资料均为收集各大资源网站整理而来;仅限用于学习和研究目的,您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。 不得使用于非法商业用途,不得违反国家法律。否则后果自负!

2、本站信息来自网络,版权争议与本站无关。一切关于该资源商业行为与www.niceym.com无关。
如果您喜欢该程序,请支持正版源码、软件,购买注册,得到更好的正版服务。
如有侵犯你版权的,请邮件与我们联系处理(邮箱:skknet@qq.com),本站将立即改正。

NICE源码网 JavaScript 微信小程序scroll-view实现左右联动 https://www.niceym.com/24908.html