提交 f28d0e0b 编写于 作者: H hdx

swiper-list: 使用 transform: scaleX 模拟宽度,如果设置圆角会被拉伸变形, 指示线仅适用于纯色直角

上级 f4879463
<template> <template>
<view class="swiper-list"> <view class="swiper-list">
<scroll-view class="swiper-tabs" :scroll-left="tabsScrollLeft" :scroll-x="true" :show-scrollbar="false"> <scroll-view ref="tabScroll" class="swiper-tabs" :scroll-x="true" :show-scrollbar="false">
<view> <view>
<view class="flex-row"> <view class="flex-row">
<text class="swiper-tabs-item" :class="swiperIndex==index ? 'swiper-tabs-item-active' : ''" <text ref="swipertab" class="swiper-tabs-item" :class="swiperIndex==index ? 'swiper-tabs-item-active' : ''"
v-for="(item, index) in swiperList" ref="swipertab" :key="index" @click="onTabClick(index)"> v-for="(item, index) in swiperList" :key="index" @click="onTabClick(index)">
{{item.title}} {{item.title}}
</text> </text>
</view> </view>
<view class="swiper-tabs-indicator"> <view ref="indicator" class="swiper-tabs-indicator"></view>
<view class="swiper-tabs-underline"
:style="{left: swiperIndicatorLineLeft + 'px', width: swiperIndicatorLineWidth + 'px'}"></view>
</view>
</view> </view>
</scroll-view> </scroll-view>
<swiper class="swiper-view" ref="swiper" :current="swiperIndex" @transition="onSwiperTransition" <swiper ref="swiper" class="swiper-view" :current="swiperIndex" @transition="onSwiperTransition"
@animationfinish="onSwiperAnimationfinish"> @animationfinish="onSwiperAnimationfinish">
<swiper-item class="swiper-item" v-for="(_, index) in swiperList" :key="index"> <swiper-item class="swiper-item" v-for="(_, index) in swiperList" :key="index">
<text class="swiper-item-text">{{index}}</text> <text class="swiper-item-text">{{index}}</text>
...@@ -38,9 +35,8 @@ ...@@ -38,9 +35,8 @@
return { return {
swiperList: [] as SwiperViewItem[], swiperList: [] as SwiperViewItem[],
swiperIndex: -1, swiperIndex: -1,
tabsScrollLeft: 0, $tabScrollView: null as null | INode,
swiperIndicatorLineLeft: 0, $indicatorNode: null as null | INode,
swiperIndicatorLineWidth: 0,
$animationFinishIndex: 0, $animationFinishIndex: 0,
$swiperWidth: 0, $swiperWidth: 0,
$swiperTabsRect: [] as SwiperTabsItem[] $swiperTabsRect: [] as SwiperTabsItem[]
...@@ -55,6 +51,8 @@ ...@@ -55,6 +51,8 @@
} }
}, },
onReady() { onReady() {
this.$tabScrollView = this.$refs.get('tabScroll') as INode
this.$indicatorNode = this.$refs.get('indicator') as INode
this.$swiperWidth = (this.$refs["swiper"] as INode).getBoundingClientRect().width this.$swiperWidth = (this.$refs["swiper"] as INode).getBoundingClientRect().width
this.queryTabItemsSize() this.queryTabItemsSize()
this.setSwiperIndex(0, true) this.setSwiperIndex(0, true)
...@@ -63,14 +61,15 @@ ...@@ -63,14 +61,15 @@
onTabClick(index : number) { onTabClick(index : number) {
this.setSwiperIndex(index, false) this.setSwiperIndex(index, false)
}, },
/// 兼容微信 skyline 和 webview, uni-app-x 和 webview 行为一致
/// skyline 每项完成触发 Animationfinish,偏移值重置
/// webview 全部完成触发 Animationfinish,偏移值累加
/// 在滑动到下一个项的过程中,再次反向滑动,偏移值递减
onSwiperTransition(e : SwiperTransitionEvent) { onSwiperTransition(e : SwiperTransitionEvent) {
// skyline 每项完成触发 Animationfinish,偏移值重置
// webview 全部完成触发 Animationfinish,偏移值累加
// 在滑动到下一个项的过程中,再次反向滑动,偏移值递减
// uni-app-x 和 webview 行为一致
const offset_x = e.detail.dx const offset_x = e.detail.dx
// 重置差异,计算当前实时索引位置 // 重置差异,计算当前索引
const current_offset_x = offset_x % this.$swiperWidth const current_offset_x = offset_x % this.$swiperWidth
const current_offset_i = offset_x / this.$swiperWidth const current_offset_i = offset_x / this.$swiperWidth
const current_index = this.$animationFinishIndex + current_offset_i.toInt() const current_index = this.$animationFinishIndex + current_offset_i.toInt()
...@@ -87,14 +86,14 @@ ...@@ -87,14 +86,14 @@
} }
} }
// 计算蛇形线位置和大小 // 计算指示线位置和大小
const percentage = Math.abs(current_offset_x) / this.$swiperWidth const percentage = Math.abs(current_offset_x) / this.$swiperWidth
const current_size = this.$swiperTabsRect[current_index] const current_size = this.$swiperTabsRect[current_index]
const move_to_size = this.$swiperTabsRect[move_to_index] const move_to_size = this.$swiperTabsRect[move_to_index]
const indicator_line_l = current_size.x + (move_to_size.x - current_size.x) * percentage const indicator_line_l = current_size.x + (move_to_size.x - current_size.x) * percentage
const indicator_line_w = current_size.w + (move_to_size.w - current_size.w) * percentage const indicator_line_w = current_size.w + (move_to_size.w - current_size.w) * percentage
// 更新蛇形线位置和大小 // 更新指示线位置和大小
this.updateTabIndicator(indicator_line_l, indicator_line_w) this.updateTabIndicator(indicator_line_l, indicator_line_w)
// console.log(current_index + "->" + move_to_index + " x=" + offset_x + " p=" + percentage) // console.log(current_index + "->" + move_to_index + " x=" + offset_x + " p=" + percentage)
...@@ -117,6 +116,7 @@ ...@@ -117,6 +116,7 @@
if (this.swiperIndex === index) { if (this.swiperIndex === index) {
return return
} }
this.swiperIndex = index this.swiperIndex = index
if (updateIndicator) { if (updateIndicator) {
...@@ -124,9 +124,13 @@ ...@@ -124,9 +124,13 @@
} }
}, },
updateTabIndicator(left : Number, width : Number) { updateTabIndicator(left : Number, width : Number) {
this.swiperIndicatorLineLeft = left // 更新指示线
this.swiperIndicatorLineWidth = width const x = left + width / 2
this.tabsScrollLeft = left + width / 2 - this.$swiperWidth / 2 this.$indicatorNode?.style?.setProperty('transform', `translateX(${x}px) scaleX(${width}px)`)
// 将指示线滚动到水平中心位置
const scroll_x = x - this.$swiperWidth / 2
this.$tabScrollView?.setAttribute('scrollLeft', scroll_x)
} }
} }
} }
...@@ -156,15 +160,8 @@ ...@@ -156,15 +160,8 @@
} }
.swiper-tabs-indicator { .swiper-tabs-indicator {
position: relative; width: 1px;
height: 2px; height: 2px;
}
.swiper-tabs-underline {
position: absolute;
top: 0;
bottom: 0;
width: 0;
background-color: #007AFF; background-color: #007AFF;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册