最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • vue+typescript音乐播放器

    正文概述 掘金(codetest2020)   2021-01-02   417

    vue + typescript音乐播放器

    掘金上面已经有很多播放器的实现了。这次造轮子主要是刻意练习吧,主要根据ustbhuangyi.com/music/的UI和流程实现。稍微查了下这个对应网课价格是399。。。目前只是粗略实现了主要的UI部分,数据部分都是本地的Mock数据。具体源码请戳github。

    技术栈

    使用了vue2.x, typescript, vue-router, swiper,better-scroll。

    • vue2.x: MVVM框架
    • typescript: 现在都普遍使用,主要还是为了语法检查和写代码的便利。按照现在的写法最后打包的代码会比Javascript更大。
    • vue-router: 局部视图的更新和页面导航。
    • swiper: 轮播幻灯片。
    • better-scroll: 列表顺畅滚动。

    主要设计

    以下按照页面结构,导航和事件,音频播放和播放页面来讲述播放器的主要设计。

    页面结构

    所有的页面都在App.vue上显示,引入Header.vue, Tab.vue和ShortPlayer.vue用以显示header, tab导航和底部固定播放器。通过router-view来根据导航显示对应的推荐,歌手列表,排行,搜索,播放器等其他模块。虽然Header, Tab都放在App.vue,可以通过position:fixed, z-index来遮挡,主要不想代码重复。
    推荐页面中的幻灯片滚动部分使用的Swiper对象来操作具体的dom节点,没有引入组件。列表滚动方面使用了better-scroll。使用这个部分会遇到滚动不生效的情况。一个重要的点是需要保证子节点超出了父节点的范围。同时需要传入{click:true}来保证组件内部的点击事件能够得到响应。滚动中是使用tanslateX来实现视图位移,而且需要考虑到生成BetterScroll对象的时候实际节点已经存在,节点内部结构变化的时候需要refresh。Vue使用的是虚拟节点,要Vue.nexttick的时候refresh。

    导航和事件

    对于简单的组件内的事件处理相对简单。如果说事件需要通知到其他的组件,那么就要设计。使用订阅和发布模式来传递数据。提供Register, Unregister, Fire接口。用一个map和数组实现即可。

    export class EventHub{
        private static id: number = 0
        private static eventData: Map<string, Array<(data: EventData) => void>> = new Map<string, Array<(data: EventData) => void>>();
        public static RegisterEvent(name: string, callback: (data: EventData) => void) {
            if (!this.eventData.has(name)){
                this.eventData.set(name, [])
            }
    
            this.eventData.get(name).push(callback)
        }
    
        public static UnregisterEvent(name: string, callback: (data: EventData) => void): boolean {
            if (this.eventData.has(name)){
                let arr = this.eventData.get(name)
                for (let inx = 0; inx < arr.length; ++inx) {
                    if (arr[inx] === callback) {
                        arr.splice(inx, 1)
                        if (arr.length == 0) {
                            this.eventData.delete(name)
                        }
    
                        return true
                    }
                }
            }
    
            return false
        }
    
        public static FireEvent(name: string, data: any) {
            if (this.eventData.has(name)) {
                let arr = this.eventData.get(name)
                let event: EventData = {id: ++this.id, data: data}
                for (let callback of arr) {
                    callback(event)
                }
            }
        }
    }
    

    在页面导航方面,使用的hash模式,为的是简化,如果是history模式,还需要server端进行处理。

    export var router = new VueRouter({
        routes: [
            {
                path: '/', component: RecommendationComponent, meta: 0
            },
            {
                path: '/singer', component: SingerListComponent, meta: 1
            },
            {
                path: '/top', component: TopListComponent, meta: 2
            },
            {
                path: '/search', component: SearchComponent, meta: 3
            },
            {
                path: '/my', component: MySonogListComponent, meta: 0, name: "my"
            },
            {
                path: '/full', component: FullPlayerComponent, meta: 0, name: "player"
            },
            {
                path: '/list', component: PlayListComponent, meta: 0, name: "list"
            }
        ],
        mode: "hash"
    })
    

    在tab点击的时候,事件处理是在Tab.vue实现的,这个时候需要发出事件。

                EventHub.FireEvent(EventType.HomePageTab, id)
    

    在App.vue中,注册Tab的事件回调并更新router

        switchTab(tab: EventData) {
            switch(tab.data) {
                case 0:
                    router.replace("/")
                    break;
                case 1:
                    router.replace("/singer")
                    break;
                case 2:
                    router.replace("/top")
                    break;
                case 3:
                    router.replace("/search")
                    break;
            }
        }
    

    vue+typescript音乐播放器

    音频播放

    主要实现在Player.ts中实现,使用Audio对象注册对应的事件回调,并发出更新事件。FullPlayer.vue和ShortPlayer.vue来响应数据更新。

            let playData: PlayerStateData = {
                state: PlayerState.play,
                progress: this.player.currentTime,
                duration: this.player.duration,
                data: this.playData
            }
    
            EventHub.FireEvent(EventType.PlayEvent, playData)
    

    PlayControl.ts可以控制播放上下一首,达到播放模式的控制。

    播放页面

    主要是全屏播放页面,底部播放页面还是比较简单。第一部分是播放进度条,进度条的时候需要考虑播放的圆点本身需要占用空间,实际的进度条需要排除这个原点的宽度。 vue+typescript音乐播放器

    点击和拖动进度调的圆点的时候需要事件响应的节点(要使用父节点),关注touchstart, toucmove, touchend, touchcancel事件。播放进度条的宽度使用width,圆点使用abosolute方式设置left即可。

                    <div class="flllplayerprogresswrap" ref="progressBarRef" @touchstart="touchStart($event)" @touchcancel="touchEnd()"  @touchend="touchEnd()"  @touchmove="dragParnet($event)">
                        <div class="flllplayerprogress">
                            <div class="flllplayerprogresscut">
                                <div class="fullplayerprogresscur" :style="{width: prog + '%'}"></div>
                                <div class="fullplayercurdot" ref="progressDotRef" :style="{left: prog + '%'}"/>
                            </div>
                        </div>
                    </div>
    

    另一个比较困难的部分就是歌词滚动。首先是歌词解析,本来想使用lyric-parser,但是发现不好用。歌词的滚动部分应该要播放进度驱动。当当前音频的currentTime更新的时候再更新。因此写一个一个简单的LyricParser能够根据传入的时间来返回应该高亮的行数。这样就不用考虑lyric-parser里面play, seek的问题。

    总结

    这个播放器有很多的bug,主要是为了练习设计能力,快速学习应用的能力。比如如何设计页面结构,事件处理。如果学习swiper,better-scroll并应用到实际中。


    起源地下载网 » vue+typescript音乐播放器

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元