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,就這麼多,至於動畫那部分的實現的計算邏輯,可以去插件市場看看我上面提到的那個插件,我本來直接也是用那個插件,但是各種不適用,所以拿出來了我自己需要的部分。

苦海無涯,學習是岸

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章