音乐播放器
This commit is contained in:
parent
88fa436d89
commit
9f92b748b5
@ -91,6 +91,7 @@ export default {
|
||||
'/me/right-menu/setting',
|
||||
'/me/collect/video-collect',
|
||||
'/me/collect/music-collect',
|
||||
'/me/my-music',
|
||||
|
||||
'/login',
|
||||
'/login/other',
|
||||
|
||||
@ -96,9 +96,9 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="process"
|
||||
<div class="progress"
|
||||
v-if="duration > 60"
|
||||
:class="processClass"
|
||||
:class="progressClass"
|
||||
@touchmove="move"
|
||||
@touchend="end"
|
||||
>
|
||||
@ -157,7 +157,7 @@ export default {
|
||||
durationStyle() {
|
||||
return {left: this.pageX + 'px'}
|
||||
},
|
||||
processClass() {
|
||||
progressClass() {
|
||||
if (this.isMove) {
|
||||
return 'stop'
|
||||
} else {
|
||||
@ -336,7 +336,7 @@ export default {
|
||||
setTimeout(() => {
|
||||
this.isMove = false
|
||||
}, 1000)
|
||||
this.currentTime = this.currentTime = Math.ceil(Math.ceil(e.changedTouches[0].pageX) / this.step)
|
||||
this.currentTime = Math.ceil(Math.ceil(e.changedTouches[0].pageX) / this.step)
|
||||
this.play()
|
||||
globalMethods.$stopPropagation(e)
|
||||
}
|
||||
@ -628,7 +628,7 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
.process {
|
||||
.progress {
|
||||
bottom: -1px;
|
||||
position: absolute;
|
||||
height: 7px;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<script>
|
||||
import bus from "../utils/bus";
|
||||
import bus from "../../utils/bus";
|
||||
|
||||
export default {
|
||||
name: "Indicator",
|
||||
@ -118,7 +118,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
@import "../assets/scss/index";
|
||||
@import "../../assets/scss/index";
|
||||
|
||||
.indicator-ctn {
|
||||
font-size: 1.4rem;
|
||||
@ -88,7 +88,7 @@
|
||||
<div class="bottom">发现超值好物</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item" @click="$no">
|
||||
<div class="item" @click="$nav('/me/my-music')">
|
||||
<img src="../../assets/img/icon/me/music-white.png" alt="">
|
||||
<div class="right">
|
||||
<div class="top">我的音乐</div>
|
||||
@ -324,7 +324,7 @@
|
||||
<script>
|
||||
import Posters from '../../components/Posters'
|
||||
import Footer from "../../components/Footer";
|
||||
import Indicator from '../../components/Indicator'
|
||||
import Indicator from '../../components/slide/Indicator'
|
||||
import {nextTick} from 'vue'
|
||||
import {mapState} from "vuex";
|
||||
import bus from "../../utils/bus";
|
||||
|
||||
370
src/pages/me/MyMusic.vue
Normal file
370
src/pages/me/MyMusic.vue
Normal file
@ -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>
|
||||
@ -209,7 +209,7 @@
|
||||
</template>
|
||||
<script>
|
||||
import Posters from '../../components/Posters'
|
||||
import Indicator from '../../components/Indicator'
|
||||
import Indicator from '../../components/slide/Indicator'
|
||||
import {nextTick} from 'vue'
|
||||
import {mapState} from "vuex";
|
||||
import bus from "../../utils/bus";
|
||||
|
||||
@ -129,7 +129,7 @@
|
||||
<script>
|
||||
import People from './components/People'
|
||||
import Search from '../../components/Search'
|
||||
import Indicator from '../../components/Indicator'
|
||||
import Indicator from '../../components/slide/Indicator'
|
||||
import FromBottomDialog from "../../components/dialog/FromBottomDialog";
|
||||
|
||||
export default {
|
||||
|
||||
@ -55,6 +55,7 @@ import LivePage from "../pages/home/LivePage";
|
||||
import Test5 from "../pages/Test5";
|
||||
import MusicCollect from "../pages/me/collect/MusicCollect";
|
||||
import VideoCollect from "../pages/me/collect/VideoCollect";
|
||||
import MyMusic from "../pages/me/MyMusic";
|
||||
|
||||
const routes = [
|
||||
// {path: '', component: Music},
|
||||
@ -111,6 +112,7 @@ const routes = [
|
||||
{path: '/me/right-menu/setting', component: Setting},
|
||||
{path: '/me/collect/music-collect', component: MusicCollect},
|
||||
{path: '/me/collect/video-collect', component: VideoCollect},
|
||||
{path: '/me/my-music', component: MyMusic},
|
||||
|
||||
{path: '/login', component: Login},
|
||||
{path: '/login/other', component: OtherLogin},
|
||||
|
||||
@ -5,7 +5,7 @@ import SlideRowList from "../components/slide/SlideRowList";
|
||||
import SlideColumnList from "../components/slide/SlideColumnList";
|
||||
import SlideColumnVirtualList from "../components/slide/SlideColumnVirtualList";
|
||||
import SlideItem from "../components/slide/SlideItem";
|
||||
import Indicator from "../components/Indicator";
|
||||
import Indicator from "../components/slide/Indicator";
|
||||
import Video from "../components/Video";
|
||||
import Footer from "../components/Footer";
|
||||
import Mask from "../components/Mask";
|
||||
|
||||
Loading…
Reference in New Issue
Block a user