引子
繼 Learn D3: Joins 第八篇,只是英文翻譯,可修改程式碼的部分用靜態圖片替代了,想要實時互動請閱讀原文。
- 原文:Learn D3: Interaction
- 版本:Published Mar 24, 2020
- Origin
- My GitHub
正文
幾乎總是有太多的資訊無法合理地“容納”在圖表中。因此,設計不僅僅是決定如何展示某些東西,而是根據我們認為對想象中的讀者重要的東西,來決定展示什麼和不展示什麼。
多虧了計算機,真正的讀者現在有了發言權:可以根據讀者興趣的需要定製圖表。
然而,這種力量是一把雙刃劍。互動性允許讀者發現更多資訊,但迫使讀者參與互動。如果我們不小心,我們可能會將重要的見解隱藏在讀者從不點選的控制元件後面。
如果我們的目的是傳達已知的資訊,我們應該在考慮互動之前設計一個有效的靜態圖表。另一方面,如果我們試圖探索未知,那麼互動可以比編碼一個新的圖表更快(但也考慮視覺化語法探索,如 Vega Lite )!
比較好的互動指南可以參考 Ben Shneiderman 的 information-seeking mantra :
Overview first,zoom and filter,then details on demand.
overview 是圖表的初始形式。它的目的不是顯示所有資料(這是不可能的),而是提供所有資料的“巨集觀”檢視。overview 是引導讀者探索。
zooming 和 filtering 是選擇感興趣主題內容顯示的方法。我們以前看到過將圖表裁剪到各個年份的控制元件;還有自由縮放的形式、平移和焦點+上下文。如果我們比較多個時間序列,我們可能需要像多折線圖示例中那樣進行過濾。另請參見可刷散點圖矩陣。
details on demand 允許讀者從圖表中提取精確值,而不限於視覺近似值。這可以像滑鼠提示一樣簡單。
滑鼠提示的一種方法是在 SVG 中不受限制的新增標題元素。滑鼠懸停(並短暫等待)檢視下面某一天的蘋果股價。
上圖中,1260 個不可見的矩形元素垂直貫穿圖表,水平橫跨相鄰的資料點(用 d3.pairs 計算)。當滑鼠懸停在矩形上時,將顯示子 title 元素的文字。因此,顯示提示資訊的是滑鼠 x 位置的函式,最適合於 y 為因變數的時間序列圖。
更通用的方法是 Voronoi 覆蓋,其中距離滑鼠最近的資料點確定為資訊提示(為了清晰起見,下面繪製了 Voronoi 圖……並且因為它看起來很酷。你通常不會顯示它。)
本地滑鼠提示有幾個缺點:它們的顯示速度較慢;移動瀏覽器不支援它們;而且並不總是很明顯哪個資料點與提示資訊關聯,尤其是在使用 Voronoi 圖時。
不過,再多做一點工作,我們就可以定製滑鼠提示了。
這裡元素的順序很重要:SVG 不支援 z 順序,因此要在直線和軸之上繪製資訊提示,它必須是最後一個。
雖然本地滑鼠提示會自動顯示,但自定義資訊提示通常需要事件監聽。當使用者執行操作(例如將滑鼠移到元素上)時,瀏覽器將呼叫這些函式。上面的偵聽器捕獲閉包中的資料( a 和 b ),以瞭解在觸發事件時顯示什麼。
(我們使用 Object.assign ,因為 Observable 的 HTML 模板文字當前不支援事件偵聽器作為屬性。我們更新的 hyperscript literal 確實支援事件偵聽器,所以請考慮使用它。我們計劃在不久的將來升級標準庫。)
自定義資訊提示在下面的類中實現。它提供了用於嵌入的 tooltip.node 屬性(SVG g 元素),以及 tooltip.show 和 tooltip.hide 方法,以根據需要更新工具提示。這為資訊提示的觸發方式提供了一定的靈活性。
上面的圖表使用 Observable 的 HTML 模板文字,但是我們可以用 D3 風格實現一個相同的圖表。用你喜歡的!
mouseover 事件觸發的資訊提示可能代價高昂:它們要求圖表的每個可懸停區域都有一個單獨的元素。對於複雜的圖表,你可以通過計算按需懸停的內容來提高效能。
對於一維排序的資料(例如我們這裡的時間序列資料),一種特別高效的方法是在 mousemove 事件觸發時進行二分查詢。
二分查詢法將立即返回滑鼠左側的資料點,但出於互動目的,最好找到離滑鼠最近的資料點(沿 x )。因此,下面的函式首先對分指定日期,然後檢查以下資料點是否更接近。
以上所有示例都演示了本地互動:與圖表互動隻影響圖表本身。Observable 最令人興奮的方面之一是,語言水平的反應性使一個單元中的互動很容易擴散到筆記本中的任何其它單元,從而實現全域性互動!
Observable 中的大多數互動控制元件都由檢視實現。要建立檢視,定義返回 HTML input 元素的 viewof 單元。然後,input 的實時值將被提供給筆記本的其餘部分。
例如,這裡有一個由範圍輸入控制的數字。
類似地,這裡有一個文字輸入,可以在你鍵入時顯示其值,還有一個下拉選單,用於從多個固定選項中選擇一個。
(還記得之前我們看到動畫生成器的時候嗎?這些檢視也涉及生成器:當你使用 viewof 操作符時,Observable 隱式建立了一個非同步輸入生成器,每當你與檢視互動時,它都會生成一個新值。)
但是檢視並不侷限於 HTML input ,它們可以是任何東西!唯一的要求是檢視提供一個 value 屬性,並在該值變化時觸發 input 事件。
甚至圖表也可以是檢視。下面的圖表在滑鼠移動時觸發合成輸入事件。
多虧了 Observable 社群,有許多定製的輸入可以複用。有關各種有用的選項,請參見 Jeremy 的 inputs bazaar 。或者對於動畫,考慮一個 scrubber 。
在本教程中,我們快速瀏覽了各種互動技術,包括滑鼠提示、事件偵聽器、Voronoi 覆蓋圖、檢視,但還有很多我們沒有介紹的內容!首先,我們甚至沒有提到 D3 的可複用行為:brushing、 zooming、 dragging 。(對於自主學習,請在 D3 相簿和收藏中查詢示例。)
事實上,既然我們已經涵蓋了基本知識,現在是時候回頭思考下一步該怎麼走了。
附錄
有關互動的更多資訊,請閱讀 Gregor Aisch 的 defense of interactive graphics。
附
根據原始碼,去除了平臺依賴,提取了主要程式碼,有以下示例: