uniapp楼层跳转、锚点效果

 话不多说,直接上代码:

1、内容滚动,头部tab选中效果也自动移动,且支持tab自动左右移动

2、tab点击,内容自动滚动

<template>
	<view class="home-page">
		<view class="slider-tab">
		    <!-- 头部tab -->
			<view class="top-tabs" :style="{paddingTop:navBarHeight + 50 + 'px'}">
				<scroll-view scroll-x="true" :scroll-left="scrollLeft" @scroll="scrollTab" class="tab-box">
					<view v-for="(item, index) in navList" :key="item.name" :class="'tab-item f-title tab-item' + index"
						@click="changeScrollTop(item, index)">
						<view :class="{'menu-topic-act':currentActive === index}">
							<text class="menu-topic-text">{{item.name}}</text>
						</view>
					</view>
				</scroll-view>
			</view>
		    <!-- 展示内容 -->
		    <view class="page-contetns">
		      <view class="items" v-for="(item, index) in navList" :key="index">
		        <view :class="'item' + index" style="height:600rpx">
		          <h2>{{ item.val }}</h2>
		        </view>
		      </view>
		    </view>
		</view>
	</view>
</template>

<script>
	export default {
		name:"home",
		data() {
			return {
				navBarHeight: 0,
				navList: [
					{
					  name: '全部',
					  val: '全部'
					},
					{
					  name: 'demo1',
					  val: 'demo1'
					},
					{
					  name: 'demo2',
					  val: 'demo2'
					},
					{
					  name: 'demo3',
					  val: 'demo3'
					},
					{
					  name: 'demo4',
					  val: 'demo4'
					},
					{
					  name: 'demo5',
					  val: 'demo5'
					},
					{
					  name: 'demo6',
					  val: 'demo6'
					},
				],
			    preActive: 0,
			    currentActive: 0,
			    isClick: false,
				scrollLeft: 0,
				old: {
					scrollLeft: 0
				},
			}
		},
		created() {
			this.navBarHeight = uni.getSystemInfoSync()['statusBarHeight'];
		},
		onPageScroll (obj) {
		    const { scrollTop } = obj
		    this.scrollTochang(scrollTop)
		},
		mounted () {
		    this.$nextTick(() => {
				this.navList.forEach((item, index) => {
					uni
						.createSelectorQuery()
						.select('.page-contetns')
						.boundingClientRect(data => {
							uni
								.createSelectorQuery()
								.select(`.item${index}`)
								.boundingClientRect(res => {
									item.scrollTop = res.top - data.top;
								})
								.exec()
						})
						.exec()
					uni
						.createSelectorQuery()
						.select('.top-tabs')
						.boundingClientRect(data => {
							uni
								.createSelectorQuery()
								.select(`.tab-item${index}`)
								.boundingClientRect(res => {
									item.scrollLeft = res.left - data.left;
								})
								.exec()
						})
						.exec()
				})
			})
		},
		methods: {
			changeScrollTop (item, index) {
			    this.isClick = true
			    const that = this
			    const { scrollTop } = item
			    this.currentActive = index
			    uni.pageScrollTo({
					duration: 80 * Math.abs(this.currentActive - this.preActive),
					scrollTop,
					complete () {
					    that.isClick = false
					}
			    })
			    this.preActive = this.currentActive
			},
			scrollTochang (scrollTop) {
			    if (this.isClick) return
			    const idx = this.navList.findIndex(item => scrollTop <= item.scrollTop);
			    if (this.currentActive === idx) return
			    this.currentActive = idx;
			    this.preActive = this.currentActive;
			    if (this.old.scrollLeft > this.navList[idx].scrollLeft ||
			    	(this.old.scrollLeft + uni.getWindowInfo().windowWidth) < this.navList[idx].scrollLeft) {
			    	this.scrollLeft = this.old.scrollLeft;
			    	this.$nextTick(() => {
			    		this.scrollLeft = this.navList[idx].scrollLeft;
			    	});
			    }
			},
			scrollTab(e) {
				this.old.scrollLeft = e.detail.scrollLeft;
			},
		},
	}
</script>

<style lang="scss" scoped>
	.home-page {
		box-sizing: border-box;
		.slider-tab {
			background: #F7F7F7;

			::-webkit-scrollbar {
				display: none;
				width: 0 !important;
				height: 0 !important;
				-webkit-appearance: none;
				background: transparent;
				color: transparent;
			}

			uni-scroll-view .uni-scroll-view::-webkit-scrollbar {
				/* 隐藏滚动条,但依旧具备可以滚动的功能 */
				display: none;
				width: 0 !important;
				height: 0 !important;
				-webkit-appearance: none;
				background: transparent;
				color: transparent;
			}
			
			.top-tabs {
				display: flex;
				flex-direction: column;
				position: sticky;
				top: 0;
				left: 0;
				white-space: nowrap;
				width: 100%;
				height: 100rpx;
				z-index: 10;
				background: #E6FDFB;
				
				.tab-box {
					width: 100%;
					height: 72rpx;
						
					.tab-item {
						display: inline-block;
						white-space: nowrap;
						height: 72rpx;
						position: relative;
						
						.menu-topic-text {
							font-weight: 400;
							font-size: 30rpx;
							color: #313335;
							padding: 10rpx 28rpx;
						}
						
						.menu-topic-act {
							.menu-topic-text {
								font-weight: 700;
								font-size: 31rpx;
								color: #000000;
						
								&::after {
									content: '';
									position: absolute;
									background-image: url(https://i.hd-r.cn/48760310f06b922d7bb10fe49b9360ba.png);
									background-size: cover;
									width: 40rpx;
									height: 26rpx;
									bottom: 8rpx;
									left: calc(50% - 20rpx);
								}
							}
						}
					}
				}
			}
		}
	}
</style>

效果图粗略如下:

 直接可运行。

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱吃彩虹吐司的安琪拉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值