仿照網(wǎng)易云音樂(lè)自制一個(gè)音樂(lè)網(wǎng)頁(yè)播放器(整體思路以及一些容易踩的坑)

自制音樂(lè)網(wǎng)頁(yè)播放器.jpg

????最近套啤,通過(guò)一個(gè)星期的時(shí)間固蛾,完成了一個(gè)仿照網(wǎng)易云音樂(lè)的自制音樂(lè)網(wǎng)頁(yè)播放器搪缨,這個(gè)播放器實(shí)現(xiàn)了以下的功能:
????1.后臺(tái)有上傳歌曲、編輯歌曲功能挚币。
????2.前端頁(yè)面自動(dòng)更新播放熱度高的歌曲
????3.在線聽歌亮蒋、查看歌詞。且配有相應(yīng)的播放動(dòng)畫忘晤。

????以下是該應(yīng)用的預(yù)覽鏈接,直接點(diǎn)擊預(yù)覽鏈接即可打開宛蚓。

????該應(yīng)用主要是使用了jQuery以及MVC模塊化的思想來(lái)完成的,因此在介紹這個(gè)應(yīng)用的制作思路和流程之前设塔,我想重新總結(jié)一下對(duì)模塊化和MVC的理解凄吏。

何為模塊化

????我的理解中远舅,模塊化是通過(guò)MVC的V,也就是View來(lái)劃分的痕钢,把頁(yè)面中看得見的區(qū)域進(jìn)行功能劃分图柏,每一個(gè)功能不同的區(qū)域就是一個(gè)分開的模塊,模塊之間是通過(guò)命名空間或者說(shuō)事件中心eventHub來(lái)進(jìn)行聯(lián)系的任连,這種聯(lián)系方式的好處就是可以任意地跨模塊進(jìn)行信息的交流蚤吹,頁(yè)面中的任意模塊都能與另一任意模塊進(jìn)行交流,只要它們綁定同樣的事件就可以了随抠。但缺點(diǎn)也很明顯裁着,就是事件中心是全局環(huán)境下的事件中心,如果一個(gè)事件觸發(fā)了兩個(gè)模塊來(lái)發(fā)布相同的事件拱她,那就會(huì)不可避免地產(chǎn)生沖突二驰,這個(gè)時(shí)候只能通過(guò)改變其中一個(gè)模塊的發(fā)布事件的事件名來(lái)消除這種沖突,這顯然并不是一種理想的解決辦法秉沼,因?yàn)楸举|(zhì)上他們就是相同的事件桶雀,給相同的事件不同的命名的做法并不恰當(dāng),因此這也是我認(rèn)為的MVC模塊交流方式的缺點(diǎn)唬复。
????以下是eventHub的代碼:

window.eventHub={
    events:{},
    emit(eventName,data){
        for(let key in this.events){
            if (key===eventName){
                let fnList=this.events[key]
                fnList.map((fn)=>{
                    fn.call(undefined,data)
                })
            }
        }
    },
    on(eventName,fn){
        if (this.events[eventName]===undefined){
            this.events[eventName]=[]
        }
        this.events[eventName].push(fn)
    }
}


何為MVC

????其次MVC有三個(gè)部分矗积,分別為M(Model),V(View)和C(Controller)敞咧,通過(guò)面向?qū)ο缶幊痰乃枷爰罚覀兛梢园堰@三個(gè)部分變成對(duì)象,然后在對(duì)象中進(jìn)行相對(duì)應(yīng)的操作妄均。
????前面講到了View就是當(dāng)前模塊所代表的看得見的功能劃分部分柱锹,View一般需要你指定這個(gè)部分在HTML對(duì)應(yīng)的元素的ID,例如我把一個(gè)歌曲列表當(dāng)作一個(gè)模塊丰包,那么一般這個(gè)列表會(huì)在HTML以一個(gè)ul標(biāo)簽的形式表示,那么我們?cè)谑褂肕VC時(shí)壤巷,就要給View指定這個(gè)ul標(biāo)簽的ID作為這個(gè)MVC模塊所要操控的區(qū)域的ID邑彪。一般在對(duì)象View里還有屬性template來(lái)表示這個(gè)功能區(qū)域的HTML模版,然后通過(guò)View對(duì)象里面你設(shè)置的函數(shù)去改變這個(gè)template胧华,例如增減標(biāo)簽的類名寄症,例如把之后Model對(duì)象里面的數(shù)據(jù)data內(nèi)容放入標(biāo)簽中等等,然后通過(guò)render()函數(shù)來(lái)更新功能區(qū)的HTML代碼矩动,使頁(yè)面視圖發(fā)生相對(duì)應(yīng)的改變有巧。總的來(lái)說(shuō)悲没,View要做的事情篮迎,就是改變網(wǎng)頁(yè)的用戶視覺,去把代碼改變的內(nèi)容以直觀的方式呈現(xiàn)在網(wǎng)頁(yè)中,需要切記的是每個(gè)MCV模塊中View所代表的區(qū)域之間是不能互相交叉的甜橱,因此在進(jìn)行模塊化時(shí)要明確好每個(gè)模塊的職責(zé)逊笆。
????以下是一個(gè)簡(jiǎn)單的View對(duì)象的代碼例子:

let view={
    el:'#功能區(qū)域',
    template:`
    <div>HTML模版</div>
    `,
    render(){
        $(this.el).html(this.template)
    }
}

????然后是Model所代表的是當(dāng)前模塊所包含的數(shù)據(jù)以及操作數(shù)據(jù)的方法,繼續(xù)以歌單模塊為例的話岂傲,那么歌單中的每個(gè)歌曲的ID难裆、以及ID對(duì)應(yīng)的歌曲名字和歌手就是我們所需要數(shù)據(jù)data,這些數(shù)據(jù)會(huì)存放在這個(gè)歌單模塊的Model中镊掖,每當(dāng)模塊需要存儲(chǔ)乃戈、獲取或者更新數(shù)據(jù),都要呼叫Model模塊并由Model模塊來(lái)執(zhí)行這些操作亩进。需要記住症虑,每個(gè)模塊的Model并不需要儲(chǔ)存整個(gè)應(yīng)用的所有數(shù)據(jù),而是只需儲(chǔ)存這個(gè)模塊所對(duì)應(yīng)的必須要的數(shù)據(jù)即可镐侯,例如歌單模塊因?yàn)樾枰層脩糁烂恳皇赘枋鞘裁凑焯郑虼诵枰杳约案枋值臄?shù)據(jù)。而因?yàn)橐推渌K進(jìn)行交流苟翻,例如讓其他模塊知道用戶是否點(diǎn)擊了某首歌韵卤,因此還需要儲(chǔ)存歌曲的ID,以方便之后歌單模塊通過(guò)事件中心把點(diǎn)擊的歌曲的ID數(shù)據(jù)傳遞給其他的模塊崇猫。歌單模塊并不需要存儲(chǔ)歌詞沈条、歌曲封面這些數(shù)據(jù),是因?yàn)檫@個(gè)模塊并不展示和操作這些數(shù)據(jù)诅炉,而其他模塊可以通過(guò)歌單模塊傳來(lái)的ID去獲取這些數(shù)據(jù)蜡歹。這篇文章介紹的音樂(lè)播放器的應(yīng)用就是Model配合LeanCloud數(shù)據(jù)庫(kù)和七牛數(shù)據(jù)庫(kù)實(shí)現(xiàn)的。
????以下是一個(gè)簡(jiǎn)單的Model對(duì)象的代碼例子:

let model={
    data:{},
    fetch(){......},
    save(){......},
    update(){......}
}

????最后是Controller涕烧,以前我對(duì)這部分的職能了解的并不是很清楚月而,現(xiàn)在我開始略有體會(huì)了,Controller代表的是控制當(dāng)前模塊在不同的時(shí)刻所進(jìn)行的操作议纯,比如父款,Controller對(duì)象里一般都會(huì)有init方法、bindEvents方法和bindEventHub方法瞻凤。init方法意思就是在模塊初始化的時(shí)候憨攒,需要做些什么,因此我們會(huì)在init方法里面初始化view阀参、初始化model肝集,進(jìn)行事件綁定,進(jìn)行事件發(fā)布訂閱中心的事件訂閱等等蛛壳,這些就是我們?cè)谀K初始化時(shí)要做的事情杏瞻。然后在元素觸發(fā)事件時(shí)模塊需要做什么所刀,在其他模塊發(fā)布事件后模塊需要做什么,都分別反映在了Controller的bindEvents方法和bindEventHub方法中伐憾,因此Controller就像一個(gè)控制塔勉痴,有條不紊地在合適的時(shí)候處理著合適的事情,是統(tǒng)籌Model和View的中心树肃。
????以下是一個(gè)簡(jiǎn)單的Controller對(duì)象的代碼例子:

let controller={
    init(view,model){
        this.view=view
        this.model=model
        this.bindEvents()
        this.bindEventHub()
    },
    bindEvents(){......},
    bindEventHub(){......}
}

????總的來(lái)說(shuō)蒸矛,MVC就是一種代碼的組織思想,View代表功能區(qū)視圖管理著與直觀內(nèi)容有關(guān)的變化胸嘴,Model則作為數(shù)據(jù)中心管理著該視圖的所有數(shù)據(jù)雏掠,Controller則作為控制中心管控著View和Model的運(yùn)作時(shí)機(jī)和運(yùn)作方式。
????相信你看完以上我對(duì)模塊化和MVC的理解之后劣像,會(huì)幫助你更好地梳理接下來(lái)我要介紹的音樂(lè)播放器的思路乡话。因?yàn)檫@個(gè)應(yīng)用涉及的代碼很多,所以我只能介紹重要的思路耳奕,以及會(huì)在最后說(shuō)一下在制作過(guò)程中遇到的幾個(gè)坑以及解決這個(gè)坑的思路的做法绑青。

網(wǎng)易云音樂(lè)的制作思路

????當(dāng)你有了制作某個(gè)應(yīng)用的想法,你第一件要做的事情是什么屋群,不是直接寫代碼闸婴,而是分析這個(gè)應(yīng)用,我們可以通過(guò)以下三個(gè)圖例來(lái)進(jìn)行分析:
????1.用例圖(use cases)
????分析當(dāng)你身為用戶或者應(yīng)用管理員的時(shí)候芍躏,使用應(yīng)用的時(shí)候需要什么的頁(yè)面邪乍,頁(yè)面需要怎么樣的功能,這就是用例圖會(huì)表達(dá)出來(lái)的內(nèi)容对竣。
????例如音樂(lè)播放器這個(gè)應(yīng)用庇楞,身為普通用戶的話,我們可以查看首頁(yè)否纬、查看歌單頁(yè)和歌曲頁(yè)吕晌,歌曲頁(yè)里面可以聽歌、可以暫停以及可以查看歌詞临燃,我們還可以搜歌聂使,可以搜歌來(lái)搜出歌手和歌曲名等等。
????通過(guò)這些分析谬俄,你就會(huì)了解到你當(dāng)前要制作的這個(gè)應(yīng)用,他需要怎么樣的功能以及每個(gè)功能應(yīng)該出現(xiàn)在哪一個(gè)頁(yè)面當(dāng)中弃理。
????2.線框圖(也叫草圖溃论,stretch)
????線框圖要展示的,就是你要制作的應(yīng)用中痘昌,每個(gè)頁(yè)面功能區(qū)的布局钥勋,也就是線框圖會(huì)告訴你這個(gè)應(yīng)用含有多少個(gè)頁(yè)面炬转,每個(gè)頁(yè)面里有著哪些功能區(qū),以及功能區(qū)的大體位置也能在上面體現(xiàn)出來(lái)算灸。
????3.系統(tǒng)架構(gòu)圖
????系統(tǒng)架構(gòu)圖展示的是在該應(yīng)用中扼劈,前端頁(yè)面、后端頁(yè)面以及數(shù)據(jù)庫(kù)中使用的是什么工具菲驴,例如音樂(lè)播放器中荐吵,前端頁(yè)面使用的是jQuery,后端頁(yè)面使用的是LeanCloud提供的API赊瞬,數(shù)據(jù)庫(kù)使用的是LeanCloud和七牛先煎,以及這三者之前的交互方式,例如前端頁(yè)面和后端頁(yè)面的交互方式是通過(guò)AJAX來(lái)進(jìn)行的巧涧。


????好了薯蝎,進(jìn)行完了上面的分析,我們對(duì)這個(gè)音樂(lè)播放器的應(yīng)用就有了大概的認(rèn)識(shí)谤绳,作為普通用戶和管理員兩種不同的角色占锯,我們應(yīng)當(dāng)設(shè)計(jì)兩個(gè)頁(yè)面,管理頁(yè)面供管理員去管理音樂(lè)播放器中的音樂(lè)信息缩筛,管理頁(yè)面應(yīng)當(dāng)提供上傳歌曲消略、編輯歌曲以及刪除歌曲的功能,每首歌曲管理員應(yīng)當(dāng)有權(quán)限去設(shè)置歌曲的歌名歪脏、歌手疑俭、封面、歌曲鏈接以及歌詞信息婿失,這樣钞艇,管理員就能通過(guò)這個(gè)頁(yè)面去管理用戶頁(yè)面中展示的歌曲了。管理頁(yè)面具體要如何實(shí)現(xiàn)豪硅,我在這里就不具體敘述了哩照,只需你熟練掌握MVC的基本操作,然后能夠讀懂七牛文檔以及LeanCloud文檔后使用相關(guān)的API懒浮,就可以輕松地把這個(gè)后臺(tái)管理頁(yè)面做出來(lái)了飘弧。這里給大家展示一下一個(gè)最丑陋的后臺(tái)管理系統(tǒng)以及它的模塊化劃分:

音樂(lè)播放器后臺(tái)管理頁(yè)面.png



????那么用戶呢,用戶頁(yè)面要怎么設(shè)計(jì)和制作呢砚著,準(zhǔn)確來(lái)說(shuō)次伶,用戶頁(yè)面應(yīng)該有三個(gè):音樂(lè)播放器首頁(yè)、歌單頁(yè)稽穆、歌曲播放頁(yè)冠王,但這次應(yīng)用因?yàn)闀r(shí)間沖忙,因此沒有制作歌單頁(yè)舌镶,所以我們把關(guān)注點(diǎn)放在首頁(yè)和歌曲播放頁(yè)就好柱彻,首先應(yīng)該首頁(yè)應(yīng)該有如下功能:歌曲名和歌手名字的展示豪娜,歌單名和封面的展示,這些內(nèi)容全都通過(guò)LeanCloud的API來(lái)獲取即可哟楷,因此也不詳細(xì)地去說(shuō)了瘤载。
????除了首頁(yè),還有一個(gè)歌曲播放頁(yè)卖擅,這個(gè)頁(yè)面的話設(shè)計(jì)到歌曲的封面鸣奔,歌詞,歌名磨镶。我來(lái)考讀者一個(gè)問(wèn)題溃蔫,這個(gè)歌曲播放頁(yè)如何才能獲取到這些數(shù)據(jù)和信息呢?如果你想的是在LeanCloud數(shù)據(jù)庫(kù)里遍歷來(lái)查找那就不對(duì)了琳猫,正確的做法應(yīng)該是伟叛,用戶在首頁(yè)中點(diǎn)擊了想聽的歌曲,之后調(diào)整到歌曲播放頁(yè)面脐嫂,把該頁(yè)面的url后面的查詢參數(shù)設(shè)置成你點(diǎn)擊的歌曲的ID统刮,那么我們?cè)诓シ鸥枨?yè)面中只需要通過(guò)捕獲url上面的這個(gè)查詢參數(shù),即可獲得該歌曲的ID账千,之后再用這個(gè)ID在LeanCloud上獲取對(duì)應(yīng)的數(shù)據(jù)展示在頁(yè)面即可侥蒙,這樣歌曲的封面、歌詞匀奏、歌名以及歌手等全部信息我們都能獲得得到鞭衩。
????關(guān)于音樂(lè)播放器的樣式問(wèn)題,這是需要讀者自己去花時(shí)間去尋找優(yōu)秀的設(shè)計(jì)模板娃善,并進(jìn)寫模仿论衍、修改和編寫才能得到的內(nèi)容,因此就不在這里進(jìn)行闡述了聚磺。
????目前我所制作的樣式效果大致如下:
音樂(lè)播放器首頁(yè).png

歌曲播放頁(yè)面.png



????關(guān)于歌單頁(yè)面的構(gòu)想:
????歌單頁(yè)面由于時(shí)間不夠充裕的關(guān)系坯台,因此沒有去進(jìn)行制作,但是我在這邊是有我自己的構(gòu)想的瘫寝,首先要制作歌單頁(yè)面首先你得有一個(gè)對(duì)應(yīng)的歌單后臺(tái)管理頁(yè)面蜒蕾,這個(gè)才是歌單頁(yè)面的重點(diǎn),歌單頁(yè)面只需拿到歌單的ID焕阿,就可以在LeanCloud獲取到對(duì)應(yīng)的歌單信息了咪啡。因此怎么給歌單錄入信息,也就是怎么設(shè)計(jì)歌單的后臺(tái)管理頁(yè)面才是重點(diǎn)暮屡。因此我覺得首先由于應(yīng)用的限制瑟匆,我們可以限定僅有六個(gè)歌單,只需反復(fù)對(duì)這些歌單進(jìn)行編輯即可,也就是說(shuō)這樣刪除了歌單的添加和刪減功能愁溜,簡(jiǎn)化了歌單管理頁(yè)面,而在歌單管理頁(yè)面中外厂,我們僅需要進(jìn)行的操作冕象,就是創(chuàng)建一個(gè)歌曲列表,列表里是目前數(shù)據(jù)庫(kù)中已上傳的歌曲汁蝶,管理員可以對(duì)這些歌曲進(jìn)行選擇渐扮,之后把選擇了的歌曲添加到對(duì)應(yīng)的歌單即可。之后再設(shè)置好歌單的標(biāo)題掖棉、封面和描述墓律,就可以完成對(duì)一個(gè)歌單的管理了。關(guān)于歌單頁(yè)幔亥,之后有時(shí)間我會(huì)一并補(bǔ)充到自己的播放器中耻讽,敬請(qǐng)期待吧。


????最后想說(shuō)一下在這次作品的制作中遇到的一些坑帕棉,以及解決這些坑的辦法:
????1.由于使用了移動(dòng)端不支持的ES6語(yǔ)法導(dǎo)致的BUG
????在進(jìn)行音樂(lè)作品播放器的制作過(guò)程中针肥,我在一些地方使用了ES6的新語(yǔ)法...,這個(gè)語(yǔ)法的表示的是當(dāng)前對(duì)象的所有屬性香伴,如:

let attributes={name:"xzb",age:18}
let obj={id:1,...attributes}
console.log(obj) // {id:1,name:"xzb",age:18}

????這個(gè)語(yǔ)法真的相當(dāng)方便慰枕,但是當(dāng)你在移動(dòng)端使用它的時(shí)候,悲劇了....語(yǔ)法錯(cuò)誤即纲,移動(dòng)端不支持它吖>甙铩!低斋!
????后面只能使用Object.assign方法來(lái)代替它了蜂厅。

????解決辦法:使用Object.assign()


????2.無(wú)法對(duì)移動(dòng)端進(jìn)行調(diào)試
????第二個(gè)坑是由第一個(gè)坑衍生出來(lái)的,在發(fā)現(xiàn)第一個(gè)坑之后拔稳,我的第一個(gè)反應(yīng)是葛峻,十分無(wú)奈,為什么這么說(shuō)呢巴比?哥术奖,你在PC端出錯(cuò),我還能通過(guò)控制臺(tái)來(lái)看看出錯(cuò)的地方在哪轻绞,你在移動(dòng)端出錯(cuò)采记,我.....
????好吧,只能靠萬(wàn)能的互聯(lián)網(wǎng)了政勃,在一番資料的查詢之后唧龄,我得到了想要的解決辦法,有以下四個(gè):
????(1)通過(guò)alert()來(lái)進(jìn)行檢驗(yàn)
????雖然說(shuō)移動(dòng)端沒有控制臺(tái)奸远,但移動(dòng)端還是可以alert的吖既棺,因此我們只要在我們認(rèn)為出錯(cuò)的地方的前后進(jìn)行alert()讽挟,若發(fā)現(xiàn)前面的alert運(yùn)行了,后面的alert沒有運(yùn)行丸冕,那么恭喜你耽梅,你的猜測(cè)是正確的,出錯(cuò)的地方就是此處胖烛。通過(guò)這種辦法我們就可以在移動(dòng)端知道自己出錯(cuò)的地方了眼姐。
????(2)通過(guò)全局的onerror來(lái)進(jìn)行檢驗(yàn)
????通過(guò)第一種方法我們的確可以在不斷的嘗試下知道出錯(cuò)的地方,但是這樣效率太低下了佩番,于是我們有第二種辦法众旗,通過(guò)監(jiān)聽全局的error來(lái)顯示錯(cuò)誤,以及顯示錯(cuò)誤的出處趟畏。代碼如下:

<script>
    window.onerror=function(message,file,row){
        alert(message,file,row)
    }
</script>

????onerror接受四個(gè)參數(shù),第一個(gè)是出錯(cuò)信息拱镐,第二個(gè)出錯(cuò)文件艘款,第三個(gè)是出錯(cuò)的行數(shù),第四個(gè)是出錯(cuò)的列數(shù)沃琅,由于列數(shù)在此處對(duì)我沒什么太大的作用哗咆,因此在上述代碼中我把它省略了。
????(3)自己手寫一個(gè)console函數(shù)法
????自己在頁(yè)面上寫一塊console的區(qū)域益眉,然后把console的值直接顯示在區(qū)域內(nèi)即可晌柬,具體代碼如下:

<div id="consoleOutput" style="......"></div>
<script>
    window.console={
        log(x){
            let p=document.createElement('p')
            p.innerText=x
            consoleOutput.appendChild('p')
        }
    }
</script>

????(4)直接引入騰訊制作的vConsole庫(kù)
????直接引入騰訊制作的vConsole庫(kù),就可以在移動(dòng)端擁有一個(gè)console了郭脂,但是需要記住在調(diào)試完之后記得刪掉這些調(diào)試工具年碘,以免出現(xiàn)在用戶使用的頁(yè)面中。


????3.由于IOS的移動(dòng)端不支持animation-play-state語(yǔ)句而導(dǎo)致的BUG
????在我對(duì)移動(dòng)端中的所有報(bào)錯(cuò)都進(jìn)行了修復(fù)之后展鸡,我在歌曲播放頁(yè)面又發(fā)現(xiàn)了一個(gè)新的BUG屿衅,那就是在點(diǎn)擊光盤進(jìn)行播放的時(shí)候,光盤沒有如我代碼所寫那樣進(jìn)行播放莹弊,百思不得其解之下涤久,我發(fā)現(xiàn)網(wǎng)上有許多人和我出現(xiàn)了類似的BUG,于是乎我就去尋找出現(xiàn)這種現(xiàn)象的原因忍弛,以及解決的辦法响迂,最后我發(fā)現(xiàn)原來(lái)是IOS不支持animation-play-state語(yǔ)句而導(dǎo)致的,而在安卓的移動(dòng)端上則不會(huì)出現(xiàn)這樣的BUG细疚。
????如何是好蔗彤,沒有了animation-play-state,我就無(wú)法去控制CSS3動(dòng)畫的播放和暫停,如果單純的用animation:none;來(lái)控制然遏,就會(huì)出現(xiàn)動(dòng)畫每次都重頭開始進(jìn)行的錯(cuò)誤效果贫途,后來(lái)我也嘗試了animation-fill-mode: forwards;來(lái)嘗試讓動(dòng)畫每次停在最后的狀態(tài),但由于歌曲的暫停是隨機(jī)的啦鸣,而不是由動(dòng)畫是否播放完畢來(lái)決定是否暫停的潮饱,因此這個(gè)方法也是行不通的,怎么辦好诫给。我不斷的嘗試,不斷地搜索資料啦扬,最后我看到了一個(gè)網(wǎng)上的解決方案:給光盤所在元素添加一個(gè)父元素中狂,當(dāng)每次點(diǎn)擊光盤暫停歌曲播放時(shí),用父元素記錄一下光盤每次暫停時(shí)transform的值扑毡,并讓父元素的transform也等于這個(gè)值胃榕,若transform本來(lái)就有值,那就在transform后面更新這個(gè)值瞄摊,就可以完成歌曲暫停勋又,光盤動(dòng)畫暫停,歌曲繼續(xù)開始换帜,光盤動(dòng)畫繼續(xù)開始的效果楔壤。
????具體的實(shí)現(xiàn)代碼如下:

recordTransform(){
    let coverTransform=this.view.$el.find('.coverWrapper').css('transform')
    let coverWrapperTransform=this.view.$el.find('.coverWrapperParent').css('transform')
    let transformDeg=coverWrapperTransform==='none'?coverTransform:coverTransform.concat(' ',coverWrapperTransform)
    this.view.$el.find('.coverWrapperParent').css('transform',transformDeg)
}



????4.由于IOS微信不支持webp格式圖片所引起的BUG
????由于我的音樂(lè)播放器中的歌單用的是webp文件的封面圖片,這個(gè)格式的圖片是谷歌開發(fā)的一種旨在加快圖片加載速度的圖片格式惯驼。WebP 的優(yōu)勢(shì)體現(xiàn)在它具有更優(yōu)的圖像數(shù)據(jù)壓縮算法蹲嚣,能帶來(lái)更小的圖片體積,而且擁有肉眼識(shí)別無(wú)差異的圖像質(zhì)量祟牲;同時(shí)具備了無(wú)損和有損的壓縮模式隙畜、Alpha 透明以及動(dòng)畫的特性,在 JPEG 和 PNG 上的轉(zhuǎn)化效果都相當(dāng)優(yōu)秀说贝、穩(wěn)定和統(tǒng)一议惰。
????可惜IOS上的微信就是不支持這種格式的圖片,因此沒有辦法乡恕,我最后解決這個(gè)BUG的方案就是把webp圖片全部轉(zhuǎn)換成了JPG然后重新上傳至應(yīng)用中言询。
????解決辦法:更換應(yīng)用圖片格式


????好了,寫了那么多几颜,終于算是介紹完了如何仿照網(wǎng)易云音樂(lè)自制一個(gè)音樂(lè)網(wǎng)頁(yè)播放器倍试,當(dāng)我做完這個(gè)應(yīng)用的時(shí)候,我覺得自己對(duì)MVC的理解和使用都更為熟練了蛋哭,接下來(lái)我會(huì)專心地研究和Vue相關(guān)的應(yīng)用县习,并繼續(xù)給大家?guī)?lái)完成后的心得和感想,希望能對(duì)你們有所幫助~


????最后的最后,說(shuō)一下目前打算寫但還沒寫的兩篇博客:(1)JSONP的安全問(wèn)題你了解過(guò)嗎躁愿?(2)Cookie叛本、Session、localStorage彤钟、sessionStorage来候、Cache-Control、Expires以及ETag是什么逸雹?



本教程版權(quán)歸宣澤彬所有营搅,轉(zhuǎn)載須說(shuō)明來(lái)源

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市梆砸,隨后出現(xiàn)的幾起案子转质,更是在濱河造成了極大的恐慌,老刑警劉巖帖世,帶你破解...
    沈念sama閱讀 206,214評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件休蟹,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡日矫,警方通過(guò)查閱死者的電腦和手機(jī)赂弓,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)哪轿,“玉大人盈魁,你說(shuō)我怎么就攤上這事〉薰洌” “怎么了备埃?”我有些...
    開封第一講書人閱讀 152,543評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)褐奴。 經(jīng)常有香客問(wèn)我按脚,道長(zhǎng),這世上最難降的妖魔是什么敦冬? 我笑而不...
    開封第一講書人閱讀 55,221評(píng)論 1 279
  • 正文 為了忘掉前任辅搬,我火速辦了婚禮,結(jié)果婚禮上脖旱,老公的妹妹穿的比我還像新娘堪遂。我一直安慰自己,他們只是感情好萌庆,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評(píng)論 5 371
  • 文/花漫 我一把揭開白布溶褪。 她就那樣靜靜地躺著,像睡著了一般践险。 火紅的嫁衣襯著肌膚如雪猿妈。 梳的紋絲不亂的頭發(fā)上吹菱,一...
    開封第一講書人閱讀 49,007評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音彭则,去河邊找鬼鳍刷。 笑死,一個(gè)胖子當(dāng)著我的面吹牛俯抖,可吹牛的內(nèi)容都是我干的输瓜。 我是一名探鬼主播,決...
    沈念sama閱讀 38,313評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼芬萍,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼尤揣!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起柬祠,我...
    開封第一講書人閱讀 36,956評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤芹缔,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后瓶盛,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,441評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡示罗,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評(píng)論 2 323
  • 正文 我和宋清朗相戀三年惩猫,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蚜点。...
    茶點(diǎn)故事閱讀 38,018評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡轧房,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出绍绘,到底是詐尸還是另有隱情奶镶,我是刑警寧澤,帶...
    沈念sama閱讀 33,685評(píng)論 4 322
  • 正文 年R本政府宣布陪拘,位于F島的核電站厂镇,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏左刽。R本人自食惡果不足惜捺信,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望欠痴。 院中可真熱鬧迄靠,春花似錦、人聲如沸喇辽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)菩咨。三九已至吠式,卻和暖如春陡厘,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背奇徒。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工雏亚, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人摩钙。 一個(gè)月前我還...
    沈念sama閱讀 45,467評(píng)論 2 352
  • 正文 我出身青樓罢低,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親胖笛。 傳聞我的和親對(duì)象是個(gè)殘疾皇子网持,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容