① 有哪些用 javaScript 實現的圖形庫
D3.js
D3 是最流行的可視化庫之一,它被很多其他的表格插件所使用。它允許綁定任意數據到 DOM,然後將數據驅動轉換應用到文檔中。你可以使用它用一個數組創建基本的
HMTL 表格,或是利用它的流體過度和交互,用相似的數據創建驚人的 SVG 條形圖。
ChartJS
Chart.js 是一個令人印象深刻的 JavaScript 圖表庫,建立在 HTML5 Canvas
基礎上。目前,它支持6種圖表類型(折線圖,條形圖,雷達圖,餅圖,柱狀圖和極地區域區)。而且,這是一個獨立的包,不依賴第三方 JavaScript 庫,小於
5KB。
Highcharts JS
Highcharts JS 是一個製作圖表的純 Javascript 類庫,主要特性如下:兼容性:兼容當今所有的瀏覽器,包括 iPhone、IE
和火狐等等;對個人用戶完全免 費;純JS,無BS;支持大部分的圖表類型:直線圖,曲線圖、區域圖、區域曲線圖、柱狀圖、餅裝圖、散布圖;跨語言:不管是
PHP、Asp.net 還是 Java 都可以使用。
Fusioncharts
FusionCharts Suite XT 是個專業的 JavaScript
圖表庫,能創建任何類型的圖表。它創建的圖表都是可以進行完全自定義的,標簽,字體,邊界等等,都可以進行修改。它有很強的交互功能,有許多信息提示,可 點擊的
legend 關鍵字,還有 dril-down,縮放/滾動 和單擊列印圖表功能。
Flot
Flot 是受 Plotr 和 PlotKit 的 啟發,Ole Laursen 基於 jQuery 開發了一個圖表繪制(WEB Chart)插件並命名為
flot。 flot 是個純 JavaSript 庫,專注於簡單的使用方式,迷人的外觀和互動式特性。支持的瀏覽器有: Internet Explorer 6+,
Chrome, Firefox 2+, Safari 3+ and Opera 9.5+。
Chartist.js
Chartist.js 提供了優美的響應圖表。就像 ChartJS。它使用 SVG 渲染圖,可以被控制,並通過對 CSS3 媒體查詢和 SASS
定製。另外 Chartist.js 提供很酷的動畫。
n3-charts
如果你是一個 AngularJS 開發者,你一定喜歡款有趣的圖表。它是建立在 D3.js 和 AngularJS 的基礎上,提供了可定製的
AngularJS 指令的形式不同標準的圖表。
Ember Charts
Ember Charts 是一個基於 Ember.js 和 D3.js
的圖表庫。它包括時間序列、柱狀圖、餅圖、點圖,很容易擴展和修改。這些圖表組件代表圖表交互性和演示的最佳實踐,是高度可定製和可擴展的。
Chartkick
Chartkick 是專為 Ruby 應用程序的 JavaScript
圖表庫。它提供了所有主要的圖表類型,如餅圖,柱形圖,條形圖,面積,地理,時間,以及多個系列。
MeteorCharts
它有一個很酷的圖表生成器,為您提供選項來選擇圖表,選擇主題,然後生成一個圖表。
amCharts
amCharts 無疑是最漂亮的圖表庫。amCharts 提供了JavaScript/HTML5 Charts、Javascript/HTML5
Stock Chart、JavaScript Maps 三種圖表組件。
EJS Chart
EJS圖表聲稱自己是企業准備的圖表庫。圖表看起來很乾凈,可讀性比大多數舊的圖表庫。這也是與IE6+等舊瀏覽器兼容。
uvCharts
uvCharts 是一個開源的 JavaScript 圖表庫,號稱有100多個自定義選項。它擁有12種不同的標准圖表類型,開箱即用。
ECharts
基於 Canvas,純 JavaScript
圖表庫,提供直觀,生動,可交互,可個性化定製的數據可視化圖表。創新的拖拽重計算、數據視圖、值域漫遊等特性大大增強了用戶體驗,賦予了用戶對數據進行挖掘、整合的能力。
商業產品常用圖表庫,底層基於ZRender,創建了坐標系,圖例,提示,工具箱等基礎組件,並在此上構建出折線圖(區域圖)、柱狀圖(條狀圖)、散點圖(氣泡圖)、餅圖(環形圖)、K線圖、地圖、和弦圖以及力導向布局圖,同時支持任意維度的堆積和多圖表混合展現。
② D3.js的V5版本-Vue框架中使用-樹狀圖
一. api簡介
d3.tree(),創建一個樹狀圖生成器
d3.tree().size(),定義樹的大小
d3.hierarchy(),層級布局,需要和tree生成器一起使用,來得到繪制樹所需要的節點數據和邊數據
node.descendants()得到所有的節點,已經經過轉換的數據
node.links(),得到所有的邊,已經經過轉換的數據
二.Vue中使用
*點擊節點可展開收縮
③ 什麼是力導向布局圖
力導向圖(Force-Directed Graph),是繪圖的一種演算法。在二維或三維空間里配置節點,節點之間用線連接,稱為連線。各連線的長度幾乎相等,且盡可能不相交。節點和連線都被施加了力的作用,力是根據節點和連線的相對位置計算的。根據力的作用,來計算節點和連線的運動軌跡,並不斷降低它們的能量,最終達到一種能量很低的安定狀態。
力導向圖能表示節點之間的多對多的關系
④ D3圖表繪制
本節內容將描述餅狀圖、力導向圖、弦圖、集群圖、樹狀圖、打包圖、分區圖、圓形分區圖、直方圖、捆圖、堆棧圖、矩陣樹圖、地圖的繪制過程,參考 D3.js入門系列
溫馨提示:對於有D3基礎的人,本節內容能夠幫助其快速掌握各圖表的繪制。若沒有掌握基礎知識,不建議直接學習本節內容。
對圖表繪制的重點內容進行了總結,下述圖表繪制步驟相似,總結如下:
布局內容總結:
轉換後的數據:
弧生成器計算路徑(svg的path)
繪制路徑path,需要調用弧生成器
或者
繪制文本text,計算路徑中心位置,放入文本值
轉換後的數據:
然後,使力學作用生效:
繪制節點時,使節點拖動
力導向圖布局force有一個事件tick,每進行到一個時刻,都要調用它,更新的內容就寫在它的監聽器里就好。
數據轉換
轉換後的數據:
首先繪制外部圓環,使用arc弧生成器
繪制path,使用數據為groups
繪制text,使用數據為groups。首先旋轉適當角度,然後向上移動外半徑個長度,135-225度范圍的文字倒置
然後,繪制弦,使用chord生成器生成路徑
繪制path,使用數據為chords
使用數據
轉換後的數據:
首先,創建對角線生成器
繪制連線,使用生成器
然後繪制節點circle。
和集群圖寫法基本相同,使用布局不同。
轉換後的數據與集群圖相同。
數據格式與樹狀圖相同,布局如下:
數據轉換寫法也類似。
轉換後的數據:
然後分別繪制circle和text。
數據類型與集群圖、樹狀圖、打包圖相同。用於表示包含與被包含關系的。布局如下:
value設定表示分區大小的值。這里的意思是:如果數據文件中用size值表示結點大小,那麼這里可寫成return d.size。
數據轉換寫法也類似。(nodes、links)
轉換後的數據:
然後繪制rect和text。rect的width、height屬性分別對應數據屬性dx、dy。
與前面相同。
數據轉換寫法也類似。(nodes、links)
轉換後的數據:
分別繪制path和text。
首先創建弧生成器。
繪制path使調用弧生成器。
繪制text時要進行一下轉換:
數據轉換
轉換後的數據:
矩形rect、坐標軸line、刻度line、文字text。
需要使用集群圖布局和捆圖布局。
轉換後的數據:
創建放射式的線段生成器:
首先繪制path,調用線段生成器:
接著創建g,在g中繪制circle和text
繪制g需要旋轉、平移:
創建堆棧圖布局
數據轉換
轉換後的數據:
分別繪制矩形rect、圓形circle、文字text、坐標軸axis,繪制過程與柱形圖相似。
創建矩陣樹圖布局
數據轉換
轉換後的數據:
分別繪制矩形rect、文字text。
更多內容: Github個人博客
備註:本文發表於 https://cnyangkui.github.io/2017/11/15/d3-graphlist/
⑤ 初識 D3.js :打造專屬可視化
隨著現在自定義可視化的需求日益增長,Highcharts、echarts等高度封裝的可視化框架已經無法滿足用戶各種強定製性的可視化需求了,這個時候D3的無限定製的能力就脫穎而出。
如果想要通過D3完成可視化,除了對於D3本身API的學習, 關於web標準的HTML, SVG, CSS, Javascript 和 數據可視化的概念以及標准都是需要學習的。這無疑帶來了較高的學習門檻,但這也是值得的,因為掌握 D3 後,我們幾乎可以實現任何 2d 的可視化需求。
本文通過對D3核心模塊分析以及進行具體案例實踐的方式,來幫助初學者學習了解D3的繪圖思路。
D3的全稱是 Data-Driven Documents(數據驅動文檔),是基於數據來操作文檔的 JavaScript 庫,其核心在於使用繪圖指令對數據進行轉換,在源數據的基礎上創建新的可繪制數據, 生成SVG路徑以及通過數據和方法在DOM中創建數據可視化元素(如軸)。
相對於Echats等開箱即用的可視化框架來說,D3更接近底層,它可以直接控制原生的SVG元素,並且不直接提供任何一種現成的可視化圖表,所有的圖表都需我們在它的庫里挑選合適的方法構建而成,這也大大提高了它的可視化定製能力。而且D3 沒有引入新的圖形元素,它遵循了web標准(HTML, CSS, SVG 以及 Canvas )來展示數據 ,所以它可以不需要依賴其他框架獨立運行在現代瀏覽器中。
在V4版本後,D3的 API 現在已經被拆分成一個個模塊,我們可以根據自己的可視化需求進行按需載入。根據泛義可以將D3 API模塊分為以下的幾大類: DOM操作、數據處理,數據分析轉換、地理路徑,行為等 。
這里我們主要對 D3-selection 和 D3-scale 模塊進行解析:
D3-selection (選擇集) 是 D3js的核心模塊,主要是用來進行選擇元素,設置屬性、數據綁定,事件綁定等操作。
選擇元素: D3-selection 提供了兩種方法來獲取目標元素,d3.select():返回目標元素的第一個節點,d3.selectAll():返回目標元素的集合,乍一看有點類似原生API 的 querySelector 和 querySelectorAll,但是 d3.select 返回的是一個 selection 對象,querySelector 返回的是一個 NodeList 數組。通過控制台列印的信息,可以看到 selection 下的 groups 存放了所有選擇的元素集合,parents 存放了所有選中元素的父節點。
設置屬性或者綁定事件: 我們不需要關心 groups 的結構是怎麼樣的。當調用 selection.attr 或者 selection.style 的時候, selection 中的所有 group 的所有子元素都會被調用,group 存在的唯一影響是: 當我們傳參是一個function 的時候,例如 selection.attr('attrName', function(data, i)) 或 selection.on('click', function(data, i)) 時, 傳遞的 function(data, i) 中, 第二個參數 i 是元素在 group 中的索引而不是在整個 selection 中的索引。
數據綁定: 實際上是給選擇的DOM元素的 __data__ 屬性賦值,這里提供了3種方式進行數據綁定:
(1)給每一個單獨的 DOM 元素調用 selection.datum:d3.select('body').datum(20) 等價於 document.body.__data__ = 20
(2)從父節點中繼承來數據, 比如: append , insert , select,子節點會主動繼承父節點的數據:
(3) 調用 selection.data() 方法,支持傳入裝有基礎數據類型的數據,也支持傳入一個function(parentNode, groupIndex)根據節點索引與數據做映射,data()方法引入了 d3 中非常重要的 join 思想:
綁定 data 到 DOM 元素, 在D3中是通過比較 data 和 DOM 的 key 值來找到對應關系的。 如果我們沒有單獨設置 key 值,那麼默認根據 data 的下標索引來設定,但是當數據順序發生改變,這個默認下標 key 值 就變得不可靠了,這時我們可以使用 selection.data(data, keyFunction) 中的第二個參數 keyFunction,根據當前的數據返回一個對應的 key 值。通過下面的圖例可以看出,不管是有一個還是多個 group(每個group 都是獨立的),只要我們保證在任意一個 group 中的 key 值是唯一的,數據一旦發生變化都會反映給對應的 DOM 元素( update 的過程):
上面提到的都是data數據和DOM元素數量相同的情況下的數據綁定,那如果data數據和DOM元素數量不相同時,我們來看看 D3 又是如何進行數據綁定的:現在終於可以來介紹 D3-selecion 模塊的核心 Join 思想了,這個思想簡單來說就是 「不應該告訴D3去怎麼創建元素, 而是告訴D3,.selectAll() 得到的 selecion 集合應該和 .data(data) 綁定的數據要怎麼一一對應」。
從上圖可以看出,在進行 d3.data(data) 數據綁定的時候,會產生三種狀態的選擇集:
用 Join 的方式來理解意味著,我們要做的事情僅僅是聲明 DOM集合和數據集合之間的關系, 並且通過處理三個不同狀態的集合 enter、update 、 exit 來描述這種關系。這種方式可以大大簡化我們對DOM元素的操作,我們不需要再用 if 和 for 循環的方式來進行復雜的邏輯判斷,來得到我們需要得到的元素集合。並且在處理動態數據的時候,可以通過處理這三種狀態,輕松的展示實時數據和添加平滑的動態交互效果。
D3-scale (比列尺) 提供多種不同類型的比例尺。經常和 D3-axis 坐標軸模塊一起使用。
D3-scale 提供了多種連續性和非連續性的比例尺,總體可以將他們分為三大類:
常用的一些比例尺:
(1)d3-scaleLinear 線性比例尺(連續性輸入和連續性輸出)
可以看出,調用d3.scaleLinear()可以生成線性比例尺,domain()是輸入域,range()是輸出域,相當於將domain中的數據集映射到range的數據集中。
使用示例:
映射關系:
(2)d3-scaleTime 時間比例尺(連續性輸入和連續性輸出)
時間比例尺與線性比例尺類似,只不過輸入域變成了一個時間軸。正常我們使用比例尺都是個正序的過程,但是D3也提供了invert()以及invertExtent()方法,我們可以通過輸出域中的具體值得出對應輸入域的值。
使用示例:
(3)d3.scaleQuantize 量化比例尺(連續性輸入和離散性輸出)
量化比例尺是將連續的輸入域根據輸出域被分割為均勻的片段,所以它的輸出域是離散的。
使用示例:
映射關系:
(4)d3. scaleThreshold 閾值比例尺(連續性輸入和離散性輸出)
閾值比例尺可以為一組連續數據指定分割閾值,閾值比例尺默認的 domain:[0.5] 以及默認的 range:[0, 1] ,因此默認的 d3.scaleThreshold() 等價於 Math.round 函數。 閾值比例尺輸入域為 N 的話,輸出域必須為 N + 1,否則比例尺對某些值可能會返回 undefined,或者輸出域多餘的值會被忽略。
使用示例:
存在三種映射關系:
a. 當domain和range的數據是 N : N+1
b. 當domain和range的數據是 N : N + 大於1
c. 當domain和range的數據是 N + 大於0 : N
(5)d3.scaleOrdinal 序數比例尺(離散性輸入和離散性輸出)
與scaleLinear等連續性比例尺不同,序數比例尺的輸出域和輸入域都是離散的。
使用示例:
存在三種映射關系:
a.當domain和range的數據是一一對應
b.當domain少於range的數據
c.當domain多於range的數據
通過以上的學習,應該對d3是如何操作DOM以及坐標軸的數據映射為相應的可視化表現有了一定的了解,下面我們來實際運用這兩個模塊,來實現我們常見的可視化圖表:柱狀圖。
(1)首先添加一個SVG元素。
(2)根據我們上面說到 d3.scale 模塊以及 d3.axis 模塊繪制坐標軸,d3.scaleBand() 叫做序數分段比例尺,類似我們說的 d3.scaleOrdinal() 序數比例尺,但是它支持連續的數值類型的輸出域,離散的輸入域可以將連續的范圍劃分為均勻的分段。這里再講一個細節,在繪制網格的時候,我們並沒有額外添加 line 元素來實現,而是通過 d3.axis 坐標軸模塊的 axis.ticks() 方法對坐標軸刻度進行了設置,通過 tickSIze() 設置了刻度線長度,來模擬和圖表寬度相等的網格線,並且還可以通過 tickFormat() 對Y軸刻度值進行格式化轉換。
(3)坐標軸繪制好了後,我們通過數據綁定來繪制與之對應的矩形(rect)元素了。
(4)這個時候柱狀圖已經基本繪制好了,我們再豐富內容展示,添加標簽、標題等提示信息。
(5)最後我們通過給柱子綁定監聽事件,實現tooltips的信息浮層交互。
通過對 d3.selection 、d3.scale 以及 d3.axis等模塊的學習,我們已經可以繪制出常用的柱狀圖等圖表,我們也可以通過d3提供的其他模塊繪制出更加復雜的可視化效果,例如通過 d3-hierarchy(層級模塊) 實現層級樹圖可視化,d3-geo(地理投影) 實現地圖數據可視化等,本文講解的內容還只是D3庫的冰山一角。所以等我們掌握了D3後,限制我們實現可視化的不再是技術而是想像力。
⑥ echarts 怎樣用js自定義圖表數據
引入ECharts
echarts提供多種引入方式,請根據你的項目類型選擇合適的方式:
模塊化包引入
如果你熟悉模塊化開發,你的項目本身就是模塊化且遵循AMD規范的,那引入echarts將很簡單,使用一個符合AMD規范的模塊載入器,如esl.js,只需要配置好packages路徑指向src即可,你將享受到圖表的按需載入等最大的靈活性,由於echarts依賴底層zrender,你需要同時下載zrender到本地,可參考demo,你需要配置如下。
需要注意的是,包引入提供了開發階段最大的靈活性,但並不適合直接上線,減少請求的文件數量是前端性能優化中最基本但很重要的規則,務必在上線時做文件的連接壓縮。
//from echarts example
require.config({
packages: [
{
name: 'echarts',
location: '../../src',
main: 'echarts'
},
{
name: 'zrender',
location: '../../../zrender/src', // zrender與echarts在同一級目錄
main: 'zrender'
}
]
});
模塊化單文件引入(推薦)
如果你使用模塊化開發但並沒有自己的打包合並環境,或者說你不希望在你的項目里引入第三方庫的源文件,我們建議你使用單文件引入,同模塊化包引入一樣,你需要熟悉模塊化開發。
自2.1.8起,我們為echarts開發了專門的合並壓縮工具echarts-optimizer。如你所發現的,build文件夾下已經包含了由echarts-optimizer生成的單文件:
dist(文件夾) : 經過合並、壓縮的單文件
line.js : 折線圖(如需折柱動態類型切換,require時還需要echarts/chart/bar)
bar.js : 柱形圖(如需折柱動態類型切換,require時還需要echarts/chart/line)
scatter.js : 散點圖
k.js : K線圖
pie.js : 餅圖(如需餅漏斗圖動態類型切換,require時還需要echarts/chart/funnel)
radar.js : 雷達圖
map.js : 地圖
force.js : 力導向布局圖(如需力導和弦動態類型切換,require時還需要echarts/chart/chord)
chord.js : 和弦圖(如需力導和弦動態類型切換,require時還需要echarts/chart/force)
funnel.js : 漏斗圖(如需餅漏斗圖動態類型切換,require時還需要echarts/chart/pie)
gauge.js : 儀表盤
eventRiver.js : 事件河流圖
treemap.js : 矩陣樹圖
venn.js : 韋恩圖
echarts.js : 這是包含AMD載入器的echarts主文件,需要通過script最先引入
chart(文件夾) : echarts-optimizer通過依賴關系分析同時去除與echarts.js的重復模塊後為echarts的每一個圖表類型單獨打包生成一個獨立文件,根據應用需求可實現圖表類型按需載入
source(文件夾) : 經過合並,但並沒有壓縮的單文件,內容同dist,可用於調試
採用單一文件使用例子見ECharts單一文件引入,存放在example/www下,首先你需要通過script標簽引入echarts主文件
在主文件引入後你將獲得一個AMD環境,配置require.conifg如下:
require.config配置後就可以通過動態載入使用echarts
總結來說,模塊化單文件引入ECharts,你需要如下4步:
為ECharts准備一個具備大小(寬高)的Dom(當然可以是動態生成的)
通過script標簽引入echarts主文件
為模塊載入器配置echarts的路徑,從當前頁面鏈接到echarts.js所在目錄,見上述說明
動態載入echarts及所需圖表然後在回調函數中開始使用(容我羅嗦一句,當你確保同一頁面已經載入過echarts,再使用時直接require('echarts').init(dom)就行)
詳見入門教程 ( Getting started ) »
標簽式單文件引入
自1.3.5開始,ECharts提供標簽式引入。如果你的項目本身並不是基於模塊化開發的,或者是基於CMD規范(如使用的是seajs),那麼引入基於AMD模塊化的echarts可能並不方便,我們建議你採用srcipt標簽式引入,忘掉require。Srcipt標簽引入echarts後將可以直接使用兩個全局的命名空間:echarts,zrender,可參考ECharts標簽式引入,需要注意的是excanvas依賴body標簽插入Canvas節點去判斷Canvas的支持,如果你把引用echarts的script標簽放置head內在IE8-的瀏覽器中會出現報錯,解決的辦法就是把標簽移動到body內(後)。
標簽式引入環境中,常用模塊的引用可通過命名空間直取,同模塊化下的路徑結構,如:
echarts.config = require('echarts/config'), zrender.tool.color = require('zrender/tool/color')
⑦ d3.js中力導向圖的節點怎麼用包圖
var force = d3.layout.force()//layout將json格式轉化為力學圖可用的格式
.nodes(d3.values(nodes))//設定節點數組
.links(links)//設定連線數組
.size([width, height])//作用域的大小
.linkDistance(180)//連接版線長度
.charge(-1500)//頂點的電荷權數。該參數決定是排斥還是吸引,數值越小越互相排斥
.on("tick", tick)//指時間間隔,隔一段時間刷新一次畫面
.start();//開始轉換
⑧ d3.js與jquery的區別
d3.js和jQuery都有個相同之處,就是它們都是js界的著名工具庫。但是它們所面對的領域不一回樣。
d3.js主要是做數據可答視化的,也就是各種炫酷的圖表,比如折線圖、弦圖、力導向圖等等。而jQuery主要是做頁面DOM控制、AJAX和動畫的。
⑨ d3.js畫力學圖,怎麼把圖限制在邊框內
我上次看了,他這個都明白了,你可以看看,他每一步都有代碼,注釋,很簡單的。
網頁鏈接
⑩ 如何使用d3.js製作可視化圖表
D3是目前最流行的JavaScript可視化圖表庫之一,D3的圖表類型非常豐富,並且支持SVG格式,因此應用十分廣泛,也有很多圖表插件基於D3開發,比如MetricsGraphics.js,在D3上構建的數據圖表非常強大。
D3的特點
允許綁定任意數據到DOM,將數據驅動轉換應用到Document中。
不僅可以創建精美的HTML表格,而且可以繪制折線圖、柱形圖和餅圖等數據圖表。
支持SVG,在Web頁面上渲染毫無壓力。
回到頂部
D3的使用方法
關於D3的具體用法,可以看D3圖形庫API參考這篇文章。本文主要對介紹一些經典圖表的實現效果及代碼。
<!DOCTYPEhtml>
<metacharset="utf-8">
<style>
svg{
font:10pxsans-serif;
}
.y.axispath{
display:none;
}
.y.axisline{
stroke:#fff;
stroke-opacity:.2;
shape-rendering:crispEdges;
}
.y.axis.zeroline{
stroke:#000;
stroke-opacity:1;
}
.title{
font:30078pxHelveticaNeue;
fill:#666;
}
.birthyear,
.age{
text-anchor:middle;
}
.birthyear{
fill:#fff;
}
rect{
fill-opacity:.6;
fill:#e377c2;
}
rect:first-child{
fill:#1f77b4;
}
</style>
<body>
<scriptsrc="http://d3js.org/d3.v3.min.js"></script>
<script>
varmargin={top:20,right:40,bottom:30,left:20},
width=960-margin.left-margin.right,
height=500-margin.top-margin.bottom,
barWidth=Math.floor(width/19)-1;
varx=d3.scale.linear()
.range([barWidth/2,width-barWidth/2]);
vary=d3.scale.linear()
.range([height,0]);
varyAxis=d3.svg.axis()
.scale(y)
.orient("right")
.tickSize(-width)
.tickFormat(function(d){returnMath.round(d/1e6)+"M";});
//AnSVGelementwithabottom-rightorigin.
varsvg=d3.select("body").append("svg")
.attr("width",width+margin.left+margin.right)
.attr("height",height+margin.top+margin.bottom)
.append("g")
.attr("transform","translate("+margin.left+","+margin.top+")");
//.
varbirthyears=svg.append("g")
.attr("class","birthyears");
//Alabelforthecurrentyear.
vartitle=svg.append("text")
.attr("class","title")
.attr("dy",".71em")
.text(2000);
d3.csv("population.csv",function(error,data){
//Convertstringstonumbers.
data.forEach(function(d){
d.people=+d.people;
d.year=+d.year;
d.age=+d.age;
});
//.
varage1=d3.max(data,function(d){returnd.age;}),
year0=d3.min(data,function(d){returnd.year;}),
year1=d3.max(data,function(d){returnd.year;}),
year=year1;
//Updatethescaledomains.
x.domain([year1-age1,year1]);
y.domain([0,d3.max(data,function(d){returnd.people;})]);
//[male,female].
data=d3.nest()
.key(function(d){returnd.year;})
.key(function(d){returnd.year-d.age;})
.rollup(function(v){returnv.map(function(d){returnd.people;});})
.map(data);
//.
svg.append("g")
.attr("class","yaxis")
.attr("transform","translate("+width+",0)")
.call(yAxis)
.selectAll("g")
.filter(function(value){return!value;})
.classed("zero",true);
//(sothatnoenterorexitisrequired).
varbirthyear=birthyears.selectAll(".birthyear")
.data(d3.range(year0-age1,year1+1,5))
.enter().append("g")
.attr("class","birthyear")
.attr("transform",function(birthyear){return"translate("+x(birthyear)+",0)";});
birthyear.selectAll("rect")
.data(function(birthyear){returndata[year][birthyear]||[0,0];})
.enter().append("rect")
.attr("x",-barWidth/2)
.attr("width",barWidth)
.attr("y",y)
.attr("height",function(value){returnheight-y(value);});
//Addlabelstoshowbirthyear.
birthyear.append("text")
.attr("y",height-4)
.text(function(birthyear){returnbirthyear;});
//Addlabelstoshowage(separate;notanimated).
svg.selectAll(".age")
.data(d3.range(0,age1+1,5))
.enter().append("text")
.attr("class","age")
.attr("x",function(age){returnx(year-age);})
.attr("y",height+4)
.attr("dy",".71em")
.text(function(age){returnage;});
//.
window.focus();
d3.select(window).on("keydown",function(){
switch(d3.event.keyCode){
case37:year=Math.max(year0,year-10);break;
case39:year=Math.min(year1,year+10);break;
}
update();
});
functionupdate(){
if(!(yearindata))return;
title.text(year);
birthyears.transition()
.ration(750)
.attr("transform","translate("+(x(year1)-x(year))+",0)");
birthyear.selectAll("rect")
.data(function(birthyear){returndata[year][birthyear]||[0,0];})
.transition()
.ration(750)
.attr("y",y)
.attr("height",function(value){returnheight-y(value);});
}
});