今日目標: 了解如何包裝 D3 視覺化元件
視覺化元件 <d3-flare>
這元件功能是顯示目前鐵人賽各組參與人數,以及積分的視覺化效果。也就是每個白色小圈圈都是一個鐵人,小圈圈的大小是根據積分決定的。所以可以一目了然各組積分程度。
[線上試玩]
未包裝成元件的版本,請參考 [Github] ,是從 D3範例是改讀取鐵人賽資料集。
程式目錄結構
程式碼如下
第2行 載入 d3 javascript library
第4行 提供 margin , diameter 這兩個屬性給外部使用
第5行 載入css (直接使用範例的css檔案)
第6行 挖個洞,準備提供給 d3 繪製圖表時就放在這個div裏面
第11,12行 設定 margin , diameter 預設值,外部沒有傳入就使用預設值
[Github]
接下來就是怎麼將範例Code包裝成元件的用法,包裝時有些經驗可以分享
- 整個Polymer JS是寫在<script>..</script>裏面,這裡是JavaScript全域,元件封裝是很重要的一環 (強調重複使用、隱藏實作細節),所以通常都會用閉包來處理
- 先前Polymer實戰的例子也有提到, 可能一次會使用到多個相同的元件 (例如自己的英文自己救-結合Youtube),單字輸入的元件就會被重複使用。這時候把該元件共同使用的部分 (例如都需要發音) 就可以抽出來,放在第9~10行之間,就可以讓產生的元件一起共用 var,function 都可以 (視為該元件的Global區域)
- 使用元件的開發者可能會改的參數,長相就用attributes暴露出去,並設定預設值。在這裏例子是第3行,第11,12行設定預設值
- JavaScript的this不像Java的this,this會隨著呼叫對象而改變,而且JavaScript又很常會使用到callback function,所以一開始就設定 var my = this ,用來在callback function中使用
- 如果要提供給使用元件的開發者元件方法,就可以像是第67,84行的寫法,外部就可以直接呼叫,例如
使用方式: document.querySelector('d3-flare').zoom()
- 在這次例子中,不夠了解d3 API,所以元件包的並不好,例如d3抓資料部分我直接寫在 ready (元件初始化方法中) ,這已經假設了該元件載入就會發出ajax,而且request url也都寫死在此元件中,該元件重複使用性就大大降低了 XD
- d3的範例是直接將圖例放到 裡面,所以要記得改成元件內挖個洞讓d3擺,修改如下 "body" 改成 my.$.d3
最後,我希望當有人點擊指定組別時,可以在右側提供該組排行榜
這時就需要這元件發出事件,外部就可以訂閱並處理,藉此實現元件間只靠事件溝通,元件間完全解耦合,誰也不依賴誰的境界。這也是包裝元件要注意的事,至於實現就很簡單,polymer本身已經提供 fire 方法,所以直接參考下面程式碼,第43行
所以開發者就可以直接在網頁裡面接聽並處理,取得積分前10名鐵人
第22行 註冊 team-rank 事件,從 e.detail 拿到該組鐵人名單
第23~26行 取得積分前10名鐵人
第27~29行 更新model ,因為有雙向binding,所以畫面就自動會更新了
[Github]
這個例子主要是學習包裝元件的一些技巧,談到一些元件重用性、封裝、隱藏技術細節等議題,明天介紹 鐵人卡片元件,聊聊如何使用Shadow DOM特性,讓使用元件達到最大的彈性