6 changed files with 244 additions and 81 deletions
@ -0,0 +1,137 @@
@@ -0,0 +1,137 @@
|
||||
<template> |
||||
<div class="indicator-ctn" :class="fixed?'fixed':''"> |
||||
<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> |
||||
<div class="indicator" |
||||
ref="indicator" |
||||
:style="{width : tabStyleWidth}" |
||||
></div> |
||||
</div> |
||||
</template> |
||||
<script> |
||||
import bus from "../utils/bus"; |
||||
|
||||
export default { |
||||
name: "Indicator", |
||||
props: { |
||||
fixed: { |
||||
type: Boolean, |
||||
default: () => false |
||||
}, |
||||
activeIndex: { |
||||
type: Number, |
||||
default: () => 0 |
||||
}, |
||||
tabStyleWidth: { |
||||
type: String, |
||||
default: () => '50%' |
||||
}, |
||||
tabTexts: { |
||||
type: Array, |
||||
default: () => [] |
||||
}, |
||||
}, |
||||
data() { |
||||
return { |
||||
indicatorFixed: false, |
||||
currentSlideItemIndex: this.activeIndex, |
||||
tabIndicatorRelationActiveIndexLefts: [],//指标和slideItem的index的对应left, |
||||
indicatorSpace: 0,//indicator之间的间距 |
||||
} |
||||
}, |
||||
computed: {}, |
||||
mounted() { |
||||
this.initTabs() |
||||
bus.on('move', this.move) |
||||
bus.on('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="scss"> |
||||
@import "../assets/scss/index"; |
||||
|
||||
.indicator-ctn { |
||||
width: 100%; |
||||
top: 0; |
||||
left: 0; |
||||
right: 0; |
||||
z-index: 999; |
||||
background: $main-bg; |
||||
|
||||
.tabs { |
||||
display: flex; |
||||
justify-content: space-between; |
||||
font-weight: bold; |
||||
|
||||
.tab { |
||||
height: 40px; |
||||
width: 45%; |
||||
display: flex; |
||||
justify-content: center; |
||||
align-items: center; |
||||
color: gray; |
||||
transition: color .3s; |
||||
|
||||
&.active { |
||||
color: white; |
||||
} |
||||
} |
||||
} |
||||
|
||||
.indicator { |
||||
height: 2px; |
||||
background: gold; |
||||
width: 45%; |
||||
position: relative; |
||||
transition: all .3s; |
||||
} |
||||
} |
||||
|
||||
.indicator-ctn.fixed { |
||||
position: fixed; |
||||
} |
||||
|
||||
</style> |
@ -0,0 +1,18 @@
@@ -0,0 +1,18 @@
|
||||
export default { |
||||
eventMap: new Map(), |
||||
on(eventType, cb) { |
||||
let cbs = this.eventMap.get(eventType) |
||||
if (cbs) { |
||||
cbs.push(cb) |
||||
} else { |
||||
cbs = [cb] |
||||
} |
||||
this.eventMap.set(eventType, cbs) |
||||
}, |
||||
emit(eventType, val) { |
||||
let cbs = this.eventMap.get(eventType) |
||||
if (cbs) { |
||||
cbs.map(cb => cb(val)) |
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue