You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
359 lines
9.0 KiB
359 lines
9.0 KiB
<template> |
|
<div class="indicator-home" :class="{isLight}"> |
|
<transition name="fade"> |
|
<div class="mask" v-if="open" @click="open = false"></div> |
|
</transition> |
|
<div class="notice" :style="noticeStyle"><span>下拉刷新内容</span></div> |
|
<div class="toolbar" ref="toolbar" :style="toolbarStyle"> |
|
<Icon |
|
icon="tabler:menu-deep" |
|
class="search" |
|
@click="$emit('showSlidebar')" |
|
style="transform: rotateY(180deg)"/> |
|
<div class="tab-ctn"> |
|
<div class="tabs" ref="tabs"> |
|
<div class="tab" :class="tabOneClass" @click.stop="change(0)"> |
|
<span>热点</span> |
|
<img v-show="index === 0" src="../../../assets/img/icon/arrow-up-white.png" class="tab1-img"> |
|
</div> |
|
<div class="tab" :class="{active:index === 1}" @click.stop="change(1)"> |
|
<span>社区</span> |
|
</div> |
|
<div class="tab" :class="{active:index === 2}" @click.stop="change(2)"> |
|
<span>关注</span> |
|
<img src="../../../assets/img/icon/live.webp" class="tab2-img"> |
|
</div> |
|
<div class="tab" :class="{active:index === 3}" @click.stop="change(3)"><span>长视频</span> |
|
</div> |
|
<div class="tab" :class="{active:index === 4}" @click.stop="change(4)"><span>推荐</span> |
|
</div> |
|
</div> |
|
<div class="indicator" ref="indicator"></div> |
|
</div> |
|
<Icon v-hide="loading" |
|
icon="ion:search" |
|
class="search" |
|
@click="$nav('/home/search')"/> |
|
</div> |
|
<div class="toggle-type" :class="{open}"> |
|
<div class="l-button" :class="{active:type === 0}" @click="toggleType(0)"> |
|
<span>同城</span> |
|
<img v-if="type === 0" src="../../../assets/img/icon/switch.png" alt=""> |
|
</div> |
|
<div class="l-button" :class="{active:type === 1}" @click="toggleType(1)">学习</div> |
|
<div class="l-button" :class="{active:type === 2}" @click="toggleType(2)">热点</div> |
|
</div> |
|
|
|
<Loading :style="loadingStyle" class="loading" style="width: 40rem;" :is-full-screen="false"/> |
|
</div> |
|
</template> |
|
<script> |
|
import Loading from "../../../components/Loading.vue"; |
|
import bus from "../../../utils/bus"; |
|
import {mapState} from "vuex"; |
|
|
|
export default { |
|
name: "IndicatorHome", |
|
components: { |
|
Loading, |
|
}, |
|
props: { |
|
loading: false, |
|
//用于和slidList绑定,因为一个页面可能有多个slidList,但只有一个indicator组件 |
|
name: { |
|
type: String, |
|
default: () => '' |
|
}, |
|
index: { |
|
type: Number, |
|
default: () => 0 |
|
}, |
|
isLight: { |
|
type: Boolean, |
|
default: () => false |
|
} |
|
}, |
|
data() { |
|
return { |
|
indicatorRef: null, |
|
lefts: [], |
|
indicatorSpace: 0, |
|
open: false, |
|
type: 1, |
|
moveY: 0 |
|
} |
|
}, |
|
computed: { |
|
...mapState(['judgeValue', 'homeRefresh']), |
|
tabOneClass() { |
|
return {active: this.index === 0, open: this.open} |
|
}, |
|
transform() { |
|
return `translate3d(0, ${this.moveY - this.judgeValue > this.homeRefresh ? this.homeRefresh : this.moveY - this.judgeValue}px, 0)` |
|
}, |
|
toolbarStyle() { |
|
if (this.loading) { |
|
return {opacity: 1, 'transition-duration': '300ms', transform: `translate3d(0, 0, 0)`,} |
|
} |
|
if (this.moveY) { |
|
return { |
|
opacity: 1 - (this.moveY - this.judgeValue) / (this.homeRefresh / 2), |
|
transform: this.transform |
|
} |
|
} |
|
return {opacity: 1, 'transition-duration': '300ms', transform: `translate3d(0, 0, 0)`,} |
|
}, |
|
noticeStyle() { |
|
if (this.loading) { |
|
return {opacity: 0,} |
|
} |
|
if (this.moveY) { |
|
return { |
|
opacity: (this.moveY - this.judgeValue) / (this.homeRefresh / 2) - .5, |
|
transform: this.transform |
|
} |
|
} |
|
return {opacity: 0,} |
|
}, |
|
loadingStyle() { |
|
if (this.loading) { |
|
return {opacity: 1, 'transition-duration': '300ms',} |
|
} |
|
if (this.moveY) { |
|
return { |
|
opacity: (this.moveY - this.judgeValue) / (this.homeRefresh / 2) - .5, |
|
transform: this.transform |
|
} |
|
} |
|
} |
|
}, |
|
created() { |
|
}, |
|
mounted() { |
|
this.initTabs() |
|
bus.on(this.name + '-moveX', this.move) |
|
bus.on(this.name + '-moveY', e => { |
|
this.moveY = e |
|
}) |
|
bus.on(this.name + '-end', this.end) |
|
}, |
|
unmounted() { |
|
bus.off(this.name + '-moveX', this.move) |
|
bus.off(this.name + '-moveY',) |
|
bus.off(this.name + '-end', this.end) |
|
}, |
|
methods: { |
|
toggleType(type) { |
|
if (type !== this.type) { |
|
this.type = type |
|
this.open = false |
|
} |
|
}, |
|
change(index) { |
|
if (this.index === 0 && index === 0) { |
|
this.open = !this.open |
|
} else { |
|
this.open = false |
|
} |
|
this.$emit('update:index', index) |
|
this.$setCss(this.indicatorRef, 'transition-duration', `300ms`) |
|
this.$setCss(this.indicatorRef, 'left', this.lefts[index] + 'px') |
|
}, |
|
initTabs() { |
|
let tabs = this.$refs.tabs |
|
this.indicatorRef = this.$refs.indicator |
|
let indicatorWidth = this.$getCss(this.indicatorRef, 'width') |
|
for (let i = 0; i < tabs.children.length; i++) { |
|
let item = tabs.children[i] |
|
let tabWidth = this.$getCss(item, 'width') |
|
this.lefts.push( |
|
item.getBoundingClientRect().x - tabs.children[0].getBoundingClientRect().x + (tabWidth * 0.5 - indicatorWidth / 2)) |
|
} |
|
this.indicatorSpace = this.lefts[1] - this.lefts[0] |
|
this.$setCss(this.indicatorRef, 'transition-duration', `300ms`) |
|
this.$setCss(this.indicatorRef, 'left', this.lefts[this.index] + 'px') |
|
}, |
|
move(e) { |
|
this.$setCss(this.indicatorRef, 'transition-duration', `0ms`) |
|
this.$setCss(this.indicatorRef, 'left', |
|
this.lefts[this.index] - |
|
e / (this.$store.state.bodyWidth / this.indicatorSpace) + 'px') |
|
}, |
|
end(index) { |
|
this.moveY = 0 |
|
this.$setCss(this.indicatorRef, 'transition-duration', `300ms`) |
|
this.$setCss(this.indicatorRef, 'left', this.lefts[index] + 'px') |
|
setTimeout(() => { |
|
this.$setCss(this.indicatorRef, 'transition-duration', `0ms`) |
|
}, 300) |
|
} |
|
}, |
|
} |
|
</script> |
|
|
|
<style scoped lang="less"> |
|
@import "@/assets/less/index"; |
|
|
|
.indicator-home { |
|
position: absolute; |
|
font-size: 16rem; |
|
top: 0; |
|
left: 0; |
|
z-index: 2; |
|
width: 100%; |
|
color: white; |
|
height: @header-height; |
|
transition: all .3s; |
|
font-weight: bold; |
|
|
|
.notice { |
|
opacity: 0; |
|
top: 0; |
|
position: absolute; |
|
width: 100vw; |
|
height: 100%; |
|
display: flex; |
|
justify-content: center; |
|
align-items: center; |
|
} |
|
|
|
.loading { |
|
opacity: 0; |
|
top: 7rem; |
|
right: 7rem; |
|
position: absolute; |
|
} |
|
|
|
.toolbar { |
|
z-index: 2; |
|
position: relative; |
|
color: white; |
|
width: 100%; |
|
height: 100%; |
|
box-sizing: border-box; |
|
padding: 0 15rem; |
|
display: flex; |
|
justify-content: space-between; |
|
align-items: center; |
|
|
|
.tab-ctn { |
|
width: 80%; |
|
position: relative; |
|
|
|
.tabs { |
|
display: flex; |
|
justify-content: space-between; |
|
|
|
.tab { |
|
transition: color .3s; |
|
color: rgb(156, 158, 165); |
|
position: relative; |
|
|
|
.tab1-img { |
|
position: absolute; |
|
@width: 1rem; |
|
width: @width; |
|
height: @width; |
|
margin-left: 4rem; |
|
transition: all .3s; |
|
margin-top: 7rem; |
|
} |
|
|
|
.tab2-img { |
|
position: absolute; |
|
height: 15rem; |
|
left: 24rem; |
|
top: -5rem; |
|
} |
|
|
|
&.open { |
|
.tab1-img { |
|
transform: rotate(180deg); |
|
} |
|
} |
|
|
|
&.active { |
|
color: white; |
|
} |
|
} |
|
} |
|
|
|
.indicator { |
|
//transition: left .3s; |
|
position: absolute; |
|
bottom: -8rem; |
|
height: 2rem; |
|
width: 20rem; |
|
//width: calc(100% / 5); |
|
background: #fff; |
|
border-radius: 5rem; |
|
} |
|
} |
|
|
|
.search { |
|
color: white; |
|
font-size: 24rem; |
|
} |
|
} |
|
|
|
.toggle-type { |
|
@height: 100rem; |
|
position: absolute; |
|
height: @height; |
|
//padding-top: @height; |
|
padding-left: 10rem; |
|
padding-right: 10rem; |
|
padding-bottom: 10rem; |
|
width: 100%; |
|
background: @main-bg; |
|
display: flex; |
|
justify-content: space-between; |
|
align-items: flex-end; |
|
box-sizing: border-box; |
|
font-size: 12rem; |
|
top: -@height; |
|
transition: all .3s; |
|
opacity: 0; |
|
|
|
&.open { |
|
top: 0; |
|
opacity: 1; |
|
} |
|
|
|
.l-button { |
|
flex: 1; |
|
margin: 0 3rem; |
|
height: 28rem; |
|
background: rgb(33, 36, 45); |
|
display: flex; |
|
align-items: center; |
|
justify-content: center; |
|
border-radius: 20rem; |
|
color: rgb(157, 161, 170); |
|
transition: all .3s; |
|
|
|
&.active { |
|
background: rgb(57, 57, 65); |
|
color: white; |
|
} |
|
|
|
img { |
|
@width: 9rem; |
|
width: @width; |
|
height: @width; |
|
margin-left: 8rem; |
|
} |
|
} |
|
|
|
} |
|
|
|
.mask { |
|
top: 0; |
|
position: absolute; |
|
width: 100vw; |
|
height: 100vh; |
|
background: #00000066; |
|
} |
|
} |
|
|
|
</style>
|
|
|