template-project/components/scroll-views/scroll-text-slide.vue

258 lines
5.9 KiB
Vue
Raw Permalink Normal View History

<template>
<view class="_tab-box" :style="{fontSize: defaultConfig.fontSize + 'rpx', color: defaultConfig.color}">
<scroll-view id="_scroll" :scroll-x="true" class="scroll-view-h" scroll-with-animation :scroll-left="slider.scrollLeft">
<view class="_scroll-content">
<view class="_tab-item-box" :class="[defaultConfig.itemWidth ? '_clamp' : '_flex']">
<block v-for="(item, index) in tabList" :key="index" >
<view
class="_item"
:id="'_tab_'+index"
:class="{ '_active': tagIndex === index }"
:style="{color: tagIndex == index ? defaultConfig.activeColor : defaultConfig.color, 'width': defaultConfig.itemWidth ? defaultConfig.itemWidth + 'rpx' : ''}"
@click="tabClick(index)">{{ item[defaultConfig.key] || item }}</view>
</block>
</view>
<view class="_underline" :style="{
transform: 'translateX(' + slider.left + 'px)',
width: slider.width + 'px',
height: defaultConfig.underLineHeight + 'rpx',
backgroundColor: defaultConfig.underLineColor,
}" />
</view>
</scroll-view>
</view>
</template>
<script>
export default {
name: 'liuyuno-tabs',
props: {
list: {
type: Array,
default: () => ['全部', '测试', '测试宽度', '测试宽度三号', '测试宽度四号小星星', '测试宽度五号']
},
// 选中索引
activeIndex: {
type: Number,
default: 0
},
config: {
type: Object,
default:() => {
return {
color: '#999999',//默认时字体颜色
activeColor: '#000000',//选中时字体颜色
underLineColor: '#000000',//下滑线颜色
}
}
},
},
data() {
return {
tabList: [],
tagIndex: 0,
slider: {
left: 0,
width: 0,
scrollLeft: 0
},
scorll: {},
defaultConfig: {
// 要显示的key
key: 'name',
// 字体大小 rpx
fontSize: 26,
// 字体颜色
color: '#313131',
// 激活字体颜色
activeColor: '#e54d42',
// item宽度 0为自动
itemWidth: 0,
// 下划线左右边距,文字宽度加边距 rpx
underLinePadding: 10,
// 下划线宽度 rpx 注意:设置了此值 underLinePadding 失效
underLineWidth: 0,
// 下划线高度 rpx
underLineHeight: 4,
// 下划线颜色
underLineColor: '#e54d42',
},
};
},
watch: {
list(value) {
this.updateData();
setTimeout(() => {
this.updateTabWidth();
}, 0);
},
config(value) {
this.updateConfig();
},
activeIndex(value) {
this.tagIndex = this.activeIndex;
this.tabToIndex(this.tagIndex);
}
},
mounted() {
this.updateConfig();
this.tagIndex = this.activeIndex;
this.updateData();
this.$nextTick(() => {
this.calcScrollPosition();
})
},
methods: {
updateData() {
let data = [];
if (typeof(this.list[0])=='string') {
this.list.forEach((item, index) => {
data.push({
name: item,
})
});
this.defaultConfig.key = 'name';
} else {
data = JSON.parse(JSON.stringify(this.list));
}
this.tabList = data;
},
updateConfig() {
this.defaultConfig = Object.assign(this.defaultConfig, this.config);
},
calcScrollPosition() {
const query = uni.createSelectorQuery().in(this);
query.select('#_scroll').boundingClientRect((res) => {
this.scorll = res;
this.updateTabWidth();
}).exec();
},
updateTabWidth(index = 0) {
let data = this.tabList;
if (data.length == 0) return false;
const query = uni.createSelectorQuery().in(this);
query.select('#_tab_' + index).boundingClientRect((res) => {
data[index]._slider = {
width: res.width,
left: res.left,
scrollLeft: res.left - (data[index - 1] ? data[index - 1]._slider.width : 0),
};
if (this.tagIndex == index) {
this.tabToIndex(this.tagIndex);
}
index++;
if (data.length > index) {
this.updateTabWidth(index);
}
}).exec();
},
tabToIndex(index) {
let _slider = this.tabList[index]._slider;
let width = uni.upx2px(this.defaultConfig.underLineWidth);
if (!width) {
if (this.defaultConfig.itemWidth) {
width = uni.upx2px(this.defaultConfig.itemWidth);
} else {
width = this.tabList[index][this.defaultConfig.key].length * uni.upx2px(this.defaultConfig.fontSize);
}
width += uni.upx2px(this.defaultConfig.underLinePadding) * 2;
}
let scorll_left = this.scorll.left || 0;
this.slider = {
left: _slider.left - scorll_left + (_slider.width - width) / 2,
width: width,
scrollLeft: _slider.scrollLeft - scorll_left,
}
},
tabClick(index) {
this.tagIndex = index;
this.tabToIndex(index);
this.$emit('changeEv', index);
}
}
}
</script>
<style lang="scss" scoped>
._tab-box {
width: 100%;
display: flex;
font-size: 26rpx;
position: relative;
height: 90rpx;
line-height: 90rpx;
z-index: 10;
.scroll-view-h{
white-space:nowrap;
width: 100%;
height: 100%;
box-sizing: border-box;
._scroll-content {
width: 100%;
height: 100%;
position:relative;
._tab-item-box {
height: 100%;
&._flex {
display: flex;
._item {
flex: 1;
}
}
&._clamp {
._item {
overflow:hidden;
text-overflow:ellipsis;
white-space:nowrap;
}
}
._item {
height: 100%;
display: inline-block;
text-align: center;
padding: 0 30rpx;
position: relative;
text-align: center;
color: #333;
&._active {
color: #e54d42;
}
}
}
._underline {
height: 4rpx;
background-color: #e54d42;
border-radius: 6rpx;
transition: .5s;
position: absolute;
bottom: 0;
}
}
}
}
.uni-scroll-view::-webkit-scrollbar {
// 隐藏滚动条,但依旧具备可以滚动的功能
display: none
}
</style>