变换

单元素动画

  1. <script type="text/javascript">
  2. var body = d3.select("body"),
  3. duration = 5000;
  4. body.append("div")
  5. .classed("box", true)
  6. .style("background-color", "#e9967a")
  7. .transition()
  8. .duration(duration)
  9. .style("background-color", "#add8e6")
  10. .style("margin-left", "600px")
  11. .style("width", "100px")
  12. .style("height", "100px");
  13. </script>

1.gif

如果没有起始值或者结束值,D3 会自动计算一个值作为过渡的有起始值或者结束值。

多元素动画

  1. <script type="text/javascript">
  2. var id= 0,
  3. data = [],
  4. duration = 500,
  5. chartHeight = 100,
  6. chartWidth = 680;
  7. for(var i = 0; i < 20; i++) push(data);
  8. function render(data) {
  9. var selection = d3.select("body")
  10. .selectAll("div.v-bar")
  11. .data(data, function(d){return d.id;});
  12. // enter
  13. selection.enter()
  14. .append("div")
  15. .attr("class", "v-bar")
  16. .style("z-index", "0")
  17. .style("position", "fixed")
  18. .style("top", chartHeight + "px")
  19. .style("left", function(d, i){
  20. return barLeft(i+1) + "px";
  21. })
  22. .style("height", "0px")
  23. .append("span");
  24. // update
  25. selection
  26. .transition().duration(duration)
  27. .style("top", function (d) {
  28. return chartHeight - barHeight(d) + "px";
  29. })
  30. .style("left", function(d, i){
  31. return barLeft(i) + "px";
  32. })
  33. .style("height", function (d) {
  34. return barHeight(d) + "px";
  35. })
  36. .select("span")
  37. .text(function (d) {return d.value;});
  38. // exit
  39. selection.exit()
  40. .transition().duration(duration)
  41. .style("left", function(d, i){
  42. return barLeft(-1) + "px";
  43. })
  44. .remove();
  45. }
  46. function push(data) {
  47. data.push({
  48. id: ++id,
  49. value: Math.round(Math.random() * chartHeight)
  50. });
  51. }
  52. function barLeft(i) {
  53. return i * (30 + 2);
  54. }
  55. function barHeight(d) {
  56. return d.value;
  57. }
  58. setInterval(function () {
  59. data.shift();
  60. push(data);
  61. render(data);
  62. }, 2000);
  63. render(data);
  64. d3.select("body")
  65. .append("div")
  66. .attr("class", "baseline")
  67. .style("position", "fixed")
  68. .style("z-index", "1")
  69. .style("top", chartHeight + "px")
  70. .style("left", "0px")
  71. .style("width", chartWidth + "px");
  72. </script>

1.gif

缓动动画

  1. <script type="text/javascript">
  2. var data = [
  3. {name: 'Linear', fn: d3.easeLinear},
  4. {name: 'Cubic', fn: d3.easeCubic},
  5. {name: 'CubicIn', fn: d3.easeCubicIn},
  6. {name: 'Sin', fn: d3.easeSin},
  7. {name: 'SinIn', fn: d3.easeSinIn},
  8. {name: 'Exp', fn: d3.easeExp},
  9. {name: 'Circle', fn: d3.easeCircle},
  10. {name: 'Back', fn: d3.easeBack},
  11. {name: 'Bounce', fn: d3.easeBounce},
  12. {name: 'Elastic', fn: d3.easeElastic},
  13. {name: 'Custom', fn: function(t){ return t * t; }}
  14. ],
  15. colors = d3.scaleOrdinal(d3.schemeCategory20);
  16. d3.select("body").selectAll("div")
  17. .data(data)
  18. .enter()
  19. .append("div")
  20. .attr("class", "fixed-cell")
  21. .style("top", function (d, i) {
  22. return i * 40 + "px";
  23. })
  24. .style("background-color", function (d, i) {
  25. return colors(i);
  26. })
  27. .style("color", "white")
  28. .style("left", "500px")
  29. .text(function (d) {
  30. return d.name;
  31. });
  32. d3.selectAll("div").each(function(d){
  33. d3.select(this)
  34. .transition().ease(d.fn) // <-D
  35. .duration(1500)
  36. .style("left", "10px");
  37. });
  38. </script>

1.gif

使用中间帧计算

  1. <script type="text/javascript">
  2. var body = d3.select("body"), duration = 5000;
  3. body.append("div").append("input")
  4. .attr("type", "button")
  5. .attr("class", "countdown")
  6. .attr("value", "0")
  7. .style("width", "150px")
  8. .transition().duration(duration).ease(d3.easeLinear)
  9. .style("width", "400px")
  10. .attr("value", "9");
  11. body.append("div").append("input")
  12. .attr("type", "button")
  13. .attr("class", "countdown")
  14. .attr("value", "0")
  15. .transition().duration(duration).ease(d3.easeLinear)
  16. .styleTween("width", widthTween)
  17. .attrTween("value", valueTween);
  18. function widthTween(a){
  19. var interpolate = d3.scaleQuantize()
  20. .domain([0, 1])
  21. .range([150, 200, 250, 350, 400]);
  22. return function(t){
  23. return interpolate(t) + "px";
  24. };
  25. }
  26. function valueTween(){
  27. var interpolate = d3.scaleQuantize()
  28. .domain([0, 1])
  29. .range([1, 2, 3, 4, 5, 6, 7, 8, 9]);
  30. return function(t){
  31. return interpolate(t);
  32. };
  33. }
  34. </script>

1.gif

在 D3 中,tween 函数是一个工厂函数,用来构造执行中间帧的最终函数。

使用级联过渡

  1. <script type="text/javascript">
  2. var body = d3.select("body");
  3. function teleport(s){
  4. s.transition().duration(1000)
  5. .style("width", "200px")
  6. .style("height", "1px")
  7. .transition().duration(500)
  8. .style("left", "600px")
  9. .transition().duration(1000)
  10. .style("left", "800px")
  11. .style("height", "80px")
  12. .style("width", "80px");
  13. }
  14. body.append("div")
  15. .style("position", "fixed")
  16. .style("background-color", "steelblue")
  17. .style("left", "10px")
  18. .style("width", "80px")
  19. .style("height", "80px")
  20. .call(teleport);
  21. </script>

1.gif

使用选择性过渡

  1. <script type="text/javascript">
  2. var data = ["Cat", "Dog", "Cat", "Dog", "Cat", "Dog", "Cat", "Dog"],
  3. duration = 1500;
  4. d3.select("body").selectAll("div")
  5. .data(data)
  6. .enter()
  7. .append("div")
  8. .attr("class", "fixed-cell")
  9. .style("top", function (d, i) {
  10. return i * 40 + "px";
  11. })
  12. .style("background-color", "steelblue")
  13. .style("color", "white")
  14. .style("left", "500px")
  15. .text(function (d) {
  16. return d;
  17. })
  18. .transition()
  19. .duration(duration)
  20. .style("left", "10px")
  21. .filter(function(d){return d == "Cat";})
  22. .transition()
  23. .duration(duration)
  24. .style("left", "500px");
  25. </script>

1.gif

监听过渡事件

  1. <script type="text/javascript">
  2. var body = d3.select("body"), duration = 3000;
  3. var div = body.append("div")
  4. .classed("box", true)
  5. .style("background-color", "steelblue")
  6. .style("color", "white")
  7. .text("waiting")
  8. .transition().duration(duration)
  9. .delay(1000)
  10. .on("start", function(){
  11. d3.select(this).text(function (d, i) {
  12. return "transitioning";
  13. });
  14. })
  15. .on("end", function(){
  16. d3.select(this).text(function (d, i) {
  17. return "done";
  18. });
  19. })
  20. .style("margin-left", "600px");
  21. </script>

1.gif

使用定时器

  1. <script type="text/javascript">
  2. var body = d3.select("body");
  3. var countdown = body.append("div").append("input");
  4. countdown.attr("type", "button")
  5. .attr("class", "countdown")
  6. .attr("value", "0");
  7. function countUp(target){
  8. var t = d3.timer(function(){
  9. var value = countdown.attr("value");
  10. if( value == target ) {
  11. t.stop();
  12. return true;
  13. }
  14. countdown.attr("value", ++value);
  15. });
  16. }
  17. function reset(){
  18. countdown.attr("value", 0);
  19. }
  20. </script>
  21. <div class="control-group">
  22. <button onclick="countUp(100)">
  23. Start
  24. </button>
  25. <button onclick="reset()">
  26. Clear
  27. </button>
  28. </div>

1.gif

形状

什么是 SVG

  • 矢量:矢量的图形更适合可视化
  • 可伸缩性:任意尺寸和放大程度下都不会失真
  • 可读性
  • 开放标准
  • 应用广泛
  • 互用性
  • 轻量

创建简单图形

  1. <style>
  2. svg line{
  3. stroke: grey;
  4. stroke-width: 2;
  5. }
  6. svg circle{
  7. stroke: red;
  8. fill: none;
  9. stroke-width: 2;
  10. }
  11. svg rect{
  12. stroke: steelblue;
  13. fill: none;
  14. stroke-width: 2;
  15. }
  16. svg polygon{
  17. stroke: green;
  18. fill: none;
  19. stroke-width: 2;
  20. }
  21. </style>
  22. <script type="text/javascript">
  23. var width = 600,
  24. height = 500;
  25. var svg = d3.select("body").append("svg");
  26. svg.attr("height", height)
  27. .attr("width", width);
  28. svg.append("line")
  29. .attr("x1", 0)
  30. .attr("y1", 200)
  31. .attr("x2", 100)
  32. .attr("y2", 100);
  33. svg.append("circle")
  34. .attr("cx", 200)
  35. .attr("cy", 150)
  36. .attr("r", 50);
  37. svg.append("rect")
  38. .attr("x", 300)
  39. .attr("y", 100)
  40. .attr("width", 100)
  41. .attr("height", 100)
  42. .attr("rx", 5);
  43. svg.append("polygon")
  44. .attr("points", "450,200 500,100 550,200");
  45. </script>

image.png

D3 还支持椭圆(ellipse)和折线(ployline)。

使用线条生成器

  1. <script type="text/javascript">
  2. var width = 500,
  3. height = 500,
  4. margin = 50,
  5. x = d3.scaleLinear()
  6. .domain([0, 10])
  7. .range([margin, width - margin]),
  8. y = d3.scaleLinear()
  9. .domain([0, 10])
  10. .range([height - margin, margin]);
  11. var data = [
  12. [
  13. {x: 0, y: 5},{x: 1, y: 9},{x: 2, y: 7},
  14. {x: 3, y: 5},{x: 4, y: 3},{x: 6, y: 4},
  15. {x: 7, y: 2},{x: 8, y: 3},{x: 9, y: 2}
  16. ],
  17. d3.range(10).map(function(i){
  18. return {x: i, y: Math.sin(i) + 5};
  19. })
  20. ];
  21. var line = d3.line()
  22. .x(function(d){return x(d.x);})
  23. .y(function(d){return y(d.y);});
  24. var svg = d3.select("body").append("svg");
  25. svg.attr("height", height)
  26. .attr("width", width);
  27. svg.selectAll("path")
  28. .data(data)
  29. .enter()
  30. .append("path")
  31. .attr("class", "line")
  32. .attr("d", function(d){return line(d);});
  33. renderAxes(svg);
  34. function renderAxes(svg){
  35. var xAxis = d3.axisBottom()
  36. .scale(x.range([0, quadrantWidth()]));
  37. var yAxis = d3.axisLeft()
  38. .scale(y.range([quadrantHeight(), 0]));
  39. svg.append("g")
  40. .attr("class", "axis")
  41. .attr("transform", function(){
  42. return "translate(" + xStart()
  43. + "," + yStart() + ")";
  44. })
  45. .call(xAxis);
  46. svg.append("g")
  47. .attr("class", "axis")
  48. .attr("transform", function(){
  49. return "translate(" + xStart()
  50. + "," + yEnd() + ")";
  51. })
  52. .call(yAxis);
  53. }
  54. function xStart(){
  55. return margin;
  56. }
  57. function yStart(){
  58. return height - margin;
  59. }
  60. function xEnd(){
  61. return width - margin;
  62. }
  63. function yEnd(){
  64. return margin;
  65. }
  66. function quadrantWidth(){
  67. return width - 2 * margin;
  68. }
  69. function quadrantHeight(){
  70. return height - 2 * margin;
  71. }
  72. </script>

image.png

使用曲线

  1. <script type="text/javascript">
  2. var width = 500,
  3. height = 500,
  4. margin = 30,
  5. x = d3.scaleLinear()
  6. .domain([0, 10])
  7. .range([margin, width - margin]),
  8. y = d3.scaleLinear()
  9. .domain([0, 10])
  10. .range([height - margin, margin]);
  11. var data = [
  12. [
  13. {x: 0, y: 5},{x: 1, y: 9},{x: 2, y: 7},
  14. {x: 3, y: 5},{x: 4, y: 3},{x: 6, y: 4},
  15. {x: 7, y: 2},{x: 8, y: 3},{x: 9, y: 2}
  16. ],
  17. d3.range(10).map(function(i){
  18. return {x: i, y: Math.sin(i) + 5};
  19. })
  20. ];
  21. var svg = d3.select("body").append("svg");
  22. svg.attr("height", height)
  23. .attr("width", width);
  24. renderAxes(svg);
  25. render(d3.curveLinear);
  26. renderDots(svg);
  27. function render(mode){
  28. var line = d3.line()
  29. .x(function(d){return x(d.x);})
  30. .y(function(d){return y(d.y);})
  31. .curve(mode);
  32. svg.selectAll("path.line")
  33. .data(data)
  34. .enter()
  35. .append("path")
  36. .attr("class", "line");
  37. svg.selectAll("path.line")
  38. .data(data)
  39. .attr("d", function(d){return line(d);});
  40. }
  41. function renderDots(svg){
  42. data.forEach(function(list){
  43. svg.append("g").selectAll("circle")
  44. .data(list)
  45. .enter().append("circle")
  46. .attr("class", "dot")
  47. .attr("cx", function(d) { return x(d.x); })
  48. .attr("cy", function(d) { return y(d.y); })
  49. .attr("r", 4.5);
  50. });
  51. }
  52. function renderAxes(svg){
  53. var xAxis = d3.axisBottom()
  54. .scale(d3.scaleLinear().range([0, quadrantWidth()]));
  55. var yAxis = d3.axisLeft()
  56. .scale(d3.scaleLinear().range([quadrantHeight(), 0]));
  57. svg.append("g")
  58. .attr("class", "axis")
  59. .attr("transform", function(){
  60. return "translate(" + xStart() + "," + yStart() + ")";
  61. })
  62. .call(xAxis);
  63. svg.append("g")
  64. .attr("class", "axis")
  65. .attr("transform", function(){
  66. return "translate(" + xStart() + "," + yEnd() + ")";
  67. })
  68. .call(yAxis);
  69. }
  70. function xStart(){
  71. return margin;
  72. }
  73. function yStart(){
  74. return height - margin;
  75. }
  76. function xEnd(){
  77. return width - margin;
  78. }
  79. function yEnd(){
  80. return margin;
  81. }
  82. function quadrantWidth(){
  83. return width - 2 * margin;
  84. }
  85. function quadrantHeight(){
  86. return height - 2 * margin;
  87. }
  88. </script>
  89. <h4>Curve Mode:</h4>
  90. <div class="control-group">
  91. <button onclick="render(d3.curveLinear)">linear</button>
  92. <button onclick="render(d3.curveLinearClosed)">linear closed</button>
  93. <button onclick="render(d3.curveStepBefore)">step before</button>
  94. <button onclick="render(d3.curveStepAfter)">step after</button>
  95. <button onclick="render(d3.curveBasis)">basis</button>
  96. <button onclick="render(d3.curveBasisOpen)">basis open</button>
  97. <button onclick="render(d3.curveBasisClosed)">basis closed</button>
  98. </div>
  99. <div class="control-group">
  100. <button onclick="render(d3.curveBundle)">bundle</button>
  101. <button onclick="render(d3.curveCardinal)">cardinal</button>
  102. <button onclick="render(d3.curveCardinalOpen)">cardinal open</button>
  103. <button onclick="render(d3.curveCardinalClosed)">cardinal closed</button>
  104. <button onclick="render(d3.curveMonotoneY)">monotone</button>
  105. <button onclick="render(d3.curveCatmullRom)">CatmullRom</button>
  106. </div>

image.png

更改线条的张力

  1. <script type="text/javascript">
  2. var width = 500,
  3. height = 500,
  4. margin = 30,
  5. duration = 500,
  6. x = d3.scaleLinear()
  7. .domain([0, 10])
  8. .range([margin, width - margin]),
  9. y = d3.scaleLinear()
  10. .domain([0, 1])
  11. .range([height - margin, margin]);
  12. var data = d3.range(10).map(function(i){
  13. return {x: i, y: (Math.sin(i * 3) + 1) / 2};
  14. });
  15. var svg = d3.select("body").append("svg");
  16. svg.attr("height", height)
  17. .attr("width", width);
  18. renderAxes(svg);
  19. render(1);
  20. function render(tension){
  21. var line = d3.line()
  22. .curve(d3.curveCardinal.tension(tension))
  23. .x(function(d){return x(d.x);})
  24. .y(function(d){return y(d.y);});
  25. svg.selectAll("path.line")
  26. .data([tension])
  27. .enter()
  28. .append("path")
  29. .attr("class", "line");
  30. svg.selectAll("path.line")
  31. .data([tension])
  32. .transition().duration(duration)
  33. .ease(d3.easeLinear)
  34. .attr("d", function(d){
  35. return line(data);
  36. });
  37. svg.selectAll("circle")
  38. .data(data)
  39. .enter().append("circle")
  40. .attr("class", "dot")
  41. .attr("cx", function(d) { return x(d.x); })
  42. .attr("cy", function(d) { return y(d.y); })
  43. .attr("r", 4.5);
  44. }
  45. function renderAxes(svg){
  46. var xAxis = d3.axisBottom()
  47. .scale(d3.scaleLinear().range([0, quadrantWidth()]));
  48. var yAxis = d3.axisLeft()
  49. .scale(d3.scaleLinear().range([quadrantHeight(), 0]));
  50. svg.append("g")
  51. .attr("class", "axis")
  52. .attr("transform", function(){
  53. return "translate(" + xStart() + "," + yStart() + ")";
  54. })
  55. .call(xAxis);
  56. svg.append("g")
  57. .attr("class", "axis")
  58. .attr("transform", function(){
  59. return "translate(" + xStart() + "," + yEnd() + ")";
  60. })
  61. .call(yAxis);
  62. }
  63. function xStart(){
  64. return margin;
  65. }
  66. function yStart(){
  67. return height - margin;
  68. }
  69. function xEnd(){
  70. return width - margin;
  71. }
  72. function yEnd(){
  73. return margin;
  74. }
  75. function quadrantWidth(){
  76. return width - 2 * margin;
  77. }
  78. function quadrantHeight(){
  79. return height - 2 * margin;
  80. }
  81. </script>
  82. <h4>Line Tension:</h4>
  83. <div class="control-group">
  84. <button onclick="render(0)">0</button>
  85. <button onclick="render(0.2)">0.2</button>
  86. <button onclick="render(0.4)">0.4</button>
  87. <button onclick="render(0.6)">0.6</button>
  88. <button onclick="render(0.8)">0.8</button>
  89. <button onclick="render(1)">1</button>
  90. </div>

image.png

使用区域生成器

  1. <script type="text/javascript">
  2. var width = 500,
  3. height = 500,
  4. margin = 30,
  5. duration = 500,
  6. x = d3.scaleLinear()
  7. .domain([0, 10])
  8. .range([margin, width - margin]),
  9. y = d3.scaleLinear()
  10. .domain([0, 10])
  11. .range([height - margin, margin]);
  12. var data = d3.range(11).map(function(i){
  13. return {x: i, y: Math.sin(i)*3 + 5};
  14. });
  15. var svg = d3.select("body").append("svg");
  16. svg.attr("height", height)
  17. .attr("width", width);
  18. renderAxes(svg);
  19. render();
  20. renderDots(svg);
  21. function render(){
  22. var line = d3.line()
  23. .x(function(d){return x(d.x);})
  24. .y(function(d){return y(d.y);});
  25. svg.selectAll("path.line")
  26. .data([data])
  27. .enter()
  28. .append("path")
  29. .attr("class", "line");
  30. svg.selectAll("path.line")
  31. .data([data])
  32. .attr("d", function(d){return line(d);});
  33. var area = d3.area()
  34. .x(function(d) { return x(d.x); })
  35. .y0(y(0))
  36. .y1(function(d) { return y(d.y); });
  37. svg.selectAll("path.area")
  38. .data([data])
  39. .enter()
  40. .append("path")
  41. .attr("class", "area")
  42. .attr("d", function(d){return area(d);});
  43. }
  44. function renderDots(svg){
  45. svg.append("g").selectAll("circle")
  46. .data(data)
  47. .enter().append("circle")
  48. .attr("class", "dot")
  49. .attr("cx", function(d) { return x(d.x); })
  50. .attr("cy", function(d) { return y(d.y); })
  51. .attr("r", 4.5);
  52. }
  53. function renderAxes(svg){
  54. var xAxis = d3.axisBottom()
  55. .scale(d3.scaleLinear().range([0, quadrantWidth()]));
  56. var yAxis = d3.axisLeft()
  57. .scale(d3.scaleLinear().range([quadrantHeight(), 0]));
  58. svg.append("g")
  59. .attr("class", "axis")
  60. .attr("transform", function(){
  61. return "translate(" + xStart() + "," + yStart() + ")";
  62. })
  63. .call(xAxis);
  64. svg.append("g")
  65. .attr("class", "axis")
  66. .attr("transform", function(){
  67. return "translate(" + xStart() + "," + yEnd() + ")";
  68. })
  69. .call(yAxis);
  70. }
  71. function xStart(){
  72. return margin;
  73. }
  74. function yStart(){
  75. return height - margin;
  76. }
  77. function xEnd(){
  78. return width - margin;
  79. }
  80. function yEnd(){
  81. return margin;
  82. }
  83. function quadrantWidth(){
  84. return width - 2 * margin;
  85. }
  86. function quadrantHeight(){
  87. return height - 2 * margin;
  88. }
  89. </script>

image.png

使用断面曲线

  1. <script type="text/javascript">
  2. var width = 500,
  3. height = 500,
  4. margin = 30,
  5. x = d3.scaleLinear()
  6. .domain([0, 10])
  7. .range([margin, width - margin]),
  8. y = d3.scaleLinear()
  9. .domain([0, 10])
  10. .range([height - margin, margin]);
  11. var data = d3.range(11).map(function(i){
  12. return {x: i, y: Math.sin(i)*3 + 5};
  13. });
  14. var svg = d3.select("body").append("svg");
  15. svg.attr("height", height)
  16. .attr("width", width);
  17. renderAxes(svg);
  18. render(d3.curveLinear);
  19. renderDots(svg);
  20. function render(mode){
  21. var line = d3.line()
  22. .x(function(d){return x(d.x);})
  23. .y(function(d){return y(d.y);})
  24. .curve(mode);
  25. svg.selectAll("path.line")
  26. .data([data])
  27. .enter()
  28. .append("path")
  29. .attr("class", "line");
  30. svg.selectAll("path.line")
  31. .data([data])
  32. .attr("d", function(d){return line(d);});
  33. var area = d3.area()
  34. .x(function(d) { return x(d.x); })
  35. .y0(y(0))
  36. .y1(function(d) { return y(d.y); })
  37. .curve(mode);
  38. svg.selectAll("path.area")
  39. .data([data])
  40. .enter()
  41. .append("path")
  42. .attr("class", "area")
  43. svg.selectAll("path.area")
  44. .data([data])
  45. .attr("d", function(d){return area(d);});
  46. }
  47. function renderDots(svg){
  48. svg.append("g").selectAll("circle")
  49. .data(data)
  50. .enter().append("circle")
  51. .attr("class", "dot")
  52. .attr("cx", function(d) { return x(d.x); })
  53. .attr("cy", function(d) { return y(d.y); })
  54. .attr("r", 4.5);
  55. }
  56. function renderAxes(svg){
  57. var xAxis = d3.axisBottom()
  58. .scale(d3.scaleLinear().range([0, quadrantWidth()]));
  59. var yAxis = d3.axisLeft()
  60. .scale(d3.scaleLinear().range([quadrantHeight(), 0]));
  61. svg.append("g")
  62. .attr("class", "axis")
  63. .attr("transform", function(){
  64. return "translate(" + xStart() + "," + yStart() + ")";
  65. })
  66. .call(xAxis);
  67. svg.append("g")
  68. .attr("class", "axis")
  69. .attr("transform", function(){
  70. return "translate(" + xStart() + "," + yEnd() + ")";
  71. })
  72. .call(yAxis);
  73. }
  74. function xStart(){
  75. return margin;
  76. }
  77. function yStart(){
  78. return height - margin;
  79. }
  80. function xEnd(){
  81. return width - margin;
  82. }
  83. function yEnd(){
  84. return margin;
  85. }
  86. function quadrantWidth(){
  87. return width - 2 * margin;
  88. }
  89. function quadrantHeight(){
  90. return height - 2 * margin;
  91. }
  92. </script>
  93. <h4>Curve Mode:</h4>
  94. <div class="control-group">
  95. <button onclick="render(d3.curveLinear)">linear</button>
  96. <button onclick="render(d3.curveLinearClosed)">linear closed</button>
  97. <button onclick="render(d3.curveStepBefore)">step before</button>
  98. <button onclick="render(d3.curveStepAfter)">step after</button>
  99. <button onclick="render(d3.curveBasis)">basis</button>
  100. <button onclick="render(d3.curveBasisOpen)">basis open</button>
  101. <button onclick="render(d3.curveBasisClosed)">basis closed</button>
  102. </div>
  103. <div class="control-group">
  104. <button onclick="render(d3.curveBundle)">bundle</button>
  105. <button onclick="render(d3.curveCardinal)">cardinal</button>
  106. <button onclick="render(d3.curveCardinalOpen)">cardinal open</button>
  107. <button onclick="render(d3.curveCardinalClosed)">cardinal closed</button>
  108. <button onclick="render(d3.curveMonotoneY)">monotone</button>
  109. <button onclick="render(d3.curveCatmullRom)">CatmullRom</button>
  110. </div>

image.png

使用圆弧生成器

  1. <script type="text/javascript">
  2. var width = 400,
  3. height = 400,
  4. fullAngle = 2 * Math.PI,
  5. colors = d3.scaleOrdinal(d3.schemeCategory20c);
  6. var svg = d3.select("body").append("svg")
  7. .attr("class", "pie")
  8. .attr("height", height)
  9. .attr("width", width);
  10. function render(innerRadius, endAngle){
  11. if(!endAngle) endAngle = fullAngle;
  12. var data = [
  13. {startAngle: 0, endAngle: 0.1 * endAngle},
  14. {startAngle: 0.1 * endAngle, endAngle: 0.2 * endAngle},
  15. {startAngle: 0.2 * endAngle, endAngle: 0.4 * endAngle},
  16. {startAngle: 0.4 * endAngle, endAngle: 0.6 * endAngle},
  17. {startAngle: 0.6 * endAngle, endAngle: 0.7 * endAngle},
  18. {startAngle: 0.7 * endAngle, endAngle: 0.9 * endAngle},
  19. {startAngle: 0.9 * endAngle, endAngle: endAngle}
  20. ];
  21. var arc = d3.arc().outerRadius(200)
  22. .innerRadius(innerRadius);
  23. svg.select("g").remove();
  24. svg.append("g")
  25. .attr("transform", "translate(200,200)")
  26. .selectAll("path.arc")
  27. .data(data)
  28. .enter()
  29. .append("path")
  30. .attr("class", "arc")
  31. .attr("fill", function(d, i){return colors(i);})
  32. .attr("d", function(d, i){
  33. return arc(d, i);
  34. });
  35. }
  36. render(0);
  37. </script>
  38. <div class="control-group">
  39. <button onclick="render(0)">Circle</button>
  40. <button onclick="render(100)">Annulus(Donut)</button>
  41. <button onclick="render(0, Math.PI)">Circular Sector</button>
  42. <button onclick="render(100, Math.PI)">Annulus Sector</button>
  43. </div>

image.png

实现圆弧过渡

  1. <script type="text/javascript">
  2. var width = 400,
  3. height = 400,
  4. endAngle = 2 * Math.PI,
  5. colors = d3.scaleOrdinal(d3.schemeCategory20c);
  6. var svg = d3.select("body").append("svg")
  7. .attr("class", "pie")
  8. .attr("height", height)
  9. .attr("width", width);
  10. function render(innerRadius) {
  11. var data = [
  12. {startAngle: 0, endAngle: 0.1 * endAngle},
  13. {startAngle: 0.1 * endAngle, endAngle: 0.2 * endAngle},
  14. {startAngle: 0.2 * endAngle, endAngle: 0.4 * endAngle},
  15. {startAngle: 0.4 * endAngle, endAngle: 0.6 * endAngle},
  16. {startAngle: 0.6 * endAngle, endAngle: 0.7 * endAngle},
  17. {startAngle: 0.7 * endAngle, endAngle: 0.9 * endAngle},
  18. {startAngle: 0.9 * endAngle, endAngle: endAngle}
  19. ];
  20. var arc = d3.arc()
  21. .outerRadius(200).innerRadius(innerRadius);
  22. svg.select("g").remove();
  23. svg.append("g")
  24. .attr("transform", "translate(200,200)")
  25. .selectAll("path.arc")
  26. .data(data)
  27. .enter()
  28. .append("path")
  29. .attr("class", "arc")
  30. .attr("fill", function (d, i) {
  31. return colors(i);
  32. })
  33. .transition().duration(1000)
  34. .attrTween("d", function (d) {
  35. var start = {startAngle: 0, endAngle: 0}; // <-A
  36. var interpolate = d3.interpolate(start, d); // <-B
  37. return function (t) {
  38. return arc(interpolate(t)); // <-C
  39. };
  40. });
  41. }
  42. render(100);
  43. </script>

1.gif

参考

【1】Data Visualization and D3.js(视频)
【2】D3 4.x 数据可视化实战手册@[加]朱启
【3】https://github.com/NickQiZhu/d3-cookbook-v2(D3 4.x 数据可视化实战手册 代码)
【4】D3.js 中文文档