uni-app吸顶+带动画滑动的tabs导航栏

需求就是两点
1,页面滚动到该导航位置吸顶
2,导航tabs切换带动画,包括下划线

效果如下:
在这里插入图片描述

首先是可滑动,用scroll-view实现,然后吸顶效果是在Dcloud是在市场找的,下划线滑动动画是插件市场这个插件改来的,show code:

**// html**
<!-- 吸顶 -->
<view class="sticky-box">
	<!-- 滑动区域 -->
	<scroll-view class="scroll-view_H" style="width: 80%;" scroll-x="true" scroll-with-animation :scroll-left="tabsScrollLeft" @scroll="scroll">
		<view class="tab" id="tab_list">
			<view id="tab_item" :class="{ 'active': listActive == index,'tab__item':true}" v-for="(item, index) in listArr" :key="index" @click="clickSort(index)">
				{{item}}
			</view>
		</view>
		<!-- tabs下划线 -->
		<view class="tab__line"
			  :style="{background: lineColor, width: lineStyle.width, transform: lineStyle.transform,transitionDuration: lineStyle.transitionDuration}">
		</view>
	</scroll-view>
	<!-- 全部按钮 -->
	<view class="listAll">
		<image src="../../static/images/all_filter.png" style="width: 36rpx; height: 36rpx;" mode="aspectFill"></image>
		全部
	</view>
</view>

**// js**
<script>

export default {
  data () {
    return {
		listArr: ['压箱好书','最新上架','名著','历史','童书','生活','心理学','艺术','推理','外国文学'],
		listActive: 0,   // 当前选中项
		tabsScrollLeft: 0,  // tabs当前偏移量
		scrollLeft:0,
		lineStyle: {},    // 下划线位置--动态甲酸
		duration: 0.2    // 下划线动画时长
	}
  },
  watch: {
  	listActive(newVal) {     // 监听当前选中项
  		this.setTabList()
  	}
  },

  mounted () {
      this.setTabList()
  },
  methods: {
    clickSort (index) {
		this.listActive = index
	},
	// scroll-view滑动事件
	scroll(e) {
		this.scrollLeft = e.detail.scrollLeft;
	},
	setTabList() {
		this.$nextTick(()=>{
			this.setLine()
			this.scrollIntoView()
		})
	},
	// 计算tabs位置
	scrollIntoView() {  // item滚动
		let lineLeft = 0;
		this.getElementData('#tab_list', (data)=> {
			let list = data[0]
			this.getElementData(`#tab_item`, (data)=> {
				let el = data[this.listActive]
				lineLeft = el.width / 2 + (-list.left) + el.left - list.width / 2 - this.scrollLeft
				this.tabsScrollLeft = this.scrollLeft + lineLeft
			})
		})
	},
	//  计算下划线位置
	setLine() {
		let lineWidth = 0, lineLeft = 0
		this.getElementData(`#tab_item`, (data)=> {
			let el = data[this.listActive]
			lineWidth = el.width / 2
			// lineLeft = el.width * (this.currentIndex + 0.5)  // 此种只能针对每个item长度一致的
			lineLeft = el.width / 2 + (-data[0].left) + el.left
			this.lineStyle = {
				width: `${lineWidth}px`,
				transform: `translateX(${lineLeft}px) translateX(-50%)`,
				transitionDuration: `${this.duration}s`
			};
		})
	},
	getElementData(el, callback){
		uni.createSelectorQuery().in(this).selectAll(el).boundingClientRect().exec((data) => {
			callback(data[0]);
		});
	},
  },
}
</script>


	**// style**
	.sticky-box {
		/* #ifndef APP-PLUS-NVUE */
		display: flex;
		position: -webkit-sticky;
		/* #endif */
		position: sticky;
		top: var(--window-top);
		z-index: 99;
		flex-direction: row;
		margin: 0px;
		border-top: 1px #f9f9f9 solid;
		border-bottom: 1px #f9f9f9 solid;
		background: #fff;
	}
	.listAll{
		width: 20%;
		text-indent: 62rpx;
		font-size: 30rpx;
		border-left: 1px #eee solid;
		margin: 1% 0 ;
		padding: 5rpx;
		position: relative;
		image{
			position: absolute;
			left: 20rpx;
			top: 8rpx;
		}
	}
	.tab {
		position: relative;
		display: flex;
		font-size: 28rpx;
		padding-bottom: 10rpx;
		white-space: nowrap;
		&__item {
			flex: 1;
			padding: 0 20rpx;
			text-align: center;
			height: 60rpx;
			line-height: 60rpx;
			color: #666;
			&.active {
				color: #09C2C9;
			}
		}
	}
	.tab__line {
		display: block;
		height:6rpx;
		position: absolute;
		bottom: 0;
		left: 0;
		z-index: 1;
		border-radius: 3rpx;
		position: relative;
		background: #2FC6CD;
	}
	.scroll-view_H {
		/* 文本不会换行,文本会在在同一行上继续,直到遇到 <br> 标签为止。 */
		white-space: nowrap;
		width: 100%;
	}

ok,就这么多,至于动画那部分的实现的计算逻辑,可以去插件市场看看我上面提到的那个插件,我本来直接也是用那个插件,但是各种不适用,所以拿出来了我自己需要的部分。

苦海无涯,学习是岸

  • 7
    点赞
  • 61
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值