效果
GIF动图有3M多,如果没有显示出来,请再等等
看到了吧,自己的一点小创意,搞了个猪头上去。
相关代码
本程序中仅使用了vue的ajax框架vue-resource,未使用到vue-router,因此再安装vue-cli的时候,可以略过vue-router,本程序仅有一个组件,即只有一个vue文件,使用了css预处理语言stylus。使用的json数据为本站相关php代码生成的(仅为了演示),如果你是在本地搭建环境,json也可以写在本地。
本demo已经使用cordova制作成了安卓的apk文件,如需体验,请点击此处下载
源码已经提交到github(记得给我加星哦):https://github.com/king2088/vue-tplayer
演示地址:http://www.egtch.com/t_works/tplayer/
生成json的php如下
代码非常简单,就是定义一串json数据,然后在展现出来:
1 |
|
2 | header("Access-Control-Allow-Origin: *");//设置跨域允许 |
3 | header('Content-Type: text/html; charset=utf-8'); //设置页面编码 |
4 | header('Content-type: application/json');//设置页面为json格式的文档 |
5 | |
6 | $data =' {"music":[ |
7 | { |
8 | "id":"1", |
9 | "name": "Apologize", |
10 | "singer":"Timbaland Remix", |
11 | "img":"http://www.egtch.com/t_works/Vuedata/apologize.jpg", |
12 | "url": "http://www.egtch.com/t_works/Vuedata/Apologize (Timbaland Remix).mp3" |
13 | }, |
14 | { |
15 | "id":"2", |
16 | "name": "Hero", |
17 | "singer":"Enrique Iglesias", |
18 | "img":"http://www.egtch.com/t_works/Vuedata/hero.jpg", |
19 | "url": "http://www.egtch.com/t_works/Vuedata/Hero.mp3" |
20 | }, |
21 | { |
22 | "id":"3", |
23 | "name": "I AM YOU", |
24 | "singer":"Kim Taylor", |
25 | "img":"http://www.egtch.com/t_works/Vuedata/iamyou.jpg", |
26 | "url": "http://www.egtch.com/t_works/Vuedata/I Am You.mp3" |
27 | } |
28 | ]}'; |
29 | echo $data |
30 |
|
app.vue代码
1 | <template> |
2 | <div id="app"> |
3 | <div class="list"><span>{{music.name}}-{{music.singer}}</span><a @click="isShow(),isBg()"><img src="./assets/player/list.png" alt=""></a></div> |
4 | <div class="music"> |
5 | <div class="text">{{music.name}}<span>{{music.singer}}</span></div> |
6 | <div class="img"><img id="pic" :src="music.img"></div> |
7 | </div> |
8 | <div class="player"> |
9 | <div class="ico"><img src="./assets/player/backward.png" id="pre" @click="isPre"></div> |
10 | <div class="ico"><img src="./assets/player/play.png" id="play" @click="isPlay"><img src="./assets/player/pause.png" id="stop" @click="isStop"></div> |
11 | <div class="ico"><img src="./assets/player/forward.png" id="next" @click="isNext"></div> |
12 | </div> |
13 | <audio id="audio" :src="music.url" preload autoplay @ended="isNext"></audio> |
14 | <transition name="fade"> |
15 | <div class="songList" v-show="showList"> |
16 | <div class="items"> |
17 | <div class="title">歌曲列表 <span id="close" @click="isClose"><img src="./assets/player/close.png"></span></div> |
18 | <div class="item" v-for="(item, index) in MList"> |
19 | <a :id="'item-'+index" @click="clickSong(index)"> |
20 | <span class="l">{{MList[index].name}}</span> |
21 | <span class="r">{{MList[index].singer}}</span> |
22 | <div class="clear"></div> |
23 | </a> |
24 | </div> |
25 | </div> |
26 | </div> |
27 | </transition> |
28 | </div> |
29 | </template> |
30 |
|
31 | <script> |
32 | export default { |
33 | name: 'app', |
34 | data(){ |
35 | return{ |
36 | apiUrl: 'http://www.egtch.com/t_works/Vuedata/data.php', |
37 | id: 0, |
38 | bg:'', |
39 | music: '', |
40 | MList:'', |
41 | showList: false |
42 | } |
43 | }, |
44 | created(){ |
45 | this.getMusic(this.id) |
46 | this.isBg() |
47 | }, |
48 | watch:{ |
49 | 'id':'getMusic', |
50 | 'bg':'isBg' |
51 | }, |
52 | methods:{ |
53 | getMusic(p){ |
54 | this.$http.get(this.apiUrl).then(response => { |
55 | // get body data |
56 | response = response.body |
57 | this.MList = response.music |
58 | /*alert(this.MList)*/ |
59 | if(p < response.music.length) { |
60 | this.music = response.music[p] |
61 | } |
62 | if(p > response.music.length){ |
63 | this.id = 0 |
64 | this.music = response.music[this.id] |
65 | } |
66 | if(p < 0){ |
67 | this.id = response.music.length |
68 | this.music = response.music[this.id] |
69 | } |
70 | }) |
71 | }, |
72 | /*查看当前audio是否正在播放,如果停止,那么播放下一曲*/ |
73 |
|
74 | isPlay(){ |
75 | document.getElementById("audio").play(); |
76 | document.getElementById("play").style.display="none"; |
77 | document.getElementById("stop").style.display="inline"; |
78 | document.getElementById("pic").style.animationPlayState="running"; |
79 | return false |
80 | }, |
81 | isStop(){ |
82 | document.getElementById("audio").pause(); |
83 | document.getElementById("stop").style.display="none"; |
84 | document.getElementById("play").style.display="inline"; |
85 | document.getElementById("pic").style.animationPlayState="paused"; |
86 | return false |
87 | }, |
88 | isNext(){ |
89 | this.id++; |
90 | /*为了防止停止状态下,点击下一曲的时候,停止图标不出现,并且专辑图片不转动*/ |
91 | document.getElementById("play").style.display="none"; |
92 | document.getElementById("stop").style.display="inline"; |
93 | document.getElementById("item-"+this.bg).style.background='none'; |
94 | document.getElementById("pic").style.animationPlayState="running"; |
95 | }, |
96 | isPre(){ |
97 | this.id--; |
98 | document.getElementById("play").style.display="none"; |
99 | document.getElementById("stop").style.display="inline"; |
100 | document.getElementById("pic").style.animationPlayState="running"; |
101 | }, |
102 | isShow(){ |
103 | this.showList = true |
104 | }, |
105 | isClose(){ |
106 | this.showList = false |
107 | }, |
108 | isBg(){ |
109 | this.bg = this.id |
110 | document.getElementById("item-"+this.bg).style.background='#F2F2F2'; |
111 | }, |
112 | /*点击列表中的歌曲,并播放*/ |
113 | clickSong(i){ |
114 | this.id = i; |
115 | document.getElementById("item-"+this.bg).style.background='none'; |
116 | document.getElementById("play").style.display="none"; |
117 | document.getElementById("pic").style.animationPlayState="running"; |
118 | this.isBg() |
119 | } |
120 | } |
121 | } |
122 | </script> |
123 |
|
124 | <style lang="stylus" rel="stylesheet/stylus"> |
125 | html,body |
126 | height 100% |
127 | width 100% |
128 | max-width 600px |
129 | margin 0 auto |
130 | .clear |
131 | clear both |
132 | #app |
133 | font-family 'Microsoft YaHei','\5FAE\8F6F\96C5\9ED1' |
134 | font-weight lighter |
135 | -webkit-font-smoothing antialiased |
136 | -moz-osx-font-smoothing grayscale |
137 | color #2c3e50 |
138 | height 100% |
139 | width 100% |
140 | overflow hidden |
141 | .list |
142 | width 100% |
143 | height 60px |
144 | line-height 60px |
145 | background #F2F2F2 |
146 | border-bottom 1px #333 solid |
147 | span |
148 | padding-left 20px |
149 | display inline-block |
150 | color darkblue |
151 | & > a |
152 | display block |
153 | float right |
154 | & > img |
155 | margin-top 8px |
156 | width 40px |
157 | .player |
158 | width 100% |
159 | max-width 600px |
160 | height 30% |
161 | opacity .8 |
162 | position fixed |
163 | background #F2F2F2 |
164 | border-top 3px #000 solid |
165 | border-bottom 10px brown solid |
166 | bottom 0 |
167 | font-size 0 |
168 | border-top-left-radius 50% |
169 | border-top-right-radius 50% |
170 | text-align center |
171 | display flex |
172 | .ico |
173 | flex 1 |
174 | padding-top 50px |
175 | text-align center |
176 | #play |
177 | width 60% |
178 | max-width 64px |
179 | margin-top 35px |
180 | display none |
181 | #stop |
182 | margin-top 35px |
183 | width 60% |
184 | max-width 64px |
185 | & > img |
186 | border 0 |
187 | width 32px |
188 | vertical-align middle |
189 | .music |
190 | width 100% |
191 | height 100% |
192 | background url("./assets/player/bg.jpg") |
193 | position relative |
194 | top 0 |
195 | left 0 |
196 | .text |
197 | width 100% |
198 | text-align center |
199 | padding-top 5% |
200 | font-size 30px |
201 | span |
202 | font-size 14px |
203 | display block |
204 | line-height 2 |
205 | .img |
206 | width 200px |
207 | height 200px |
208 | border-radius 50% |
209 | background #333 |
210 | margin 0 auto |
211 | position absolute |
212 | outline none |
213 | bottom 46% |
214 | left 50% |
215 | transform translateX(-100px) |
216 | & > img |
217 | width 90% |
218 | height 90% |
219 | padding 5% |
220 | border-radius 50% |
221 | animation: rotation 10s linear infinite; |
222 | -moz-animation: rotation 10s linear infinite; |
223 | -webkit-animation: rotation 10s linear infinite; |
224 | -o-animation: rotation 10s linear infinite; |
225 | .songList |
226 | position: fixed; |
227 | top: 0; |
228 | z-index: 100; |
229 | width: 100%; |
230 | max-width 600px |
231 | margin 0 auto |
232 | height: 100%; |
233 | overflow: auto; |
234 | transition: all .5s; |
235 | background: rgba(7, 17, 27, .4); |
236 | backdrop-filter: blur(10px); /*ios 模糊背景*/ |
237 | .items |
238 | background #ffffff |
239 | width 100% |
240 | height 55% |
241 | margin 0 auto |
242 | padding 60px 0 0 0 |
243 | overflow auto |
244 | border-bottom 2px #000 solid |
245 | .title |
246 | width 100% |
247 | max-width 600px |
248 | height 50px |
249 | line-height 50px |
250 | background #FFF |
251 | border-bottom 1px #DDD solid |
252 | text-align center |
253 | padding-top 10px |
254 | font-size 18px |
255 | position fixed |
256 | top 0 |
257 | #close |
258 | float right |
259 | width 40px |
260 | & > img |
261 | width 40px |
262 | .item |
263 | width 100% |
264 | margin 0 auto |
265 | border-top 1px #EEE solid |
266 | line-height 2 |
267 | & > a |
268 | color black |
269 | padding 8px 5% |
270 | display block |
271 | width 90% |
272 | & > span |
273 | display inline-block |
274 | width 50% |
275 | .l |
276 | float left |
277 | font-size 16px |
278 | .r |
279 | float right |
280 | text-align right |
281 | font-size 12px |
282 | color #CCC |
283 | @-webkit-keyframes rotation |
284 | from |
285 | transform rotate(0deg) |
286 | to |
287 | -webkit-transform rotate(360deg) |
288 | .fade-enter-active |
289 | transition all .3s ease |
290 | .fade-leave-active |
291 | transition all .3s cubic-bezier(1.0, 0.5, 0.8, 1.0) |
292 | .fade-enter, .fade-leave-active |
293 | transform translateY(-20px) |
294 | opacity 0 |
295 | </style> |