深圳幻海软件技术有限公司 欢迎您!

记录--Vue开发历程---音乐播放器

2023-03-03

这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助一、audio标签的使用1、Audio对象属性 2、对象方法二、效果效果如下:三、代码代码如下:MusicPlayer.vue?123456789101112131415161718192021222324252627282930

这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助

一、audio标签的使用

1、Audio 对象属性

 2、对象方法

二、效果

效果如下:

三、代码

代码如下: MusicPlayer.vue

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
<template>
    <div class="music">
        <!-- 占位 -->
        <div class="m_hold">
 
        </div>
        <div class="m_img">
            <img :src="this.$parent.songNames[this.$parent.index].png" width="90px" :class="this.$parent.isRun">
        </div>
        <!-- 歌曲信息 -->
        <div class="m_text">
            {{ this.$parent.songNames[this.$parent.index].name }}
            <div class="block" style="margin-top:5px">
                <el-slider :v-model="value1"></el-slider>
            </div>
        </div>
        <!-- 按钮 -->
        <div class="m_btn">
            <a href="#" class="m_prev" @click="playLastSong()"></a>
            <a href="#" class="m_play" @click="changeState()" v-show="this.$parent.isShow"></a>
            <a href="#" class="m_pause" @click="changeState()" v-show="!this.$parent.isShow"></a>
            <a href="#" class="m_next" @click="playNextSong()"></a>
        </div>
        <!-- 折叠功能 -->
        <div class="m_close" @click="changeCloseState()">
            <a href=""></a>
        </div>
 
    </div>
</template>
 
<script>
export default {
    name: 'MusicPlayer',
    data() {
        return {
            songName: '',
            value1:0
 
        }
    },
    methods: {
        changeState() {
 
            this.$emit("play")
        },
        changeCloseState() {
            this.$emit("hello");
        },
        playNextSong() {
            this.$emit("nextSongs");
            this.songName = this.$parent.songNames[this.$parent.index].name
        },
        playLastSong() {
            this.$emit("lastSongs");
            this.songName = this.$parent.songNames[this.$parent.index].name
        }
    },
    watch:
    {
        
 
    }, mounted() {
        this.songName = this.$parent.songNames[this.$parent.index].name
    }
 
}
</script>
 
<style scoped>
/* 关于播放器的样式 */
.music {
    width: 100%;
    height: 120px;
    background: black;
    /* 相对浏览器定位 */
    position: absolute;
    left: 0px;
    bottom: 100px;
    border-bottom: 50px;
    /* 透明度 */
    opacity: 0.8;
    /* 阴影值 */
    box-shadow: 10px 15px 15px 1px black
}
 
.music .m_hold {
    float: left;
    width: 90px;
    height: 90px;
}
 
/* 调整音乐盒图片 */
.music .m_img {
    margin-top: 15px;
    margin-left: 10px;
    margin-right: 10px;
    /* 左浮动 */
    float: left;
    width: 90px;
    height: 90px;
    border-radius: 50%;
    overflow: hidden;
 
}
 
/* 修改文字 */
.music .m_text {
    /* 左浮动 */
    float: left;
    color: white;
    font-size: 20px;
    /* 字体加粗 */
    font-weight: bold;
    margin-top: 25px;
    margin-left: 20px;
    margin-bottom: 10px;
    width: 25%;
 
}
 
/* 使得所有a标签一起移动 */
.music .m_btn {
    float: left;
    position: absolute;
    /* 绝对定位:防止歌曲名称过长,挤出div */
    left: 40%;
}
 
/* 修改a标签 */
.music .m_btn a {
    width: 32px;
    height: 32px;
    float: left;
    margin-top: 50px;
    margin-left: 20px;
    background: url(@/assets/player_bg.png);
 
}
 
.music .m_btn .m_prev {
    background-position: -69px 0px;
}
 
.music .m_btn .m_next {
    background-position: -150px 0px;
}
 
.music .m_btn .m_play {
    background-position: -107px -5px;
}
 
.music .m_btn .m_prev:hover {
    background-position: -69px -32px;
}
 
.music .m_btn .m_next:hover {
    background-position: -150px -32px;
}
 
.music .m_btn .m_play:hover {
    background-position: -107px -47px;
}
 
.music .m_btn .m_pause {
    background-position: -292px -94px;
}
 
.music .m_btn .m_pause:hover {
    background-position: -334px -94px;
}
 
/* 还有一个悬停 没写 */
/* 设置最右边的关闭样式 */
.music .m_close {
    float: right;
    background: white;
    cursor: pointer;
    width: 23px;
    height: 100px;
    margin-top: 10px;
    background: url(@/assets/player_bg.png);
 
}
 
/* 设置最右边的关闭样式 */
.music_hide {
    float: left;
    background: white;
    cursor: pointer;
    width: 23px;
    height: 100px;
    margin-top: 2px;
}
 
.go {
    animation: bounce-in 2s linear infinite;
}
 
.come {
    animation: none;
}
 
@keyframes bounce-in {
    from {
        transform: rotate(0deg);
    }
 
    to {
        transform: rotate(360deg);
    }
}
 
.open-enter-active {
    animation: slide-in linear 0.5s;
}
 
.open-leave-active {
    animation: slide-in reverse linear 0.5s;
}
 
@keyframes slide-in {
    from {
        transform: translateX(-100%);
    }
 
    to {
        transform: translateX(0%);
    }
}
</style>

HideMusic.vue

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<template>
    <div class="music_hide" @click="changeCloseState()"><a href="#" class="m_open"></a></div>
</template>
 
<script>
export default {
    name:'HidePlayer',
    methods:{
        changeCloseState()
        {
            this.$emit("hello");
        }
    }
}
</script>
 
<style scoped>
.music_hide {
    float: left;
    background: url(@/assets/player_bg.png);
    cursor: pointer;
    width: 23px;
    height: 100px;
    margin-top: 10px;
    bottom: 100px;
    position: absolute;
    background-position-x: -45px;
}
</style>

MyPlayer.vue

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
<template>
    <div>
        <transition name="open" mode="out-in">
            <component v-bind:is="view" @hello="changeSlideState" @play="changePlayState" @lastSongs="lastSongs"
                @nextSongs="nextSongs"></component>
        </transition>
        <audio class="m_mp3" id="m_mp3" :src="this.songNames[this.index].Url" autoplay loop>
 
        </audio>
    </div>
 
</template>
 
<script>
import HidePlayer from '@/part/HidePlayer'
import MusicPlayer from '@/part/MusicPlayer'
export default {
    name: 'MyPlayer',
    data() {
        return {
            view: MusicPlayer,
            isClose: false,
            isShow: true,
            isRun: 'come',
            index: 0,
            songNum: 2,
            currentTime: '0:00',
            duration: '0:00',
            songNames: [
                {
                    id: 1,
                    name: '张韶涵-篇章',
                    Url: require('@/assets/张韶涵-篇章.mp3'),
                    png: require('@/assets/篇章.png'),
                },
                {
                    id: 2,
                    name: '爱就一个字 抒情版',
                    Url: require('@/assets/爱就一个字 抒情版.mp3'),
                    png: require('@/assets/爱就一个字.png'),
                },
                {
                    id: 3,
                    name: '最伟大的作品-周杰伦',
                    Url: require('@/assets/最伟大的作品-周杰伦.mp3'),
                    png: require('@/assets/周杰伦.jpg'),
                },
                {
                    id: 4,
                    name: '等你下课 (with 杨瑞代)-周杰伦',
                    Url: require('@/assets/等你下课 (with 杨瑞代)-周杰伦.mp3'),
                    png: require('@/assets/等你下课.png'),
                },
                {
                    id: 5,
                    name: '告白气球-周杰伦',
                    Url: require('@/assets/告白气球-周杰伦.mp3'),
                    png: require('@/assets/告白气球.png'),
                },
                {
                    id: 6,
                    name: '还在流浪-周杰伦',
                    Url: require('@/assets/还在流浪-周杰伦.mp3'),
                    png: require('@/assets/还在流浪.png'),
                },
            ]
        }
    },
    components: {
        HidePlayer,
        MusicPlayer
    },
    methods: {
        changeSlideState() {
            this.isClose = !this.isClose;
            if (this.isClose) {
                this.view = HidePlayer;
            } else {
                this.view = MusicPlayer;
            }
        },
        changePlayState() {
            if (!this.isShow) {
                this.isShow = true;
                this.isRun = "come";
                document.getElementById("m_mp3").pause();
            } else {
                this.isShow = false;
                this.isRun = "go";
                var my_mp3 = document.getElementById("m_mp3");
                my_mp3.play();
 
 
            }
        },
        nextSongs() {
            if (this.isShow) {
                this.isShow = false;
                this.isRun = "go";
            }
            this.index = (this.index + 1) % this.songNum;
        },
        lastSongs() {
            if (this.isShow) {
                this.isShow = false;
                this.isRun = "go";
            }
            if (this.index == 0) {
                this.index = this.songNum - 1;
            } else {
                this.index = this.index - 1;
            }
 
        }
    }, mounted() {
        this.songNum = this.songNames.length;
         
    }
 
}
</script>
 
<style scoped>
.open-enter-active {
    animation: slide-in linear 0.5s;
}
 
.open-leave-active {
    animation: slide-in reverse linear 0.5s;
}
 
@keyframes slide-in {
    from {
        transform: translateX(-100%);
    }
 
    to {
        transform: translateX(0%);
    }
}
</style>

四、难点解析

1、过渡动画的实现

 参考了vue文档过渡&动画中多个组件的过渡(下面三份代码)

?
1
2
3
<transition name="component-fade" mode="out-in">
  <component v-bind:is="view"></component>
</transition>
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
new Vue({
  el: '#transition-components-demo',
  data: {
    view: 'v-a'
  },
  components: {
    'v-a': {
      template: '<div>Component A</div>'
    },
    'v-b': {
      template: '<div>Component B</div>'
    }
  }
})
?
1
2
3
4
5
6
7
.component-fade-enter-active, .component-fade-leave-active {
  transition: opacity .3s ease;
}
.component-fade-enter, .component-fade-leave-to
/* .component-fade-leave-active for below version 2.1.8 */ {
  opacity: 0;
}

因此分化出MusicPlayer.vue 和 HideMusic.vue,由此又产生了组件内通信的问题。

2、组件内通信

为什么会产生组件内的通信?原因在于:MusicPlayer组件和HidePlayer组件,只能有一个展示,但是在不展示的过程中,他的数据应该也是实时改变的。例如MusicPlayer组件上有播放按钮,如果不采用组件通信,那么MusicPlayer重新渲染的时候,播放按钮会回到最初的设定,是不符合逻辑的。所以需要采用组件内通信的方式。实现的方式也比较简单,子组件直接访问父组件的数据,子组件通过$emit调用父组件的方法,修改父组件的数据。

3、旋转动画的实现

 首先,编写动画。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
.go {
    animation: bounce-in 2s linear infinite;
}
 
.come {
    animation: none;
}
 
@keyframes bounce-in {
    from {
        transform: rotate(0deg);
    }
 
    to {
        transform: rotate(360deg);
    }
}

然后,动态绑定class,isRun两个值即为"go","come"。

?
1
2
3
<div class="m_img">
   <img :src="this.$parent.songNames[this.$parent.index].png" width="90px" :class="this.$parent.isRun">
</div>

本文转载于:

https://blog.51cto.com/u_15807146/5807883

如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。

 


__EOF__

  • 本文作者: 林恒
  • 本文链接: https://www.cnblogs.com/smileZAZ/p/17047009.html
  • 关于博主: 评论和私信会在第一时间回复。或者直接私信我。
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
  • 声援博主: 如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。