9 changed files with 581 additions and 266 deletions
@ -0,0 +1,152 @@
@@ -0,0 +1,152 @@
|
||||
<template> |
||||
<div class="indicator-home"> |
||||
<div class="notice"><span>下拉刷新内容</span></div> |
||||
<div class="toolbar" ref="toolbar"> |
||||
<div class="left" @click="$nav('/home/live')">直播</div> |
||||
<div class="tab-ctn"> |
||||
<div class="tabs" ref="tabs"> |
||||
<div class="tab" |
||||
@click="changeIndex(false,0)"> |
||||
<span>同城</span> |
||||
</div> |
||||
<div class="tab" |
||||
|
||||
@click="changeIndex(false,0)"> |
||||
<span>关注</span> |
||||
</div> |
||||
<div class="tab" |
||||
@click="changeIndex(false,1)"><span>推荐</span> |
||||
</div> |
||||
</div> |
||||
<div class="indicator" ref="indicator"></div> |
||||
</div> |
||||
<img src="../../assets/img/icon/search-gray.png" alt="" |
||||
@click="$nav('/home/search')" |
||||
style="margin-top: .5rem;"> |
||||
</div> |
||||
<Loading class="loading" style="width: 4rem;" :is-full-screen="false"/> |
||||
</div> |
||||
</template> |
||||
<script> |
||||
import Loading from "../../components/Loading"; |
||||
|
||||
export default { |
||||
name: "IndicatorHome", |
||||
components: { |
||||
Loading, |
||||
}, |
||||
props: { |
||||
modelValue: false |
||||
}, |
||||
data() { |
||||
return { |
||||
tabWidth: 0, |
||||
indicatorRef: null, |
||||
indicatorRelateIndexLefts: [], |
||||
indicatorSpace: 0 |
||||
} |
||||
}, |
||||
computed: {}, |
||||
watch: {}, |
||||
created() { |
||||
}, |
||||
mounted() { |
||||
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') |
||||
//TODO 这里算得不对,两个字时正常,字一多就会出问题,修改参考IndicatorLight.vue |
||||
this.indicatorRelateIndexLefts.push( |
||||
item.getBoundingClientRect().x - tabs.children[0].getBoundingClientRect().x + this.tabWidth * 0.15) |
||||
} |
||||
this.indicatorSpace = this.indicatorRelateIndexLefts[1] - this.indicatorRelateIndexLefts[0] |
||||
this.$setCss(this.indicatorRef, 'transition-duration', `300ms`) |
||||
this.$setCss(this.indicatorRef, 'left', this.indicatorRelateIndexLefts[0] + 'px') |
||||
|
||||
}, |
||||
methods: { |
||||
changeIndex() { |
||||
|
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style scoped lang="less"> |
||||
@import "@/assets/less/index"; |
||||
|
||||
.indicator-home { |
||||
position: fixed; |
||||
font-size: 1.6rem; |
||||
top: 0; |
||||
left: 0; |
||||
height: 60px; |
||||
z-index: 2; |
||||
width: 100%; |
||||
color: white; |
||||
|
||||
.notice { |
||||
opacity: 0; |
||||
top: 0; |
||||
position: absolute; |
||||
width: 100vw; |
||||
height: 100%; |
||||
display: flex; |
||||
justify-content: center; |
||||
align-items: center; |
||||
} |
||||
|
||||
.loading { |
||||
opacity: 0; |
||||
top: 1.3rem; |
||||
right: 1.5rem; |
||||
position: absolute; |
||||
} |
||||
|
||||
.toolbar { |
||||
z-index: 2; |
||||
position: relative; |
||||
color: white; |
||||
width: 100%; |
||||
height: 100%; |
||||
box-sizing: border-box; |
||||
padding: 0 1.5rem; |
||||
display: flex; |
||||
justify-content: space-between; |
||||
align-items: center; |
||||
|
||||
.tab-ctn { |
||||
width: 45%; |
||||
position: relative; |
||||
|
||||
.tabs { |
||||
display: flex; |
||||
justify-content: space-between; |
||||
font-weight: bold; |
||||
|
||||
.tab { |
||||
transition: color .3s; |
||||
color: gray; |
||||
|
||||
&.active { |
||||
color: white; |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
.indicator { |
||||
//transition: left .3s; |
||||
position: absolute; |
||||
bottom: -0.8rem; |
||||
height: .3rem; |
||||
width: 2rem; |
||||
background: #fff; |
||||
border-radius: .5rem; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
</style> |
@ -0,0 +1,403 @@
@@ -0,0 +1,403 @@
|
||||
<template> |
||||
<div id="Slide" @click="checkDbClick"> |
||||
<slide-horizontal> |
||||
<div class="item"> |
||||
<IndicatorHome/> |
||||
<slide-horizontal |
||||
style="height: calc(100% - 5rem);" |
||||
> |
||||
<div class="item"> |
||||
<div class="nav-one" :class="{close:closeOne}"> |
||||
<div class="nav-item"> |
||||
<img src="../../assets/img/icon/msg-icon9.webp" alt=""> |
||||
<span>美食</span> |
||||
</div> |
||||
<div class="nav-item"> |
||||
<img src="../../assets/img/icon/msg-icon9.webp" alt=""> |
||||
<span>休闲娱乐</span> |
||||
</div> |
||||
<div class="nav-item"> |
||||
<img src="../../assets/img/icon/msg-icon9.webp" alt=""> |
||||
<span>游玩</span> |
||||
</div> |
||||
<div class="nav-item"> |
||||
<img src="../../assets/img/icon/msg-icon9.webp" alt=""> |
||||
<span>丽人/美发</span> |
||||
</div> |
||||
<div class="nav-item"> |
||||
<img src="../../assets/img/icon/msg-icon9.webp" alt=""> |
||||
<span>住宿</span> |
||||
</div> |
||||
</div> |
||||
<SlideVertical> |
||||
<div class="item" style="background: tan"> |
||||
<p style="padding: 1rem;" v-for="i in 50"> |
||||
r2222222222222222222222222222222222222222222222222222222 |
||||
</p> |
||||
</div> |
||||
<div class="item">r333333333333333333333333333333333333333333333333333333</div> |
||||
</SlideVertical> |
||||
</div> |
||||
<div class="item"> |
||||
<div class="nav-two" :class="{close:closeOne}"> |
||||
<div class="title"> |
||||
<span>正在直播</span> |
||||
<div class="right"> |
||||
<div>全部关注</div> |
||||
<back mode="gray" direction="right"/> |
||||
</div> |
||||
</div> |
||||
<div class="users"> |
||||
<div class="user" v-for="item in friends.all"> |
||||
<img :style="item.select?'opacity: .5;':''" class="avatar" :src="$imgPreview(item.avatar)" alt=""> |
||||
<span>{{ item.name }}</span> |
||||
<div class="tag">直播中</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
<SlideVertical> |
||||
<div class="item">r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1</div> |
||||
<div class="item">r2222222222222222222222222222222222222222222222222222222</div> |
||||
<div class="item">r333333333333333333333333333333333333333333333333333333</div> |
||||
</SlideVertical> |
||||
</div> |
||||
<div class="item"> |
||||
<SlideVertical> |
||||
<div class="item">r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1</div> |
||||
<div class="item">r2222222222222222222222222222222222222222222222222222222</div> |
||||
<div class="item">r333333333333333333333333333333333333333333333333333333</div> |
||||
</SlideVertical> |
||||
</div> |
||||
</slide-horizontal> |
||||
<Footer v-bind:init-tab="1"/> |
||||
</div> |
||||
<div class="item"> |
||||
<p v-for="i in 100">2</p> |
||||
</div> |
||||
</slide-horizontal> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import SlideHorizontal from './slide-horizontal' |
||||
import SlideVertical from './slide-vertical' |
||||
import BVideo from "../../components/BVideo"; |
||||
import resource from "../../assets/data/resource"; |
||||
import Dom from "../../utils/dom"; |
||||
import Footer from "../../components/Footer"; |
||||
import Loading from "../../components/Loading"; |
||||
import {mapState} from "vuex"; |
||||
import IndicatorHome from "./IndicatorHome"; |
||||
|
||||
export default { |
||||
name: "slide", |
||||
components: { |
||||
SlideHorizontal, |
||||
SlideVertical, |
||||
BVideo, |
||||
Footer, |
||||
IndicatorHome |
||||
}, |
||||
data() { |
||||
return { |
||||
closeOne: true, |
||||
videos: [], |
||||
totalSize: 52, |
||||
pageSize: 10, |
||||
pageNo: 0, |
||||
lastClickTime: -1, |
||||
clickTimer: null, |
||||
dbClickTimer: null, |
||||
isDbClick: false, |
||||
} |
||||
}, |
||||
computed: { |
||||
...mapState(['friends']), |
||||
}, |
||||
created() { |
||||
this.getData() |
||||
}, |
||||
mounted() { |
||||
}, |
||||
methods: { |
||||
changeIndex() { |
||||
this.closeOne = !this.closeOne |
||||
}, |
||||
dbClick(e) { |
||||
console.log('dbclick') |
||||
let id = 'a' + Date.now() |
||||
let elWidth = 80 |
||||
let rotate = this.randomNum(0, 1) |
||||
let template = `<img class="${rotate ? 'left love-dbclick' : 'right love-dbclick'}" id="${id}" src="${new URL('../../assets/img/icon/loved.svg', import.meta.url).href}">` |
||||
let el = new Dom().create(template) |
||||
el.css({top: e.y - elWidth, left: e.x - elWidth / 2,}) |
||||
new Dom('#Slide').append(el) |
||||
setTimeout(() => { |
||||
new Dom(`#${id}`).remove() |
||||
}, 1000) |
||||
}, |
||||
randomNum(minNum, maxNum) { |
||||
switch (arguments.length) { |
||||
case 1: |
||||
return parseInt(Math.random() * minNum + 1, 10); |
||||
case 2: |
||||
return parseInt(Math.random() * (maxNum - minNum + 1) + minNum, 10); |
||||
default: |
||||
return 0; |
||||
} |
||||
}, |
||||
checkDbClick(e) { |
||||
let checkTime = 400 |
||||
if (this.isDbClick) { |
||||
this.dbClick(e) |
||||
// console.log('checkDbClick-dbclick1') |
||||
clearTimeout(this.dbClickTimer); |
||||
this.dbClickTimer = setTimeout(() => { |
||||
this.isDbClick = false |
||||
}, 400); |
||||
return |
||||
} |
||||
let nowTime = new Date().getTime(); |
||||
if (nowTime - this.lastClickTime < checkTime) { |
||||
this.dbClick(e) |
||||
// console.log('checkDbClick-dbclick2') |
||||
|
||||
this.lastClickTime = 0; |
||||
this.clickTimer && clearTimeout(this.clickTimer); |
||||
this.isDbClick = true |
||||
this.dbClickTimer = setTimeout(() => { |
||||
this.isDbClick = false |
||||
}, checkTime); |
||||
} else { |
||||
this.lastClickTime = nowTime; |
||||
this.clickTimer = setTimeout(() => { |
||||
console.log('单击') |
||||
// this.togglePlayVideo() |
||||
}, checkTime); |
||||
} |
||||
}, |
||||
async getData() { |
||||
if (process.env.NODE_ENV !== 'development') { |
||||
this.totalSize = 11 |
||||
// return this.videos = this.$clone(this.localVideos) |
||||
// await this.$sleep(200) |
||||
// return this.videos = this.$clone(this.webVideos) |
||||
return this.videos = this.$clone(resource.videos) |
||||
} |
||||
this.loading = true |
||||
let res = await this.$api.videos.recommended({pageNo: this.pageNo, pageSize: this.pageSize}) |
||||
console.log(res) |
||||
this.loading = false |
||||
if (res.code === this.SUCCESS) { |
||||
this.totalSize = res.data.total |
||||
this.videos = this.videos.concat(res.data.list) |
||||
// this.videos = this.$clone(this.localVideos) |
||||
} else { |
||||
this.pageNo-- |
||||
} |
||||
}, |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style lang="less"> |
||||
#Slide { |
||||
height: 100vh; |
||||
width: 100vw; |
||||
color: white; |
||||
} |
||||
|
||||
.slide { |
||||
height: 100%; |
||||
width: 100%; |
||||
overflow: hidden; |
||||
|
||||
.slide-wrapper { |
||||
height: 100%; |
||||
width: 100%; |
||||
display: flex; |
||||
|
||||
//transform: translateX(1rem); |
||||
|
||||
} |
||||
|
||||
.item { |
||||
width: 100%; |
||||
min-width: 100%; |
||||
height: 100%; |
||||
min-height: 100%; |
||||
overflow: hidden; |
||||
} |
||||
} |
||||
|
||||
.love-dbclick { |
||||
position: absolute; |
||||
@width: 8rem; |
||||
width: @width; |
||||
height: @width; |
||||
|
||||
&.left { |
||||
animation: loveLeft 1.1s linear; |
||||
} |
||||
|
||||
&.right { |
||||
animation: loveRight 1.1s linear; |
||||
} |
||||
|
||||
@scale: scale(1.2); |
||||
@rotate: 10deg; |
||||
|
||||
@keyframes loveLeft { |
||||
0% { |
||||
opacity: 0; |
||||
transform: scale(2) rotate(0-@rotate); |
||||
} |
||||
10% { |
||||
opacity: 1; |
||||
transform: scale(1) rotate(0-@rotate); |
||||
} |
||||
15% { |
||||
opacity: 1; |
||||
transform: @scale rotate(0-@rotate); |
||||
} |
||||
40% { |
||||
opacity: 1; |
||||
transform: @scale rotate(0-@rotate); |
||||
} |
||||
100% { |
||||
transform: translateY(-12rem) scale(2) rotate(0-@rotate); |
||||
opacity: 0; |
||||
} |
||||
} |
||||
@keyframes loveRight { |
||||
0% { |
||||
opacity: 0; |
||||
transform: scale(2) rotate(0+@rotate); |
||||
} |
||||
10% { |
||||
opacity: 1; |
||||
transform: scale(1) rotate(0+@rotate); |
||||
} |
||||
15% { |
||||
opacity: 1; |
||||
transform: @scale rotate(0+@rotate); |
||||
} |
||||
40% { |
||||
opacity: 1; |
||||
transform: @scale rotate(0+@rotate); |
||||
} |
||||
100% { |
||||
transform: translateY(-12rem) scale(2) rotate(0+@rotate); |
||||
opacity: 0; |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
.nav-one { |
||||
height: 14rem; |
||||
box-sizing: border-box; |
||||
background: linear-gradient(to right, rgb(36, 34, 84), rgb(7, 5, 16)); |
||||
transition: all .3s; |
||||
padding: 2rem; |
||||
display: flex; |
||||
align-items: flex-end; |
||||
justify-content: space-between; |
||||
|
||||
.nav-item { |
||||
@width: 3.5rem; |
||||
display: flex; |
||||
align-items: center; |
||||
flex-direction: column; |
||||
|
||||
img { |
||||
width: @width; |
||||
height: @width; |
||||
margin-bottom: .5rem; |
||||
} |
||||
} |
||||
|
||||
&.close { |
||||
margin-top: -14rem; |
||||
} |
||||
} |
||||
|
||||
@space-width: 1.5rem; |
||||
@icon-width: 5.2rem; |
||||
|
||||
.nav-two { |
||||
height: 18rem; |
||||
display: flex; |
||||
flex-direction: column; |
||||
justify-content: flex-end; |
||||
box-sizing: border-box; |
||||
padding: @space-width; |
||||
transition: .3s; |
||||
|
||||
.title { |
||||
width: 100%; |
||||
display: flex; |
||||
justify-content: space-between; |
||||
box-sizing: border-box; |
||||
margin-bottom: 1.5rem; |
||||
|
||||
.right { |
||||
color: gray; |
||||
display: flex; |
||||
align-items: center; |
||||
} |
||||
|
||||
img { |
||||
width: 1rem; |
||||
height: 1rem; |
||||
margin-left: .4rem; |
||||
} |
||||
} |
||||
|
||||
.users { |
||||
display: flex; |
||||
width: 100%; |
||||
overflow: hidden; |
||||
|
||||
.user { |
||||
width: @icon-width; |
||||
position: relative; |
||||
margin-right: @space-width; |
||||
font-size: 1rem; |
||||
display: flex; |
||||
flex-direction: column; |
||||
align-items: center; |
||||
|
||||
.avatar { |
||||
width: @icon-width; |
||||
height: @icon-width; |
||||
border-radius: 50%; |
||||
} |
||||
|
||||
span { |
||||
margin-top: .8rem; |
||||
text-align: center; |
||||
width: @icon-width; |
||||
white-space: nowrap; |
||||
overflow: hidden; |
||||
text-overflow: ellipsis; |
||||
} |
||||
|
||||
.tag { |
||||
background: rgb(239, 46, 137); |
||||
border-radius: .2rem; |
||||
padding: 0 .2rem; |
||||
bottom: 1.8rem; |
||||
position: absolute; |
||||
font-size: 1rem; |
||||
} |
||||
} |
||||
} |
||||
|
||||
&.close { |
||||
margin-top: -18rem; |
||||
} |
||||
} |
||||
|
||||
|
||||
</style> |
@ -1,121 +0,0 @@
@@ -1,121 +0,0 @@
|
||||
<template> |
||||
<div class="Slide" @click.capture="c"> |
||||
<slide-horizontal> |
||||
<div class="item"> |
||||
<slide-horizontal> |
||||
<div class="item"> |
||||
<SlideVertical> |
||||
<div class="item" v-for="i in videos"> |
||||
<BVideo :video="i"></BVideo> |
||||
</div> |
||||
<div class="item">r2222222222222222222222222222222222222222222222222222222</div> |
||||
<div class="item">r333333333333333333333333333333333333333333333333333333</div> |
||||
</SlideVertical> |
||||
</div> |
||||
<div class="item"> |
||||
<SlideVertical> |
||||
<div class="item">r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1</div> |
||||
<div class="item">r2222222222222222222222222222222222222222222222222222222</div> |
||||
<div class="item">r333333333333333333333333333333333333333333333333333333</div> |
||||
</SlideVertical> |
||||
</div> |
||||
<div class="item"> |
||||
<SlideVertical> |
||||
<div class="item">r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1</div> |
||||
<div class="item">r2222222222222222222222222222222222222222222222222222222</div> |
||||
<div class="item">r333333333333333333333333333333333333333333333333333333</div> |
||||
</SlideVertical> |
||||
</div> |
||||
</slide-horizontal> |
||||
</div> |
||||
<div class="item"> |
||||
<p v-for="i in 100">2</p> |
||||
</div> |
||||
</slide-horizontal> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import SlideHorizontal from './slide-horizontal' |
||||
import SlideVertical from './slide-vertical' |
||||
import BVideo from "../../components/BVideo"; |
||||
import resource from "../../assets/data/resource"; |
||||
|
||||
export default { |
||||
name: "slide", |
||||
components: { |
||||
SlideHorizontal, |
||||
SlideVertical, |
||||
BVideo |
||||
}, |
||||
data() { |
||||
return { |
||||
videos: [], |
||||
totalSize: 52, |
||||
pageSize: 10, |
||||
pageNo: 0, |
||||
} |
||||
}, |
||||
created() { |
||||
this.getData() |
||||
}, |
||||
mounted() { |
||||
}, |
||||
methods: { |
||||
c() { |
||||
console.log('console.log()') |
||||
return true |
||||
}, |
||||
async getData() { |
||||
if (process.env.NODE_ENV !== 'development') { |
||||
this.totalSize = 11 |
||||
// return this.videos = this.$clone(this.localVideos) |
||||
// await this.$sleep(200) |
||||
// return this.videos = this.$clone(this.webVideos) |
||||
return this.videos = this.$clone(resource.videos) |
||||
} |
||||
this.loading = true |
||||
let res = await this.$api.videos.recommended({pageNo: this.pageNo, pageSize: this.pageSize}) |
||||
console.log(res) |
||||
this.loading = false |
||||
if (res.code === this.SUCCESS) { |
||||
this.totalSize = res.data.total |
||||
this.videos = this.videos.concat(res.data.list) |
||||
// this.videos = this.$clone(this.localVideos) |
||||
} else { |
||||
this.pageNo-- |
||||
} |
||||
}, |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style lang="less"> |
||||
.Slide { |
||||
height: 90vh; |
||||
width: 100vw; |
||||
color: white; |
||||
} |
||||
|
||||
.slide-column, .slide-row { |
||||
height: 100%; |
||||
width: 100%; |
||||
overflow: hidden; |
||||
|
||||
.column-wrapper { |
||||
height: 100%; |
||||
width: 100%; |
||||
display: flex; |
||||
|
||||
//transform: translateX(1rem); |
||||
|
||||
} |
||||
|
||||
.item { |
||||
width: 100%; |
||||
min-width: 100%; |
||||
height: 100%; |
||||
min-height: 100%; |
||||
} |
||||
} |
||||
</style> |
Loading…
Reference in new issue