9 changed files with 385 additions and 12 deletions
@ -0,0 +1,370 @@
@@ -0,0 +1,370 @@
|
||||
<template> |
||||
<div class="MyMusic"> |
||||
<Indicator |
||||
name="myMusicList" |
||||
tabStyleWidth="50%" |
||||
:tabTexts="['猜你爱听','我的收藏']" |
||||
v-model:active-index="slideIndex"> |
||||
</Indicator> |
||||
<SlideRowList |
||||
style="height: calc(100vh - 5rem);" |
||||
name="myMusicList" |
||||
v-model:active-index="slideIndex"> |
||||
<SlideItem> |
||||
<div class="music-play"> |
||||
<div class="cover"> |
||||
<img v-lazy="$imgPreview(music.cover)" alt=""> |
||||
</div> |
||||
<div class="lyrics-wrapper"> |
||||
<div class="container"> |
||||
<div class="lyrics">111111111111111</div> |
||||
<div class="lyrics">222222222222222</div> |
||||
<div class="lyrics">333333333333333</div> |
||||
<div class="lyrics">444444444444444</div> |
||||
<div class="lyrics">555555555555555</div> |
||||
</div> |
||||
</div> |
||||
|
||||
<div class="bottom"> |
||||
<div class="desc"> |
||||
<div class="left"> |
||||
<div class="name">{{ music.name }}</div> |
||||
<div class="author">{{ music.author }}</div> |
||||
</div> |
||||
<div class="right"> |
||||
<div class="btn"> |
||||
<img src="../../assets/img/icon/star-white.png" alt=""> |
||||
<span>收藏</span> |
||||
</div> |
||||
<div class="btn"> |
||||
<img src="../../assets/img/icon/share-white-full.png" alt=""> |
||||
<span>分享</span> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
<div class="progress"> |
||||
<div class="start">{{ $durationTime(currentTime) }}</div> |
||||
<div class="bar"> |
||||
<div class="slide-bar" |
||||
ref="slideBar" |
||||
@touchstart="start" |
||||
@touchmove="move" |
||||
@touchend="end"></div> |
||||
<div class="bar-line" :style="durationStyle(1)"></div> |
||||
<div class="bar-point" :style="durationStyle(2)"></div> |
||||
</div> |
||||
<div class="end">{{ $durationTime(duration) }}</div> |
||||
</div> |
||||
<div class="options"> |
||||
<img v-show="isLoop" src="../../assets/img/icon/me/loop.png" @click="isLoop = !isLoop"> |
||||
<img v-show="!isLoop" src="../../assets/img/icon/me/play-normal.png" @click="isLoop = !isLoop"> |
||||
<div class="center"> |
||||
<img src="../../assets/img/icon/me/previous.png"> |
||||
<img v-show="isPlay" class="control" src="../../assets/img/icon/me/pause.png" @click="togglePlay"> |
||||
<img v-show="!isPlay" class="control" src="../../assets/img/icon/me/play.png" @click="togglePlay"> |
||||
<img src="../../assets/img/icon/me/next.png"> |
||||
</div> |
||||
<img src="../../assets/img/icon/me/music-list.png"> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</SlideItem> |
||||
<SlideItem> |
||||
</SlideItem> |
||||
</SlideRowList> |
||||
</div> |
||||
</template> |
||||
<script> |
||||
import {mapState} from "vuex"; |
||||
import globalMethods from "../../utils/global-methods"; |
||||
|
||||
export default { |
||||
name: "MyMusic", |
||||
components: {}, |
||||
props: { |
||||
modelValue: false |
||||
}, |
||||
data() { |
||||
return { |
||||
slideIndex: 0, |
||||
music: { |
||||
name: '发如雪', |
||||
mp3: 'https://m3.8js.net:99/2014/211204142150965.mp3', |
||||
cover: require('../../assets/img/music-cover/7.png'), |
||||
author: '周杰伦', |
||||
duration: 60, |
||||
use_count: 37441000, |
||||
is_collect: false, |
||||
is_play: false, |
||||
}, |
||||
isPlay: false, |
||||
isLoop: false, |
||||
isMove: false, |
||||
lastPageX: 0, |
||||
pageX: 0, |
||||
audio: new Audio(), |
||||
duration: 0, |
||||
currentTime: 0, |
||||
step: 0, |
||||
startX: 0, |
||||
slideBarWidth: 0 |
||||
} |
||||
}, |
||||
computed: { |
||||
...mapState(['bodyWidth']) |
||||
}, |
||||
created() { |
||||
}, |
||||
mounted() { |
||||
this.audio.src = this.music.mp3 |
||||
this.audio.addEventListener('loadedmetadata', e => { |
||||
this.duration = this.audio.duration |
||||
this.slideBarWidth = this.$refs.slideBar.clientWidth |
||||
this.step = this.slideBarWidth / Math.floor(this.duration) |
||||
}) |
||||
this.audio.addEventListener('timeupdate', e => { |
||||
if (!this.isMove) { |
||||
this.currentTime = Math.ceil(e.target.currentTime) |
||||
if (Math.ceil(e.target.currentTime) * this.step > this.slideBarWidth - 5) { |
||||
this.pageX = this.slideBarWidth - 5 |
||||
} else { |
||||
this.pageX = Math.ceil(e.target.currentTime) * this.step |
||||
} |
||||
} |
||||
}) |
||||
this.audio.addEventListener('play', e => this.isPlay = true) |
||||
this.audio.addEventListener('ended', e => { |
||||
if (this.isLoop) { |
||||
this.lastPageX = 0 |
||||
this.audio.currentTime = 0 |
||||
this.audio.play() |
||||
} else { |
||||
this.isPlay = false |
||||
} |
||||
}) |
||||
}, |
||||
methods: { |
||||
togglePlay() { |
||||
this.isPlay = !this.isPlay |
||||
if (this.isPlay) { |
||||
this.audio.play() |
||||
} else { |
||||
this.audio.pause() |
||||
} |
||||
}, |
||||
start(e) { |
||||
this.startX = e.touches[0].pageX |
||||
}, |
||||
move(e) { |
||||
this.isMove = true |
||||
this.pageX = this.lastPageX + (e.touches[0].pageX - this.startX) |
||||
if (this.pageX < 0) this.pageX = 0 |
||||
if (this.pageX > this.slideBarWidth) this.pageX = this.slideBarWidth - 5 |
||||
this.currentTime = Math.ceil(this.pageX / this.step) |
||||
globalMethods.$stopPropagation(e) |
||||
}, |
||||
end(e) { |
||||
this.lastPageX = this.pageX |
||||
this.currentTime = Math.ceil(this.pageX / this.step) |
||||
this.audio.currentTime = this.currentTime |
||||
this.audio.play() |
||||
this.isMove = false |
||||
globalMethods.$stopPropagation(e) |
||||
}, |
||||
$durationTime(time) { |
||||
if (time === 0) return '00:00' |
||||
else { |
||||
return this.$duration(time) |
||||
} |
||||
}, |
||||
durationStyle(type) { |
||||
// return {} |
||||
if (type === 1) { |
||||
return {width: this.pageX + 'px'} |
||||
} |
||||
return {left: this.pageX + 'px'} |
||||
}, |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style scoped lang="less"> |
||||
@import "../../assets/scss/index"; |
||||
|
||||
.MyMusic { |
||||
position: fixed; |
||||
left: 0; |
||||
right: 0; |
||||
bottom: 0; |
||||
top: 0; |
||||
overflow: auto; |
||||
color: white; |
||||
font-size: 1.4rem; |
||||
|
||||
.music-play { |
||||
display: flex; |
||||
flex-direction: column; |
||||
align-items: center; |
||||
|
||||
.cover { |
||||
margin-top: 4rem; |
||||
width: 80vw; |
||||
height: 80vw; |
||||
|
||||
img { |
||||
border-radius: 2.5rem; |
||||
object-fit: cover; |
||||
width: 100%; |
||||
height: 100%; |
||||
} |
||||
|
||||
} |
||||
|
||||
.lyrics-wrapper { |
||||
margin-top: 3rem; |
||||
overflow: auto; |
||||
height: 8rem; |
||||
|
||||
.container { |
||||
min-height: 8rem; |
||||
display: flex; |
||||
flex-direction: column; |
||||
justify-content: flex-end; |
||||
} |
||||
|
||||
.lyrics { |
||||
height: 4rem; |
||||
display: flex; |
||||
align-items: center; |
||||
justify-content: center; |
||||
} |
||||
} |
||||
|
||||
.bottom { |
||||
position: absolute; |
||||
bottom: 0; |
||||
width: 100vw; |
||||
|
||||
.desc { |
||||
width: 100vw; |
||||
padding: @padding-page; |
||||
box-sizing: border-box; |
||||
display: flex; |
||||
justify-content: space-between; |
||||
align-items: flex-end; |
||||
|
||||
img { |
||||
width: 3.5rem; |
||||
} |
||||
|
||||
.left { |
||||
.name { |
||||
font-size: 1.8rem; |
||||
margin-bottom: .4rem; |
||||
} |
||||
|
||||
.author { |
||||
font-size: 1.4rem; |
||||
} |
||||
} |
||||
|
||||
.right { |
||||
.btn { |
||||
display: flex; |
||||
align-items: center; |
||||
flex-direction: column; |
||||
margin-top: 2rem; |
||||
font-size: 1.2rem; |
||||
} |
||||
} |
||||
} |
||||
|
||||
.progress { |
||||
width: 100vw; |
||||
font-size: 1.2rem; |
||||
padding: 0 @padding-page; |
||||
box-sizing: border-box; |
||||
display: flex; |
||||
align-items: center; |
||||
justify-content: space-between; |
||||
color: gainsboro; |
||||
|
||||
.bar { |
||||
margin: 0 .6rem; |
||||
flex: 1; |
||||
position: relative; |
||||
|
||||
.slide-bar { |
||||
position: absolute; |
||||
height: 2rem; |
||||
width: 100%; |
||||
top: -1rem; |
||||
z-index: 11; |
||||
} |
||||
|
||||
&:before { |
||||
z-index: 9; |
||||
content: ' '; |
||||
height: 1.5px; |
||||
width: 100%; |
||||
background: gray; |
||||
position: absolute; |
||||
top: 0; |
||||
} |
||||
|
||||
.bar-line { |
||||
z-index: 10; |
||||
content: ''; |
||||
position: absolute; |
||||
top: 0; |
||||
height: 1.5px; |
||||
width: 50vw; |
||||
background: white; |
||||
} |
||||
|
||||
.bar-point { |
||||
z-index: 10; |
||||
position: absolute; |
||||
left: 50vw; |
||||
top: -3px; |
||||
height: .8rem; |
||||
width: .8rem; |
||||
border-radius: 50%; |
||||
background: white; |
||||
} |
||||
} |
||||
} |
||||
|
||||
.options { |
||||
width: 100vw; |
||||
padding: @padding-page; |
||||
box-sizing: border-box; |
||||
display: flex; |
||||
align-items: center; |
||||
justify-content: space-between; |
||||
|
||||
img { |
||||
width: 3.8rem; |
||||
height: 3.8rem; |
||||
} |
||||
|
||||
.center { |
||||
display: flex; |
||||
align-items: center; |
||||
|
||||
img { |
||||
margin: 0 1rem; |
||||
} |
||||
|
||||
.control { |
||||
width: 5.5rem; |
||||
height: 5.5rem; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
} |
||||
</style> |
Loading…
Reference in new issue