JavaScript可视化图表库D3.js

jopen 9年前

D3是目前最流行的JavaScript可视化图表库之一,D3的图表类型非常丰富,并且支持SVG格式,因此应用十分广泛,也有很多图表插件基于D3开发,比如MetricsGraphics.js,在D3上构建的数据图表非常强大。

D3的特点

  • 允许绑定任意数据到DOM,将数据驱动转换应用到Document中。
  • 不仅可以创建精美的HTML表格,而且可以绘制折线图、柱形图和饼图等数据图表。
  • 支持SVG,在Web页面上渲染毫无压力。

D3的使用方法

关于D3的具体用法,可以看D3图形库API参考这篇文章。本文主要对介绍一些经典图表的实现效果及代码。

柱形图

效果图:

index.html代码:

<!DOCTYPE html>  <meta charset="utf-8">  <style>    svg {    font: 10px sans-serif;  }    .y.axis path {    display: none;  }    .y.axis line {    stroke: #fff;    stroke-opacity: .2;    shape-rendering: crispEdges;  }    .y.axis .zero line {    stroke: #000;    stroke-opacity: 1;  }    .title {    font: 300 78px Helvetica Neue;    fill: #666;  }    .birthyear,  .age {    text-anchor: middle;  }    .birthyear {    fill: #fff;  }    rect {    fill-opacity: .6;    fill: #e377c2;  }    rect:first-child {    fill: #1f77b4;  }    </style>  <body>  <script src="http://d3js.org/d3.v3.min.js"></script>  <script>    var margin = {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;    var x = d3.scale.linear()      .range([barWidth / 2, width - barWidth / 2]);    var y = d3.scale.linear()      .range([height, 0]);    var yAxis = d3.svg.axis()      .scale(y)      .orient("right")      .tickSize(-width)      .tickFormat(function(d) { return Math.round(d / 1e6) + "M"; });    // An SVG element with a bottom-right origin.  var svg = 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 + ")");    // A sliding container to hold the bars by birthyear.  var birthyears = svg.append("g")      .attr("class", "birthyears");    // A label for the current year.  var title = svg.append("text")      .attr("class", "title")      .attr("dy", ".71em")      .text(2000);    d3.csv("population.csv", function(error, data) {      // Convert strings to numbers.    data.forEach(function(d) {      d.people = +d.people;      d.year = +d.year;      d.age = +d.age;    });      // Compute the extent of the data set in age and years.    var age1 = d3.max(data, function(d) { return d.age; }),        year0 = d3.min(data, function(d) { return d.year; }),        year1 = d3.max(data, function(d) { return d.year; }),        year = year1;      // Update the scale domains.    x.domain([year1 - age1, year1]);    y.domain([0, d3.max(data, function(d) { return d.people; })]);      // Produce a map from year and birthyear to [male, female].    data = d3.nest()        .key(function(d) { return d.year; })        .key(function(d) { return d.year - d.age; })        .rollup(function(v) { return v.map(function(d) { return d.people; }); })        .map(data);      // Add an axis to show the population values.    svg.append("g")        .attr("class", "y axis")        .attr("transform", "translate(" + width + ",0)")        .call(yAxis)      .selectAll("g")      .filter(function(value) { return !value; })        .classed("zero", true);      // Add labeled rects for each birthyear (so that no enter or exit is required).    var birthyear = 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) { return data[year][birthyear] || [0, 0]; })      .enter().append("rect")        .attr("x", -barWidth / 2)        .attr("width", barWidth)        .attr("y", y)        .attr("height", function(value) { return height - y(value); });      // Add labels to show birthyear.    birthyear.append("text")        .attr("y", height - 4)        .text(function(birthyear) { return birthyear; });      // Add labels to show age (separate; not animated).    svg.selectAll(".age")        .data(d3.range(0, age1 + 1, 5))      .enter().append("text")        .attr("class", "age")        .attr("x", function(age) { return x(year - age); })        .attr("y", height + 4)        .attr("dy", ".71em")        .text(function(age) { return age; });      // Allow the arrow keys to change the displayed year.    window.focus();    d3.select(window).on("keydown", function() {      switch (d3.event.keyCode) {        case 37: year = Math.max(year0, year - 10); break;        case 39: year = Math.min(year1, year + 10); break;      }      update();    });      function update() {      if (!(year in data)) return;      title.text(year);        birthyears.transition()          .duration(750)          .attr("transform", "translate(" + (x(year1) - x(year)) + ",0)");        birthyear.selectAll("rect")          .data(function(birthyear) { return data[year][birthyear] || [0, 0]; })        .transition()          .duration(750)          .attr("y", y)          .attr("height", function(value) { return height - y(value); });    }  });

数据文件:

year,age,sex,people  1850,0,1,1483789  1850,0,2,1450376  1850,5,1,1411067  1850,5,2,1359668  1850,10,1,1260099  1850,10,2,1216114  1850,15,1,1077133  1850,15,2,1110619  1850,20,1,1017281  1850,20,2,1003841  1850,25,1,862547  1850,25,2,799482  1850,30,1,730638  1850,30,2,639636  1850,35,1,588487  1850,35,2,505012  1850,40,1,475911  1850,40,2,428185  1850,45,1,384211  1850,45,2,341254  1850,50,1,321343  1850,50,2,286580  1850,55,1,194080  1850,55,2,187208  1850,60,1,174976  1850,60,2,162236  1850,65,1,106827  1850,65,2,105534  1850,70,1,73677  1850,70,2,71762  1850,75,1,40834  1850,75,2,40229  1850,80,1,23449  1850,80,2,22949  1850,85,1,8186  1850,85,2,10511  1850,90,1,5259  1850,90,2,6569  1860,0,1,2120846  1860,0,2,2092162  1860,5,1,1804467  1860,5,2,1778772  1860,10,1,1612640  1860,10,2,1540350  1860,15,1,1438094  1860,15,2,1495999  1860,20,1,1351121  1860,20,2,1370462  1860,25,1,1217615  1860,25,2,1116373  1860,30,1,1043174  1860,30,2,936055  1860,35,1,866910  1860,35,2,737136  1860,40,1,699434  1860,40,2,616826  1860,45,1,552404  1860,45,2,461739  1860,50,1,456176  1860,50,2,407305  1860,55,1,292417  1860,55,2,267224  1860,60,1,260887  1860,60,2,249735  1860,65,1,149331  1860,65,2,141405  1860,70,1,98465  1860,70,2,101778  1860,75,1,56699  1860,75,2,57597  1860,80,1,29007  1860,80,2,29506  1860,85,1,10434  1860,85,2,14053  1860,90,1,7232  1860,90,2,6622  1870,0,1,2800083  1870,0,2,2717102  1870,5,1,2428469  1870,5,2,2393680  1870,10,1,2427341  1870,10,2,2342670  1870,15,1,1958390  1870,15,2,2077248  1870,20,1,1805303  1870,20,2,1909382  1870,25,1,1509059  1870,25,2,1574285  1870,30,1,1251534  1870,30,2,1275629  1870,35,1,1185336  1870,35,2,1137490  1870,40,1,968861  1870,40,2,944401  1870,45,1,852672  1870,45,2,747916  1870,50,1,736387  1870,50,2,637801  1870,55,1,486036  1870,55,2,407819  1870,60,1,399264  1870,60,2,374801  1870,65,1,260829  1870,65,2,239080  1870,70,1,173364  1870,70,2,165501  1870,75,1,86929  1870,75,2,89540  1870,80,1,47427  1870,80,2,54190  1870,85,1,15891  1870,85,2,19302  1870,90,1,8649  1870,90,2,13068  1880,0,1,3533662  1880,0,2,3421597  1880,5,1,3297503  1880,5,2,3179142  1880,10,1,2911924  1880,10,2,2813550  1880,15,1,2457734  1880,15,2,2527818  1880,20,1,2547780  1880,20,2,2512803  1880,25,1,2119393  1880,25,2,1974241  1880,30,1,1749107  1880,30,2,1596772  1880,35,1,1540772  1880,35,2,1483717  1880,40,1,1237347  1880,40,2,1239435  1880,45,1,1065973  1880,45,2,1003711  1880,50,1,964484  1880,50,2,863012  1880,55,1,679147  1880,55,2,594843  1880,60,1,580298  1880,60,2,526956  1880,65,1,369398  1880,65,2,346303  1880,70,1,255422  1880,70,2,251860  1880,75,1,141628  1880,75,2,143513  1880,80,1,67526  1880,80,2,77290  1880,85,1,22437  1880,85,2,31227  1880,90,1,10272  1880,90,2,15451  1900,0,1,4619544  1900,0,2,4589196  1900,5,1,4465783  1900,5,2,4390483  1900,10,1,4057669  1900,10,2,4001749  1900,15,1,3774846  1900,15,2,3801743  1900,20,1,3694038  1900,20,2,3751061  1900,25,1,3389280  1900,25,2,3236056  1900,30,1,2918964  1900,30,2,2665174  1900,35,1,2633883  1900,35,2,2347737  1900,40,1,2261070  1900,40,2,2004987  1900,45,1,1868413  1900,45,2,1648025  1900,50,1,1571038  1900,50,2,1411981  1900,55,1,1161908  1900,55,2,1064632  1900,60,1,916571  1900,60,2,887508  1900,65,1,672663  1900,65,2,640212  1900,70,1,454747  1900,70,2,440007  1900,75,1,268211  1900,75,2,265879  1900,80,1,127435  1900,80,2,132449  1900,85,1,44008  1900,85,2,48614  1900,90,1,15164  1900,90,2,20093  1910,0,1,5296823  1910,0,2,5287477  1910,5,1,4991803  1910,5,2,4866139  1910,10,1,4650747  1910,10,2,4471887  1910,15,1,4566154  1910,15,2,4592269  1910,20,1,4637632  1910,20,2,4447683  1910,25,1,4257755  1910,25,2,3946153  1910,30,1,3658125  1910,30,2,3295220  1910,35,1,3427518  1910,35,2,3088990  1910,40,1,2860229  1910,40,2,2471267  1910,45,1,2363801  1910,45,2,2114930  1910,50,1,2126516  1910,50,2,1773592  1910,55,1,1508358  1910,55,2,1317651  1910,60,1,1189421  1910,60,2,1090697  1910,65,1,850159  1910,65,2,813868  1910,70,1,557936  1910,70,2,547623  1910,75,1,322679  1910,75,2,350900  1910,80,1,161715  1910,80,2,174315  1910,85,1,59699  1910,85,2,62725  1910,90,1,23929  1910,90,2,28965  1920,0,1,5934792  1920,0,2,5694244  1920,5,1,5789008  1920,5,2,5693960  1920,10,1,5401156  1920,10,2,5293057  1920,15,1,4724365  1920,15,2,4779936  1920,20,1,4549411  1920,20,2,4742632  1920,25,1,4565066  1920,25,2,4529382  1920,30,1,4110771  1920,30,2,3982426  1920,35,1,4081543  1920,35,2,3713810  1920,40,1,3321923  1920,40,2,3059757  1920,45,1,3143891  1920,45,2,2669089  1920,50,1,2546035  1920,50,2,2200491  1920,55,1,1880975  1920,55,2,1674672  1920,60,1,1587549  1920,60,2,1382877  1920,65,1,1095956  1920,65,2,989901  1920,70,1,714618  1920,70,2,690097  1920,75,1,417292  1920,75,2,439465  1920,80,1,187000  1920,80,2,211110  1920,85,1,75991  1920,85,2,92829  1920,90,1,22398  1920,90,2,32085  1930,0,1,5875250  1930,0,2,5662530  1930,5,1,6542592  1930,5,2,6129561  1930,10,1,6064820  1930,10,2,5986529  1930,15,1,5709452  1930,15,2,5769587  1930,20,1,5305992  1930,20,2,5565382  1930,25,1,4929853  1930,25,2,5050229  1930,30,1,4424408  1930,30,2,4455213  1930,35,1,4576531  1930,35,2,4593776  1930,40,1,4075139  1930,40,2,3754022  1930,45,1,3633152  1930,45,2,3396558  1930,50,1,3128108  1930,50,2,2809191  1930,55,1,2434077  1930,55,2,2298614  1930,60,1,1927564  1930,60,2,1783515  1930,65,1,1397275  1930,65,2,1307312  1930,70,1,919045  1930,70,2,918509  1930,75,1,536375  1930,75,2,522716  1930,80,1,246708  1930,80,2,283579  1930,85,1,88978  1930,85,2,109210  1930,90,1,30338  1930,90,2,43483  1940,0,1,5294628  1940,0,2,5124653  1940,5,1,5468378  1940,5,2,5359099  1940,10,1,5960416  1940,10,2,5868532  1940,15,1,6165109  1940,15,2,6193701  1940,20,1,5682414  1940,20,2,5896002  1940,25,1,5438166  1940,25,2,5664244  1940,30,1,5040048  1940,30,2,5171522  1940,35,1,4724804  1940,35,2,4791809  1940,40,1,4437392  1940,40,2,4394061  1940,45,1,4190187  1940,45,2,4050290  1940,50,1,3785735  1940,50,2,3488396  1940,55,1,2972069  1940,55,2,2810000  1940,60,1,2370232  1940,60,2,2317790  1940,65,1,1897678  1940,65,2,1911117  1940,70,1,1280023  1940,70,2,1287711  1940,75,1,713875  1940,75,2,764915  1940,80,1,359418  1940,80,2,414761  1940,85,1,127303  1940,85,2,152131  1940,90,1,42263  1940,90,2,58119  1950,0,1,8211806  1950,0,2,7862267  1950,5,1,6706601  1950,5,2,6450863  1950,10,1,5629744  1950,10,2,5430835  1950,15,1,5264129  1950,15,2,5288742  1950,20,1,5573308  1950,20,2,5854227  1950,25,1,6007254  1950,25,2,6317332  1950,30,1,5676022  1950,30,2,5895178  1950,35,1,5511364  1950,35,2,5696261  1950,40,1,5076985  1950,40,2,5199224  1950,45,1,4533177  1950,45,2,4595842  1950,50,1,4199164  1950,50,2,4147295  1950,55,1,3667351  1950,55,2,3595158  1950,60,1,3035038  1950,60,2,3009768  1950,65,1,2421234  1950,65,2,2548250  1950,70,1,1627920  1950,70,2,1786831  1950,75,1,1006530  1950,75,2,1148469  1950,80,1,511727  1950,80,2,637717  1950,85,1,182821  1950,85,2,242798  1950,90,1,54836  1950,90,2,90766  1960,0,1,10374975  1960,0,2,10146999  1960,5,1,9495503  1960,5,2,9250741  1960,10,1,8563700  1960,10,2,8310764  1960,15,1,6620902  1960,15,2,6617493  1960,20,1,5268384  1960,20,2,5513495  1960,25,1,5311805  1960,25,2,5548259  1960,30,1,5801342  1960,30,2,6090862  1960,35,1,6063063  1960,35,2,6431337  1960,40,1,5657943  1960,40,2,5940520  1960,45,1,5345658  1960,45,2,5516028  1960,50,1,4763364  1960,50,2,4928844  1960,55,1,4170581  1960,55,2,4402878  1960,60,1,3405293  1960,60,2,3723839  1960,65,1,2859371  1960,65,2,3268699  1960,70,1,2115763  1960,70,2,2516479  1960,75,1,1308913  1960,75,2,1641371  1960,80,1,619923  1960,80,2,856952  1960,85,1,253245  1960,85,2,384572  1960,90,1,75908  1960,90,2,135774  1970,0,1,8685121  1970,0,2,8326887  1970,5,1,10411131  1970,5,2,10003293  1970,10,1,10756403  1970,10,2,10343538  1970,15,1,9605399  1970,15,2,9414284  1970,20,1,7729202  1970,20,2,8341830  1970,25,1,6539301  1970,25,2,6903041  1970,30,1,5519879  1970,30,2,5851441  1970,35,1,5396732  1970,35,2,5708021  1970,40,1,5718538  1970,40,2,6129319  1970,45,1,5794120  1970,45,2,6198742  1970,50,1,5298312  1970,50,2,5783817  1970,55,1,4762911  1970,55,2,5222164  1970,60,1,4037643  1970,60,2,4577251  1970,65,1,3142606  1970,65,2,3894827  1970,70,1,2340826  1970,70,2,3138009  1970,75,1,1599269  1970,75,2,2293376  1970,80,1,886155  1970,80,2,1417553  1970,85,1,371123  1970,85,2,658511  1970,90,1,186502  1970,90,2,314929  1980,0,1,8439366  1980,0,2,8081854  1980,5,1,8680730  1980,5,2,8275881  1980,10,1,9452338  1980,10,2,9048483  1980,15,1,10698856  1980,15,2,10410271  1980,20,1,10486776  1980,20,2,10614947  1980,25,1,9624053  1980,25,2,9827903  1980,30,1,8705835  1980,30,2,8955225  1980,35,1,6852069  1980,35,2,7134239  1980,40,1,5692148  1980,40,2,5953910  1980,45,1,5342469  1980,45,2,5697543  1980,50,1,5603709  1980,50,2,6110117  1980,55,1,5485098  1980,55,2,6160229  1980,60,1,4696140  1980,60,2,5456885  1980,65,1,3893510  1980,65,2,4896947  1980,70,1,2857774  1980,70,2,3963441  1980,75,1,1840438  1980,75,2,2951759  1980,80,1,1012886  1980,80,2,1919292  1980,85,1,472338  1980,85,2,1023115  1980,90,1,204148  1980,90,2,499046  1990,0,1,9307465  1990,0,2,8894007  1990,5,1,9274732  1990,5,2,8799955  1990,10,1,8782542  1990,10,2,8337284  1990,15,1,9020572  1990,15,2,8590991  1990,20,1,9436188  1990,20,2,9152644  1990,25,1,10658027  1990,25,2,10587292  1990,30,1,11028712  1990,30,2,11105750  1990,35,1,9853933  1990,35,2,10038644  1990,40,1,8712632  1990,40,2,8928252  1990,45,1,6848082  1990,45,2,7115129  1990,50,1,5553992  1990,50,2,5899925  1990,55,1,4981670  1990,55,2,5460506  1990,60,1,4953822  1990,60,2,5663205  1990,65,1,4538398  1990,65,2,5594108  1990,70,1,3429420  1990,70,2,4610222  1990,75,1,2344932  1990,75,2,3723980  1990,80,1,1342996  1990,80,2,2545730  1990,85,1,588790  1990,85,2,1419494  1990,90,1,238459  1990,90,2,745146  2000,0,1,9735380  2000,0,2,9310714  2000,5,1,10552146  2000,5,2,10069564  2000,10,1,10563233  2000,10,2,10022524  2000,15,1,10237419  2000,15,2,9692669  2000,20,1,9731315  2000,20,2,9324244  2000,25,1,9659493  2000,25,2,9518507  2000,30,1,10205879  2000,30,2,10119296  2000,35,1,11475182  2000,35,2,11635647  2000,40,1,11320252  2000,40,2,11488578  2000,45,1,9925006  2000,45,2,10261253  2000,50,1,8507934  2000,50,2,8911133  2000,55,1,6459082  2000,55,2,6921268  2000,60,1,5123399  2000,60,2,5668961  2000,65,1,4453623  2000,65,2,4804784  2000,70,1,3792145  2000,70,2,5184855  2000,75,1,2912655  2000,75,2,4355644  2000,80,1,1902638  2000,80,2,3221898  2000,85,1,970357  2000,85,2,1981156  2000,90,1,336303  2000,90,2,1064581

齿轮图

效果图:

JavaScript代码:

<!DOCTYPE html>  <meta charset="utf-8">  <style>    body {    font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;    width: 960px;    height: 500px;    position: relative;  }    form {    position: absolute;    top: 1em;    left: 1em;  }    path {    fill-rule: evenodd;    stroke: #333;    stroke-width: 2px;  }    .sun path {    fill: #6baed6;  }    .planet path {    fill: #9ecae1;  }    .annulus path {    fill: #c6dbef;  }    </style>  <form>    <input type="radio" name="reference" id="ref-annulus">    <label for="ref-annulus">Annulus</label><br>    <input type="radio" name="reference" id="ref-planet" checked>    <label for="ref-planet">Planets</label><br>    <input type="radio" name="reference" id="ref-sun">    <label for="ref-sun">Sun</label>  </form>  <script src="http://d3js.org/d3.v3.min.js"></script>  <script>    var width = 960,      height = 500,      radius = 80,      x = Math.sin(2 * Math.PI / 3),      y = Math.cos(2 * Math.PI / 3);    var offset = 0,      speed = 4,      start = Date.now();    var svg = d3.select("body").append("svg")      .attr("width", width)      .attr("height", height)    .append("g")      .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")scale(.55)")    .append("g");    var frame = svg.append("g")      .datum({radius: Infinity});    frame.append("g")      .attr("class", "annulus")      .datum({teeth: 80, radius: -radius * 5, annulus: true})    .append("path")      .attr("d", gear);    frame.append("g")      .attr("class", "sun")      .datum({teeth: 16, radius: radius})    .append("path")      .attr("d", gear);    frame.append("g")      .attr("class", "planet")      .attr("transform", "translate(0,-" + radius * 3 + ")")      .datum({teeth: 32, radius: -radius * 2})    .append("path")      .attr("d", gear);    frame.append("g")      .attr("class", "planet")      .attr("transform", "translate(" + -radius * 3 * x + "," + -radius * 3 * y + ")")      .datum({teeth: 32, radius: -radius * 2})    .append("path")      .attr("d", gear);    frame.append("g")      .attr("class", "planet")      .attr("transform", "translate(" + radius * 3 * x + "," + -radius * 3 * y + ")")      .datum({teeth: 32, radius: -radius * 2})    .append("path")      .attr("d", gear);    d3.selectAll("input[name=reference]")      .data([radius * 5, Infinity, -radius])      .on("change", function(radius1) {        var radius0 = frame.datum().radius, angle = (Date.now() - start) * speed;        frame.datum({radius: radius1});        svg.attr("transform", "rotate(" + (offset += angle / radius0 - angle / radius1) + ")");      });    d3.selectAll("input[name=speed]")      .on("change", function() { speed = +this.value; });    function gear(d) {    var n = d.teeth,        r2 = Math.abs(d.radius),        r0 = r2 - 8,        r1 = r2 + 8,        r3 = d.annulus ? (r3 = r0, r0 = r1, r1 = r3, r2 + 20) : 20,        da = Math.PI / n,        a0 = -Math.PI / 2 + (d.annulus ? Math.PI / n : 0),        i = -1,        path = ["M", r0 * Math.cos(a0), ",", r0 * Math.sin(a0)];    while (++i < n) path.push(        "A", r0, ",", r0, " 0 0,1 ", r0 * Math.cos(a0 += da), ",", r0 * Math.sin(a0),        "L", r2 * Math.cos(a0), ",", r2 * Math.sin(a0),        "L", r1 * Math.cos(a0 += da / 3), ",", r1 * Math.sin(a0),        "A", r1, ",", r1, " 0 0,1 ", r1 * Math.cos(a0 += da / 3), ",", r1 * Math.sin(a0),        "L", r2 * Math.cos(a0 += da / 3), ",", r2 * Math.sin(a0),        "L", r0 * Math.cos(a0), ",", r0 * Math.sin(a0));    path.push("M0,", -r3, "A", r3, ",", r3, " 0 0,0 0,", r3, "A", r3, ",", r3, " 0 0,0 0,", -r3, "Z");    return path.join("");  }    d3.timer(function() {    var angle = (Date.now() - start) * speed,        transform = function(d) { return "rotate(" + angle / d.radius + ")"; };    frame.selectAll("path").attr("transform", transform);    frame.attr("transform", transform); // frame of reference  });    </script>

更多D3相关的内容,可以前往其官方网站查阅。

本文链接:http://www.codeceo.com/article/javascript-d3-js.html
本文作者:码农网 – 小峰