Browse Source

音乐播放器

pull/19/head
zyronon 4 years ago
parent
commit
9f92b748b5
  1. 1
      src/App.vue
  2. 10
      src/components/Video.vue
  3. 4
      src/components/slide/Indicator.vue
  4. 4
      src/pages/me/Me.vue
  5. 370
      src/pages/me/MyMusic.vue
  6. 2
      src/pages/me/Uploader.vue
  7. 2
      src/pages/people/FindAcquaintance.vue
  8. 2
      src/router/index.js
  9. 2
      src/utils/mixin.js

1
src/App.vue

@ -91,6 +91,7 @@ export default { @@ -91,6 +91,7 @@ export default {
'/me/right-menu/setting',
'/me/collect/video-collect',
'/me/collect/music-collect',
'/me/my-music',
'/login',
'/login/other',

10
src/components/Video.vue

@ -96,9 +96,9 @@ @@ -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 { @@ -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 { @@ -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 { @@ -628,7 +628,7 @@ export default {
}
}
.process {
.progress {
bottom: -1px;
position: absolute;
height: 7px;

4
src/components/Indicator.vue → src/components/slide/Indicator.vue

@ -1,5 +1,5 @@ @@ -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 { @@ -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;

4
src/pages/me/Me.vue

@ -88,7 +88,7 @@ @@ -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 @@ @@ -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

@ -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>

2
src/pages/me/Uploader.vue

@ -209,7 +209,7 @@ @@ -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";

2
src/pages/people/FindAcquaintance.vue

@ -129,7 +129,7 @@ @@ -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 {

2
src/router/index.js

@ -55,6 +55,7 @@ import LivePage from "../pages/home/LivePage"; @@ -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 = [ @@ -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},

2
src/utils/mixin.js

@ -5,7 +5,7 @@ import SlideRowList from "../components/slide/SlideRowList"; @@ -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…
Cancel
Save