Pymaster

文章推薦指數: 80 %
投票人數:10人

... 與https://pymaster.tw 同步發文; 除了前端專題,可能會再開一個動畫心得專題 ... 歲末年終,一起來幫你家D3瘦身吧!December20,2019最近某專案弄完上線之後,因為想要加快FirstMeaningfulPaint的速度,開始調查有沒有甚麼可以改進的地方。

看著看著就看到博大精深(超大包)的D3 其實也不過就是gzip後74.7KB嘛… 本文的終極目標就是希望針對自己的需求,能夠幫D3瘦身一下。

不想再聽到瀏覽器的悲鳴了! D3為何大包 是這樣的,其實D3是一個包羅萬象的超強library,不能單純的把它定位成「一個畫圖的library」。

官方介紹如下: D3.jsisaJavaScriptlibraryformanipulatingdocumentsbasedondata.D3helpsyoubringdatatolifeusingHTML,SVG,andCSS.D3’semphasisonwebstandardsgivesyouthefullcapabilitiesofmodernbrowserswithouttyingyourselftoaproprietaryframework,combiningpowerfulvisualizationcomponentsandadata-drivenapproachtoDOMmanipulation. 如果你也實際用過D3,就會瞭解D3的強大之處在於它對資料數據->圖像數字的處裡非常有一套,我這邊也不說太多,如果想深入一點瞭解D3,可以參考幾乎每年都有人寫的鐵人賽系列文章: D3.js新手開發基本圖表系列 React+D3的正確姿勢-Day13 我是不太推薦完整閱讀「Reac/Vue+D3」的這類型的系列。

以想學D3的角度來看,介紹React/Vue的部分感覺沒什麼卵用,想要讀的話,可以只看其中D3的部分就好囉! 而D3本身其實被切分為非常多的package,依據使用情況的不同,會用上不同package的功能,一樣推薦一個非常優質的D3教學網頁: IntrotoD3 好的,簡單來說就是如果你照官網寫的起手式 就會把上面gif裡面所有的package全部載入網頁裡,這樣做會影響我們FMP的點有兩個: 因為比較大包,需要額外的下載時間 因為比較大包,瀏覽器載入這段code會花比較多時間 那麼接下來就來幫它瘦身吧! 瘦身123 首先,這次的專案本身是一個Gatsby網站,也就是說我們有強力的webpackbundler做後盾。

我們可以透過webpack包出一個只有我們需要的功能的D3object。

首先需要檢視我們到底用了哪些D3的package裡的功能,先看一眼網站內的效果: 用到的package如下: d3-selection基本選取操作工具,這是必備的 d3-transition看到動畫表示有用到 d3-ease看到比較炫砲的動畫表示有用到:特殊timingfunction的transition總是會炫砲一點 d3-interpolate看到比較炫砲的動畫表示有用到:有嘗試自訂interpolation表示對動畫比較有追求,通常也會呈現比較炫砲的效果 d3-shape看到複雜SVG圖形表示有用到:複雜SVG圖形指的是像圓餅圖的切片這種需要用才畫得出來的 當然,純看效果是沒有辦法100%兜出需要的package的,畢竟最懂用了什麼的人是寫這段code的我,所以上面這種純推論的伎倆其實是瞎掰的。

我是看code來找出用了哪一些package的,欸嘿థ౪థ 心法 一眼看出使用什麼package的大原則就是 對照一下d3.xxx()在D3APIReference的哪個package區塊裡面。

舉例來說,我們看一下這段code(可以不用嘗試理解它,隨便看看): constsvg=d3.select(elmRef.current).attrs({ width, height, viewBox:`00${width}${height}`, 'shape-rendering':'geomatricPrecision', }) constgroup=svg.append('g').attr('transform',()=>{ letx=width/2 lety=height/2 if(withDescription){ if(lang==='ja'){ x+=0.05*x }else{ x+=0.1*x } } return`translate(${x},${y})` }) constpieGenerator=d3.pie().value(d=>d.value.value) constdataReady=pieGenerator( _.orderBy(d3.entries(data),({value})=>value.value,'desc') ) constdurations=dataReady.map( d=>(d.endAngle-d.startAngle)*ANGLE_SPEED ) constdelays=durations.map((t,i)=>{ if(i===0){ return0 } return_.sum(_.slice(durations,0,i)) }) constarcGenerator=d3 .arc() .innerRadius(0) .outerRadius(radius) 套用大原則,可以用d3.xxx()對應出package: d3.select->d3-select d3.pie->d3-shape d3.entries->d3-collection d3.arc->d3-shape 然而事情往往沒有這麼簡單,D3鏈式操作的特性,使得其實有些package幾乎沒有用到d3.xxx()這種形式的呼叫,而是針對特定的物件(通常是selection)做prototype的擴充。

像D3APIReference#d3-transition就是一個很好的例子: 實際使用的時候大都是: d3.select(this) .transition() .ease(d3.easeLinear) .duration(duration) .delay(delay) 此時,儘管沒有用到d3.xxx()類的呼叫,還是需要記得打包要算上d3-transition。

場外加映一下d3-transition裡面是怎麼寫的: 經過一番嚴謹的判斷,我把有用到的部分重新export成一個d3: /*file:d3.js*/ export{select,selectAll}from'd3-selection' export{transition}from'd3-transition' export{ easeElasticOut, easeSinOut, easeBackOut, easeLinear, easeCubicOut, easeExpOut, }from'd3-ease' export{arc,pie}from'd3-shape' export{entries}from'd3-collection' export{interpolate,interpolateNumber}from'd3-interpolate' 最後再把原本從global抓的d3換成import這個自己打包的版本就好啦! 修羅場 只是打包完畢並不能夠滿足我們旺盛的好奇心。

跟應有盡有的版本相比,到底變小了多少呢!? 讓我們親手來比較看看吧! D3的d3/d3repository就是官方版打包用的repository,話不多說,馬上fork一個來打包。

Fork之後,小修改一下,在官方完整版之外加入我們的custom版本: 新增custom.js作為custombuild的進入點 新增一個rollup-custom.config.js 官方版是用rollup打包,比較適合打包library 修改npmscript的pretest,加入執行我們這個新的rollupconfig 最後執行 #安裝nodemodules yarn #開始bundle yarnpretest 然後我們就可以在dist資料夾裡面看到成果(方便視覺上比較,我把*.node.js砍了): 同時也來比較一下實際載入花的時間: 總結比較結果: 檔案大小差距242KBvs50KB->瘦身後,大小減少了約80% 執行時間差距58msvs16ms->瘦身後,載入library時間減少了約72% 後記 Update2020/05/05 過了一兩週馬上就懶了😎 是說最近我打算把方格子也加入我發表文章的平台。

畢竟我不喜歡大家一股腦往Medium發中文文章的模樣,如果不做點什麼來表現我堅定的立場,好像說不太過去。

這篇就是第一篇同步在方格子跟我的blog上架的文章。

考慮到方格子的向性,我也打算順便寫一些別的有的沒的(?),拓展一下寫文的觸角,看看有沒有什麼新的火花。

最近看了紫羅蘭永恆花園之後,深刻感受到文字的力量之大,同時也覺得沒辦法好好運用文字的自己有點可悲😢 稍微總結一下在方格子上的計畫: 與https://pymaster.tw同步發文 除了前端專題,可能會再開一個動畫心得專題 提高產文頻率,希望一週兩篇以上前端專題,動畫心得的話就看心情囉 希望往後我的文字能夠更加隨心所欲、Sincerely! 👉我的方格子個人頁面Chrome79-遲到了6年的rem/em修正December01,2019眼看Chrome79大概再兩周就要release啦! 對大多數人來說,這個也就是Chrome例行更新的一個版本。

而對我,Chrome79修正了一個最近一年多在我心裡佔有一席之地的bug,我曾經努力試著解決它,最後似乎也找到自己應對它的方法。

而現在它要被修掉了,多少有點感觸😥。

本文特別想趕在Chrome79正式釋出之前寫出來,讓在閱讀的你也可以一同經歷這個變化的過程。

話說從頭,可能會有點長,如果想直接看結論可以點這邊。

Chrome的「最小字體」傳說 我想小有接觸前端的人大概都知道Chrome有個最小字體是12px的傳說,然而時過境遷、滄海桑田,2019的現在還是如此嗎? 實際上現在再去Google“chromeminimumfontsize”得到的結果跟討論大都是2013年以前的內容,就算有稍微近期的文章,也大都是參考早期文章寫出來的。

從搜尋結果裡面可以找到這個issue: https://bugs.chromium.org/p/chromium/issues/detail?id=36429 裡面提到幾件重要的事情: Chrome預設的最小字體是和UI使用的語言有關的 大部分的UI語言預設最小字體是1px 複雜UI語言(多為亞洲語言)的預設最小字體是10px/12px 2010年時還沒有辦法從設定該改最小字體的設定 而到了2019的現在,最小字體已經可以從設定裡面更改了,位置就在「設定」->「自訂字型」。

可能很多人會是在看到這篇文章之後才第一次打開這個設定畫面,比對一下上面列出來的項目可以發現繁中UI的Chrome的最小字體預設值就是12px。

我猜如果從安裝時就是英文版UI,預設值應該會是0px/6px。

曾經是傳說的最小字體12px,僅限於某些UI語言(基本上就是中文、日文、韓文、泰文)的瀏覽器。

現在其實是使用者把它調低就可以解決的問題。

當然,對於開發者來說還是一個無法跨越的障礙。

做一個fiddle來測試一下「沒調設定」跟「調過設定」的結果:https://jsfiddle.net/pc035860/jgtfdL98/4/ Twitch聽說你是rem排版大師? 自從近年各瀏覽器對rem的支援度有提高之後,坊間出現一些使用rem為單位進行網頁排版的文章,並且漸漸也有些網站開始使用這種排版方法(雖然我覺得還是相對蠻少的)。

建議往下看之前要先瞭解一下用rem單位進行排版大概是怎麼樣進行,可以參考下面這篇sitepoint的文章 https://www.sitepoint.com/understanding-and-using-rem-units-in-css/ 普遍常見的起手式,是把rembase設為1px或10px,這樣一來直接使用rem單位換算的過程會簡單很多。

其中又以在上用font-size:62.5%來設定為10px最常見: html{ /*16*0.625=10*/ font-size:62.5%; } Twitch的大改版衝擊 Twitch在2018年2月左右做了一次重大改版,把原本用的Ember.js換成React,這一次改版同時也把網站的排版單位改為rem,而這也是我們繁中Chrome使用者的噩夢開端(好像講得有點誇張了)。

改版之後,原本頻道的資訊頁面變得非常奇怪。

下面示範截圖是目前最新版,當然也還是用rem單位排版。

正常來說應該是這樣: 改版後就直接跑掉: 這還只是第一眼就覺得不對勁的部分。

用Firefox打開Twitch來比較就可以看出整個網站都有點不一樣,Chrome整體似乎大了一號,這邊就單取側邊欄來對比: WTF!?不是,Twitch難道沒有測過嗎… Readon 週末長知識:Google的彈指特效小研究April28,2019隨著「復仇者聯盟:終局之戰」的上映,Google在和薩諾斯與無限手套相關的搜尋結果頁面加了一個灰飛煙滅的特效: 特效被發現後引起了各界熱烈的討論,所以這週末的長知識就來蹭個熱度,看一下灰飛煙滅的特效是如何完成的。

將元素轉換為圖片 其實這個特效很直覺就認為有用html2canvas,因為需要作出後續的類粒子特效,明顯需要是用圖片下去操作。

稍微用Chromedevtools追查一下之後就可以看到html2canvas的蹤跡: 粒子效果 如果在特效運作的時候觀察一下DOM的狀態,會發現似乎有大量的canvas被塞進來。

深入追查特效本體的區塊,不像一般的粒子特效會有比較多粒子相關的運算,Google這個特效的程式碼相對簡潔。

這個粒子效果其實是用一個比較平民的方法達成:用canvas層層疊+CSStransition。

在動畫進行中的Layerview截圖是長這樣: 層層疊的學問 已經知道了原理是層層疊起來,是不是後面就簡單了? 仔細看一下上面的動畫截圖,可以發現其實它是稍微有左->右這樣散開的傾向,而這點其實是需要靠一些巧思來達到的: 多層canvas分開負責由左至右的像素 用不同的transition-delay來讓動畫由左至右完成 為了粒子效果的隨機性,對原圖取樣的時候也要加入隨機成分 取樣的方法 取樣的方法一樣是從程式碼裡面挖出來: 對所有像素x,y: 重複n次: layer=隨機選出哪一層(x值越靠前,層數越靠前) 完整複製像素到layer 圖層疊起來一定可以拼出原本的圖 n可以控制視覺上的紮實度,Google取2看起來剛好 用此方法做一維取8層,大概會是像這樣: 幾層比較好? 看code可以發現canvas的數量就是32層,照上面的幾點推論下來,理論上層數越多看起來會越自然,當然也相對的越吃效能。

32層大概是他們權衡效果與效能之後取得的一個最佳數字。

效果重現 把Google的版本整理一下,並且讓層數變成可以設定的參數,歡迎大家玩看看不同層數的效果。

如果想要知道對原圖取樣的方法,這個版本的程式碼應該也比打亂過的原版好讀很多。

注意1:使用手機觀看的話,層數過高瀏覽器會直接crash 注意2:選用的html2canvas版本在Firefox上的繪製效果會有較大誤差,建議用其他瀏覽器觀看 後記 好久沒寫blog,這次回來寫有一種力不從心的懶散感Orz 再接再厲。

TGDF2016:第二天July06,20167/1,7/2因緣際會的去了兩天的2016台北遊戲開發者論壇(TaipeiGameDeveloperForum),雖然現在並沒有在開發遊戲,但兩天下來感覺相較於去技術意味濃厚的conference,收獲也是不少。

本系列文以簡單心得的方式做一些紀錄,免得以後忘光光了。

一共分為兩天。

TGDF2016:第一天 TGDF2016:第二天<刀劍->手勢體驗 而劇情則是小說式的精煉:劇情->插圖+文字->玩家自行腦補 看完遊戲玩法確實能夠感受到「武俠」的精神在裡面,非常厲害。

有興趣可以看一下介紹影片:https://www.youtube.com/watch?v=tDGEzNMqma8 系列文後記 這兩天都早起,前往會場的路上,一度微微感覺後悔接受友人的邀約(X)。

不過事實證明我錯了,覺得兩天下來有充分的感受到「想做遊戲」的能量,有一種神祕的充電感(雖然我不做遊戲啦)。

我想說的是 有對遊戲充滿熱情的各位真是太好了。

那麼最後我們就來聽一首「廁所女神」吧! TGDF2016:第一天July04,20167/1,7/2因緣際會的去了兩天的2016台北遊戲開發者論壇(TaipeiGameDeveloperForum),雖然現在並沒有在開發遊戲,但兩天下來感覺相較於去技術意味濃厚的conference,收獲也是不少。

本系列文以簡單心得的方式做一些紀錄,免得以後忘光光了。

一共分為兩天。

TGDF2016:第一天<



請為這篇文章評分?