douyin/src/components/slide/Indicator.vue
2024-03-06 02:04:40 +08:00

167 lines
4.7 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<script lang="jsx">
import bus from "../../utils/bus";
export default {
name: "Indicator",
props: {
activeIndex: {
type: Number,
default: () => 0
},
tabStyleWidth: {
type: String,
default: () => ''
},
tabTexts: {
type: Array,
default: () => []
},
tabRender: {
type: Function,
default: null
},
//用于和slidList绑定因为一个页面可能有多个slidList但只有一个indicator组件
name: {
type: String,
default: () => ''
},
},
data() {
return {
currentSlideItemIndex: this.activeIndex,
tabIndicatorRelationActiveIndexLefts: [],//指标和slideItem的index的对应left,
indicatorSpace: 0,//indicator之间的间距
}
},
computed: {},
render() {
/*
* <div class="tabs" ref="tabs">
<div class="tab"
style="{width : tabStyleWidth}"
v-for="(item,index) in tabTexts"
:class="currentSlideItemIndex === index?'active':''"
@click="changeIndex(index)">
<span>{{ item }}</span></div>
</div>
* */
return (
<div className='indicator-ctn'>
{this.tabRender ?
this.tabRender() :
<div className="tabs" ref="tabs">
{
this.tabTexts.map((item, index) => {
return (
<div className={this.currentSlideItemIndex === index ? 'active tab' : 'tab'}
style={{width: this.tabStyleWidth || 100 / this.tabTexts.length + '%'}}
onClick={e => this.changeIndex(index)}
>
< span> {item}</span>
</div>
)
})
}
</div>
}
<div className="indicator" ref="indicator"
style={{width: this.tabStyleWidth || 100 / this.tabTexts.length + '%'}}/>
</div>
)
},
mounted() {
this.initTabs()
bus.on(this.name + '-moved', this.move)
bus.on(this.name + '-end', this.end)
},
methods: {
changeIndex(index) {
this.currentSlideItemIndex = index
this.$attrs['onUpdate:active-index'] && this.$emit('update:active-index', this.currentSlideItemIndex)
this.$setCss(this.indicatorRef, 'transition-duration', `300ms`)
this.$setCss(this.indicatorRef, 'left', this.tabIndicatorRelationActiveIndexLefts[this.currentSlideItemIndex] + 'px')
},
initTabs() {
let tabs = this.$refs.tabs
this.indicatorRef = this.$refs.indicator
for (let i = 0; i < tabs.children.length; i++) {
let item = tabs.children[i]
this.tabWidth = this.$getCss(item, 'width')
this.tabIndicatorRelationActiveIndexLefts.push(
item.getBoundingClientRect().x - tabs.children[0].getBoundingClientRect().x + (this.indicatorType === 'home' ? this.tabWidth * 0.15 : 0))
}
this.indicatorSpace = this.tabIndicatorRelationActiveIndexLefts[1] - this.tabIndicatorRelationActiveIndexLefts[0]
this.$setCss(this.indicatorRef, 'transition-duration', `0ms`)
this.$setCss(this.indicatorRef, 'left', this.tabIndicatorRelationActiveIndexLefts[this.currentSlideItemIndex] + 'px')
},
move(e) {
this.$setCss(this.indicatorRef, 'left',
this.tabIndicatorRelationActiveIndexLefts[this.currentSlideItemIndex] -
e.x.distance / (this.$store.state.bodyWidth / this.indicatorSpace) + 'px')
},
end(index) {
// console.log(index)
this.currentSlideItemIndex = index
this.$setCss(this.indicatorRef, 'transition-duration', `300ms`)
this.$setCss(this.indicatorRef, 'left',
this.tabIndicatorRelationActiveIndexLefts[this.currentSlideItemIndex] + 'px')
setTimeout(() => {
this.$setCss(this.indicatorRef, 'transition-duration', `0ms`)
}, 300)
}
}
}
</script>
<style scoped lang="less">
@import "../../assets/less/index";
.indicator-ctn {
font-size: 14rem;
width: 100%;
height: @indicator-height;
top: 0;
left: 0;
right: 0;
z-index: 1;
background: @main-bg;
.tabs {
display: flex;
justify-content: space-between;
font-weight: bold;
.tab {
height: 40rem;
width: 45%;
display: flex;
justify-content: center;
align-items: center;
color: gray;
transition: color .3s;
font-size: 16rem;
&.active {
color: white;
}
img {
margin-left: 5rem;
@width: 12rem;
width: @width;
height: @width;
}
}
}
.indicator {
height: 2px;
background: gold;
width: 45%;
position: relative;
transition: all .3s;
}
}
</style>