网站制作器软件下载/最新的疫情情况
效果:红色位置代码
实现功能描述:
左侧内容滚动的时候,右侧首字母会变换选中,右侧选中指定首字母,左侧内容滚到指定位置。
组件game_list
<template><div><div class="game_list"><div class="left_list_box" ref="scrollBox" @scroll="contentScroll"><divv-for="(key, index) in Object.keys(gamesObject).sort()":key="index":id="key":ref="key"><div class="title_name">{{ key }}</div><div class="left_list_game"><divclass="game_item"v-for="(item, _index) in gamesObject[key]":key="_index":class="$attrs['letter-hidden'] ? 'letter_hidden' : ''"><van-image :src="item.Icon" width="1.12rem" height="1.12rem"></van-image><p :class="$attrs['letter-hidden'] ? 'show_oneline' : ''">{{ item.Name }}</p></div></div></div></div><div class="right_word_box" v-if="!$attrs['letter-hidden']" @scroll="menuScroll"><div ref="rightBox" :style="{ top: rightScrollTop + 'px' }"><divclass="letter add_margin_top":class="isChoose == '热' ? 'is_choose' : ''"@click="toLetter('热')">热</div><divclass="letter"v-for="(letter, index) in firstLetter.split('')":key="index":class="isChoose == letter ? 'is_choose' : ''"@click="toLetter(letter)":ref="'menu_' + letter">{{ letter }}</div></div></div></div><!-- <empty-page></empty-page> --></div>
</template><script>
import { nextTick } from 'vue'
import EmptyPage from '../../components/Empty/EmptyPage.vue'
export default {name: '',props: {gameList: {type: Array}},data() {return {// 处理后的游戏列表gamesObject: {},firstLetter: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ#',isChoose: '热',clickMenu: false, //点击菜单时候rightScrollTop: 200 //右侧菜单的滚动距离}},components: { EmptyPage },watch: {gameList(newVal) {let arr = newVal.concat()arr.reverse()let tempName = ''//重构列表结构arr.forEach((game, index) => {if (index == 0) {this.$set(this.gamesObject, game.NameInitials.toUpperCase(), [])tempName = game.NameInitials.toUpperCase()}if (tempName != game.NameInitials.toUpperCase()) {this.$set(this.gamesObject, game.NameInitials.toUpperCase(), [])}this.gamesObject[game.NameInitials.toUpperCase()].push(game)})},// 选中的首字母监听用于右侧首字母栏的滚动isChoose(newVal) {// 获取内容盒子到头部的距离let headerHeight = this.$refs['rightBox'].offsetTop// 当前点击字母的距离右侧菜单框的距离let chooseTop = this.$refs['menu_' + newVal][0].offsetTop - headerHeight// 获取右侧菜单盒子可见高度let rightMenuHeight = this.$refs['scrollBox'].offsetHeight// 右侧菜单内容实际高度let rightRealHeight = this.$refs['rightBox'].offsetHeight// 如果当前点击的字母的位置占据了rightMenuHeight高后四分之一的位置。就让右侧菜单网上滚一个二分之一rightMenuHeight的高度if (chooseTop >= rightMenuHeight * (3 / 4)) {//让右侧菜单往上滚动1/2rightMenuHeight后没有到达右侧菜单的实际高度if (this.rightScrollTop + rightMenuHeight * (3 / 2) < rightRealHeight) {console.log('执行')// 继续向上滚动nextTick(() => {this.rightScrollTop = this.rightScrollTop + rightMenuHeight * (3 / 2)})} else {//让右侧菜单往上滚动1/2rightMenuHeight过程中会打到达右侧菜单的实际高度,为最后一下的滚动// debuggernextTick(() => {this.rightScrollTop =this.rightScrollTop + rightRealHeight - this.rightScrollTop - rightMenuHeight})}}}},created() {},mounted() {},methods: {toLetter(letter) {this.isChoose = letterthis.clickMenu = trueconst point = document.getElementById(letter)point &&point.scrollIntoView({block: 'start',behavior: 'smooth'})// 设置滚动之后过一段时间恢复clickMenu字段,避免自定义滚动操作和点击后滚动同时出现setTimeout(() => {this.clickMenu = false}, 1000)},// 监听内容盒子的滚动事件contentScroll(e) {// 判断是不是鼠标点击菜单导致滚动if (!this.clickMenu) {// 记录内容滚动距离let scrollTop = e.srcElement.scrollTop// 获取内容盒子到头部的距离let headerHeight = this.$refs['scrollBox'].offsetTop// 根据滚动值,查询在哪两个字母的区间内for (let i = 0; i < this.firstLetter.length - 1; i++) {// 首个字母出现的位置let letter_before = 0// 第二个字母出现的位置let letter_after = nullif (this.$refs[this.firstLetter.split('')[i]]) {letter_before = this.$refs[this.firstLetter.split('')[i]][0].offsetTop - headerHeight}if (i != this.firstLetter.length - 1 && this.$refs[this.firstLetter.split('')[i + 1]]) {letter_after = this.$refs[this.firstLetter.split('')[i + 1]][0].offsetTop - headerHeight}// 鼠标滚动一次是100if (scrollTop + 100 >= letter_before && scrollTop + 100 < letter_after) {this.isChoose = this.firstLetter.split('')[i]break}}}},// 监听右侧菜单盒子滚动事件menuScroll(e) {this.rightScrollTop = e.srcElement.scrollTop}}
}
</script><style lang="scss" scoped>
.game_list {width: 100%;display: flex;justify-content: space-between;
}
// 左侧游戏列表
.left_list_box {flex: 1;height: calc(100vh - 0.92rem);overflow-y: scroll;padding: 0 0.14rem;padding-bottom: 1.08rem;box-sizing: border-box;.title_name {font-size: 0.28rem;color: #111;font-weight: bold;padding: 0.32rem 0.3rem;}.left_list_game {overflow: hidden;display: flex;flex-wrap: wrap;justify-content: flex-start;align-content: flex-start;border-bottom: 0.02rem solid #edeef1;padding-bottom: 0.34rem;.game_item {width: 1.48rem;display: flex;flex-direction: column;align-items: center;margin: 0 0.06rem 0.2rem;height: max-content;p {width: 1.48rem;font-size: 0.24rem;color: #555555;margin-top: 0.22rem;white-space: pre-wrap;text-align: center;}// 只显示一行.show_oneline {white-space: nowrap;overflow: hidden;text-overflow: ellipsis;}}// 当右侧首字母列隐藏时候.letter_hidden {margin: 0 0.16rem 0.2rem;}}
}/* 右侧首字母选择 */
.right_word_box {width: 0.8rem;box-sizing: border-box;height: calc(100vh - 0.92rem);overflow-y: scroll;padding-bottom: 1.08rem;padding-top: 0.5rem;.letter {height: 0.7rem;line-height: 0.7rem;text-align: center;font-size: 0.28rem;color: #111;}.is_choose {width: 0.8rem;height: 0.4rem;line-height: 0.4rem;text-align: center;font-size: 0.28rem;background: linear-gradient(90deg, #ff650d, #ffa40d);color: #fff;border-radius: 0.3rem 0 0 0.3rem;padding: 0.04rem 0;box-sizing: content-box;}
}
</style>
使用组件