在不久前結(jié)束的 Google I/O 大會上,Google 宣傳公司將從以 "Mobile-first" 過渡到以 "AI-first" 為主旨的產(chǎn)品研發(fā)。并且在大會中還介紹了由 Google 實(shí)驗(yàn)室團(tuán)隊(duì)開發(fā)的一款基于機(jī)器學(xué)習(xí)的 Auto Draw 工具。該工具是基于用戶的涂鴉經(jīng)過機(jī)器學(xué)習(xí)處理后,推斷出用戶想要畫的圖像,是一款很好玩并且很使用的工具。只不過基于國內(nèi)的網(wǎng)絡(luò)環(huán)境是無法訪問直接訪問 Auto Draw 的網(wǎng)站的,必須借助于“梯子”才可以訪問到。為了可以讓國內(nèi)更多的用戶可以感受一下,Google 基于機(jī)器學(xué)習(xí)開發(fā)的 Auto Draw。故有了將其移植到小程序上的想法。下面將會詳細(xì)的講解,我是如何將 Google Auto Draw 移植到小程序上的。了解微信小程序
既然是要把 Auto Draw 移植到小程序上,那首要任務(wù)就是要了解小程序開發(fā)平臺及相關(guān)的開發(fā)文檔。在這里推薦一個(gè)小程序的官方 Demo,此 Demo 詳細(xì)的講解了微信小程序中各組件的使用方法,結(jié)合著開發(fā)文檔再對照著此 Demo,就很容易掌握小程序整體的開發(fā)流程。
微信小程序有專門的官方開發(fā)工具,使用開發(fā)工具建立項(xiàng)目會就可以基于生成的模板進(jìn)行相應(yīng)的業(yè)務(wù)邏輯開發(fā)。文件結(jié)構(gòu)
小程序包含一個(gè)描述整體程序的 app 和多個(gè)描述各自頁面的 page。一個(gè)小程序主體部分由三個(gè)文件組成,必須放在項(xiàng)目的根目錄,如下:
文件 | 必填 | 作用 |
---|---|---|
app.js | 是 | 小程序邏輯 |
app.json | 是 | 小程序公共設(shè)置 |
app.wxss | 否 | 小程序公共樣式表 |
一個(gè)小程序頁面由四個(gè)文件組成,分別是:
文件 | 必填 | 作用 |
---|---|---|
js | 是 | 頁面邏輯 |
wxml | 是 | 頁面結(jié)構(gòu) |
wxss | 否 | 頁面樣式表 |
json | 否 | 頁面配置 |
因?yàn)楸救酥耙恢睆氖碌氖?Android 開發(fā),看到小程序的文件結(jié)構(gòu)的時(shí)候,將其與 Android 的文件結(jié)構(gòu)進(jìn)行了對比,發(fā)現(xiàn)這兩者的文件結(jié)構(gòu)其實(shí)是很相似的。
熟悉 Android 開發(fā)的應(yīng)該也能看得出來, app.js 類似于 Android 中的 Application,是一個(gè)默認(rèn)啟動的全局變量。app.json 則可以看作是 AndroidManifest 一些跟頁面相關(guān)的配置需要在這里進(jìn)行配置。而 app.wxss 可以看作是 Android Resource 中的 style,通用組件的屬性可以放在這里。
小程序的頁面文件組成中,js 可以看作 Android 中的 Activity 用于處理頁面邏輯。wxml 則相當(dāng)于 layout 用于對頁面進(jìn)行布局。wxss 同樣可以看作是 style 只不過其作用范圍只限于此頁面。json 可以看作是 AndroidManifest 中的
不知道這樣的解釋是否可以讓熟悉 Android 開發(fā)的小伙伴們,對理解小程序的文件結(jié)構(gòu)更容易一些。調(diào)試 Google Auto Draw
在使用 Google Auto Draw 時(shí), 就考慮既然是會將用戶的涂鴉交由機(jī)器學(xué)習(xí)進(jìn)行學(xué)習(xí),那應(yīng)該是通過調(diào)用 API 接口來實(shí)現(xiàn)的。通過使用 Chrome 的 Inspect 調(diào)試后,然后果然如猜測的一樣找到了請求的 API,如下圖所示
可以看到當(dāng)用戶在畫板上結(jié)束繪畫之后,就會向 https://inputtools.google.com/request?ime=handwriting&app=autodraw&dbg=1&cs=1&oe=UTF-8 發(fā)送一個(gè) POST 請求,并將用戶在畫板上繪制的座標(biāo),即上圖Request Payload 部分通過 application/json 的方式傳遞給后臺服務(wù)器,然后后臺服務(wù)器經(jīng)過機(jī)器學(xué)習(xí)的處理后,將預(yù)測的結(jié)構(gòu)返回回來,如下圖所示
通過返回的 Response 可以明白,Auto Draw 將用戶涂鴉后的圖像經(jīng)過機(jī)器學(xué)習(xí)處理后,是轉(zhuǎn)化為了圖像可能所對應(yīng)的英語單詞,而不是直接畫出推測的圖像。這不禁讓我聯(lián)想到了 Google 實(shí)驗(yàn)室更早些的時(shí)候推出的 Quick Draw, 就是根據(jù)用戶的涂鴉,機(jī)器學(xué)習(xí)以英語單詞的形式來推算你畫的是什么。我接著對 Quick Draw 用相同的方法進(jìn)行了調(diào)試,果然后臺調(diào)用的 API 是一模一樣的。原來 Auto Draw 是基于 Quick Draw 進(jìn)行的開發(fā)。
已經(jīng)知道了機(jī)器學(xué)習(xí)是先將用戶的涂鴉轉(zhuǎn)化為推測的英語單詞,那么接下來的問題則需要搞清楚 Auto Draw 是如何將這些英語單詞轉(zhuǎn)變成圖像的。
繼續(xù)調(diào)試不難發(fā)現(xiàn),Auto Draw 在第一次加載的時(shí)候還會調(diào)用一個(gè) GET 的請求,如下圖所示
Auto Draw 在第一次加載的時(shí)候會發(fā)送向 https://www.autodraw.com/assets/stencils.json 發(fā)送一個(gè) GET 請求。那這個(gè)請求又返回了什么呢?
啊哈!查看請求的 Response 的就會發(fā)現(xiàn)這是一個(gè)英語單詞及單詞所對應(yīng)存放在 Google storage 上圖像的 JSON 集合。原來Auto Draw 是通過這個(gè) JSON 集合,實(shí)現(xiàn)了英語單詞到圖像的轉(zhuǎn)化。通過調(diào)試,Auto Draw 整體的一個(gè)核心 API 調(diào)用流程就很清楚了。
以上就是根據(jù)調(diào)試,得到的 Auto Draw 的時(shí)序圖。開發(fā)中的坑
通過上面的調(diào)試已經(jīng)摸清楚了 Auto Draw 的調(diào)用流程。那下面就可以進(jìn)入到實(shí)戰(zhàn)的開發(fā)階段了。但是沒想到高興的太早了,實(shí)際在開發(fā)當(dāng)中遇到了很多的坑,下面就來講講遇到了哪些坑,又是如何把坑給填平的。小程序開發(fā)文檔簡陋
目前微信小程序的開發(fā)文檔還是過于的簡陋,好多在實(shí)際開發(fā)中很重要的點(diǎn),文檔都沒有涉及到。
例如,在 SKetch 里要給小程序做設(shè)計(jì)的時(shí)候,應(yīng)該基于什么樣的分辨率的畫板下,文檔中并沒有很好的涉及到。
還有我在開發(fā)當(dāng)中想自定義 button 的邊框,于是在 WXSS 當(dāng)中為 button 添加了如下的屬性
border:1px solid rgba(0, 0, 0, 0.2);
但實(shí)際效果會邊框出現(xiàn)兩條線,自定義的邊框只是在默認(rèn)邊框上進(jìn)行了繪制,默認(rèn)邊框并沒有消失,很是難看,button 的自定義問題在開發(fā)文檔中一點(diǎn)都沒有提及到。
幸虧騰訊前端工程師在知乎上的《有用!關(guān)于微信小程序,那些開發(fā)文檔沒有告訴你的》這篇文章拯救了我。強(qiáng)烈推薦想開發(fā)小程序的小伙伴再看了開發(fā)文檔之后,一定要閱讀這篇文章。
微信小程序的坑還不止這些,但是相信隨著微信團(tuán)隊(duì)的不斷維護(hù),微信小程序會越來越趨向成熟穩(wěn)定。服務(wù)器域名
文中最開始已經(jīng)提到了,想將 Auto Draw 移植到小程序,是因?yàn)閲鴥?nèi)訪問 Auto Draw 會收到各種的限制。最初的想法是將小程序的網(wǎng)絡(luò)請求先經(jīng)過我在國外的 VPS,然后轉(zhuǎn)發(fā)給 Google 的服務(wù)器,變相的繞過了攔截??墒窃诳戳诵〕绦虻拈_發(fā)文檔后,發(fā)現(xiàn)微信對小程序可以訪問的網(wǎng)絡(luò)請求擁有很嚴(yán)格的限制,必須是 HTTPS 和備案過的域名才可以。
支持 HTTPS 還好說現(xiàn)在有好多免費(fèi)辦法證書的機(jī)構(gòu),但是必須是備案過的域名確實(shí)難搞。備案需要準(zhǔn)備相應(yīng)文件和差不多一周的審核時(shí)間,而且我這還涉及到了訪問 Google 的服務(wù)??吹轿⑿判〕绦虻倪@些限制后,讓我一度有了這項(xiàng)目做不了的想法。
幸虧天無絕人之路,我突然想到之前開發(fā)手機(jī) App 經(jīng)常用到 BaaS 提供商 LeanCloud。LeanCloud 不光有支持 HTTPS 和備案過的域名,而且它們還有一個(gè)云引擎服務(wù)。
云引擎是 LeanCloud 推出的服務(wù)端托管平臺。提供了多種運(yùn)行環(huán)境(Node.js, Python 等)來運(yùn)行服務(wù)端程序。需要提供服務(wù)端的業(yè)務(wù)邏輯(網(wǎng)站或云函數(shù)等),而服務(wù)端的多實(shí)例負(fù)載均衡,不中斷服務(wù)的平滑升級等都由云引擎提供支持。
簡單的講,你可以把你寫的腳本或者后臺程序放在 LeanCloud 提供的云平臺。更重要的是 LeanCloud 有國內(nèi)和美國兩個(gè)節(jié)點(diǎn),美國的節(jié)點(diǎn)可以暢通無阻的直接訪問 Google 服務(wù)。這完全符合我的需求,簡直就是量身定做。哈哈哈
在 LeanCloud 的開發(fā)文檔中果然發(fā)現(xiàn)了支持微信小程序的文檔。文檔比較詳細(xì),反正比微信小程序的官方文檔是要好很多,哈哈。
根據(jù)開發(fā)文檔我講微信小程序的服務(wù)器域名配置如下
request合法域名 https://api.bmob.cn https://api.leancloud.cn https://app-router.leancloud.cn https://router-g0-push.leancloud.cn https://vcn64yge.api.lncld.net https://vcn64yge.engine.lncld.net https://us-api.leancloud.cn https://router-a0-push.leancloud.cn https://storage.googleapis.com
socket合法域名 wss://api.bmob.cn wss://cn-n1-cell1.leancloud.cn wss://cn-n1-cell2.leancloud.cn wss://cn-n1-cell5.leancloud.cn wss://cn-n1-cell7.leancloud.cn
uploadFile合法域名 https://api.bmob.cn https://up.qbox.me
downloadFile合法域名 https://api.bmob.cn https://dn-vCn64yGe.qbox.me
以上是 LeanCloud 國內(nèi)和美國站點(diǎn)的服務(wù)器域名,因?yàn)槲⑿艑π〕绦蛐薷姆?wù)器域名每個(gè)月有次數(shù)限制,故建議一次性都寫進(jìn)去,不管是否會用的著。
關(guān)于如何使用 LeanCloud 的云引擎,官方文檔已經(jīng)介紹的很詳細(xì),這里就不再重復(fù)。關(guān)于 Auto Draw 小程序 LeanCloud 云引擎的腳本,可以在這里查看。
解決了域名和 HTTPS 的問題,剩下的就是愉快寫代碼了~開源相關(guān)
最后附上 Auto Draw 移植到小程序上的二維碼,感興趣的小伙伴可以掃描玩玩~