數據可視化之MarkPoint

1

      MarkPoint是什麼效果?如上圖,一閃一閃亮晶晶的效果,這是在Echarts中對應的效果。我最先看到的是騰訊的一個Flash的版本,顯示當前QQ在線人數的全國分佈效果,感受效果很炫,當時也在想,怎麼用JS,HTML5來作出相似的效果,但說實話,沒什麼思路,甚至懷疑JS是否作不出來這種逼真的效果來。終於看到Echarts中提供了這個功能。下面就扒開她絢麗的衣着,一塊兒走進MarkPoint的世界。 算法

數據

2

      首先仍是先看看數據上的邏輯。上圖是一個數據格式,placeList包括每個關鍵點的名稱和座標位置,而在風格中主要有name,能夠設置爲強中弱三種,分別對應MarkPoint圖中白藍綠三種效果,類型是中國地圖,而具體的風格在存儲在markPoint字段中。咱們在看看markPoint字段裏面是什麼內容。 緩存

3

      如上就是markPoint裏面的主要內容,這裏,每個點是一個鑽石(diamond)的樣式,符號大小,還有一個effect的屬性,這就是它的動畫風格,而data則用來加載placeList的信息。 框架

      綜上所述,對於使用者而言,指定好要顯示markPoint的位置,也就是placeList,而後在賦予它們的具體效果,中國範圍,強弱類型以及具體的形狀(鑽石,矩形或圓形等),這樣就能夠獲得MarkPoint這樣的閃爍效果。 dom

原理

      其實說原理有點誇大其詞。經過數據層面,能夠看出來每個點都是獨立的,若是你放大後,基本能夠判斷出來各自完成本身的動畫效果,並一致循環下去。若是縮小後,你會發現全部的markPoint並非同步的,頻率各不相同,顯得雜亂無章。(推薦TED的視頻:The First Secret of Great Design - Tony Fadell - TED Talks)。 函數

      這樣,這個問題就分解成了兩個部分: 字體

  • 如何模擬每個點的閃爍效果優化

  • 如何管理大規模的點的閃爍週期動畫

閃爍效果的實現

4

      如上,是同一個markPoint在不一樣幀下的效果,你們能夠想一想一下這樣一個從小到大而後再到小的過程,則完成了閃爍的效果,若是你足夠細心會發現裏面有一個blur的平滑效果,這樣會讓閃爍有一個平滑的效果,相似字體的抗鋸齒,看起來有一種朦朧的感受。固然,blur這個效果是怎麼實現的?其實在以前風向圖和熱點圖中都採用了這個技術,就是和上一幀的圖片進行一個半透明的疊加。而後在配合一個動畫特效(animation effect),閃爍的效果就完成了。 ui

多點閃爍動畫的實現

5

      如上是在某一幀的截圖。俗話說的好,一花獨放不是春,因此如何控制這麼多的點,風格各不相同的markPoint,並且頻率各不相同,這就涉及到動畫類和隨機數之間的內容,同時在框架上可以貫穿整個渲染週期。 調試

      咱們看一下在Echarts上的流程,先是初始化的流程:

6

      如同,MarkPoint的數據初始化主要是Map類讀取數據,而後在Base中調用getLargeMarkPointShape來建立這些點。

      在Base中,調用animationEffect指定單個MarkPoint的閃爍風格,這裏須要額外說明一下,雖然在數據中動畫風格只是簡單的show:true.但實際上,最終是採用的config.js中默認的動畫風格,好比周期,是否循環,跳動等,以下圖所示:

7

      而在ecEffect中,調用largePoint來隨機設置,實現各自不一樣的動畫週期。從而完成整改初始化的過程。

      初始化結束後,則進入到了渲染階段。渲染是採用的zrender框架,而markPoint則是由Animation來驅動,每一幀都會調用update,在onframe中來設置每個點當前的狀態,好比大小,根據時間週期下,線性插值計算出它應該的大小(下面會詳細說明),最後調用Symbol::buildPath實現全部markPoint的閃爍效果。

      這就是初始化準備和渲染週期的大體一個過程,下面對主要功能模塊進行介紹

實現代碼

8

      如上,只是指定了blur爲true,則實現了平滑效果,簡單不?其實這用了一個雙緩存的技術,在zrender中有一個Layer對象,每一幀都會疊加上一幀的效果,並保存。具體的實現能夠參閱zrender的Layer類,比較簡單。

閃爍動畫有點複雜,首先,怎麼控制一個markPoint從大到小的這樣一個線性變換的過程,動畫類是如何控制的,另外對於不一樣的markPoint,有這麼多點,同一幀下每一個點對應的風格也不盡相同,這又是如何控制的。

      首先,這要介紹一下zrender中的Animation類,一個很是好用強大的類,先看看使用代碼,以下:

9

      首先,這是一個when.js風格的使用方式,該動畫主要用來控制effectShape的‘style’屬性,即每一幀來對style屬性進行更新。那更新什麼內容呢?這就是clip對象了。

      這裏有四個when,再加上最上面的隨機的初始大小,也就是說一個週期有5個控制點,其中clip1 = 100,而clip2 = 0,,這裏對應的是該控制點對應markPoint的size的百分比。也就是在這個週期中,按照以下的插值算法來控制該點的size。不知道說清楚了沒有,能夠本身調試一下代碼看看。

10

      這是在一幀下插值計算當前size的百分比,這裏採用的線性插值,還有其餘多種算法能夠選擇,這裏是size,因此用的最簡單的線性插值,你也能夠實現軌跡,或者加速度等不一樣的公式來實現對應的效果。

11

      插值計算完了,付給對應的style中randomMap+i屬性上。這裏,一共常見了20個Animation類,這樣就會有20個動畫效果,來實現頻率各自不一樣的閃爍效果。最後會調用zrender的refresh,最終來到Symbol的渲染階段。這裏,每個點根據本身的索引選擇對應的縮放比例percent,而後進入下面的繪製階段。

12

      另外,在對每個點的渲染函數中,進行了進一步的優化,代碼以下,根據大小進行了簡化。

13

      Ok,到此,我想到的關於MarkPoint的內容都已經完畢,另外這個類涉及到一個大規模點渲染,等有機會對這方面詳細研究後在和你們分享。

相關文章
相關標籤/搜索