d3多圈系列数据图表

时间:2017-03-28 16:55:36

标签: javascript d3.js

enter image description here

如何调整以叠加第二组圆圈?

  var data = [{
    "name": "Twitter",
    "items": [{
      "value": 2000
    }, {
      "value": 3000
    }]
  }, {
    "name": "Facebook",
    "items": [{
      "value": 200
    }, {
      "value": 300
    }]
  }, {
    "name": "Ebay",
    "items": [{
      "value": 1000
    }, {
      "value": 2000
    }]
  }, {
    "name": "Foursquare",
    "items": [{
      "value": 2000
    }, {
      "value": 3000
    }]
  }]

可选择添加其他数据集 - 目标是创建具有不同颜色圆圈的2D金字塔,表示不同的数据集 - 最大的数据集采用基圆。

http://jsfiddle.net/0aqvx66j/4/

function circleMaker() {


    var counter = 0;
    series = 0


    var set = svg.append("g")
      .attr("class", "series" + series);

    set.selectAll("circle")
      .data(data)
      .enter().append("circle")
      .attr("class", "series" + series)
      .attr("cy", 60)
      .attr("cx", function(d, i) {
        if (i) {
          return (counter += Math.sqrt(data[i - 1].items[series].value) + Math.sqrt(data[i].items[series].value));
        } else {
          return counter;
        }
      })
      .attr("fill", function(d, i) {
        var colorArray = ["#00ccff", "#fcdd0a"];
        return colorArray[series];
      })
      .attr("r", function(d) {
        return Math.sqrt(d.items[series].value);
      });

}

最终甚至可能在不同的数据集之间翻转,始终将最大的圆圈作为背景。所以喜欢这个

enter image description here

2 个答案:

答案 0 :(得分:2)

大部分只是在绘制数据之前组织数据。在每个系列中,为每个项目提供索引,然后按值排序。 index属性将告诉我们系列中每个项目的初始位置。每个系列的第一项现在将是最大的价值。使用它为每个系列构建一个偏移量,并将所有这些偏移量相加以形成定位比例。

然后为每个系列制作组元素,使用我们计算的偏移量进行定位。

在每个组中,绘制圆形元素。由于我们对它们进行了分类,因此它们将首先被绘制得最大。 .index属性可用于按系列中的原始位置进行着色。

http://jsfiddle.net/0ht35rpb/2/

var width = 600;
var height = 400;
var svg = d3.select('svg').attr("width", width).attr("height",height);


  var data = [{
    "name": "Twitter",
    "items": [{
      "value": 2000
    }, {
      "value": 3000
    }]
  }, {
    "name": "Facebook",
    "items": [{
      "value": 200
    }, {
      "value": 300
    }]
  }, {
    "name": "Ebay",
    "items": [{
      "value": 2000
    }, {
      "value": 1000
    }]
  }, {
    "name": "Foursquare",
    "items": [{
      "value": 2000
    }, {
      "value": 3000
    },
    {
      "value": 4000
    }]
  }];


  // organise the data. 
  // Insert indices and sort items in each series
  // keep a running total of max circle size in each series
  // for later positioning
  var x = 0;
  var totalWidth = d3.sum (
    data.map (function (series) {
      series.items.forEach (function (item, i) {
            item.index = i;
      });
      series.items.sort (function (a, b) {
        return b.value - a.value;
      });
      var maxr = Math.sqrt(series.items[0].value);
      x += maxr;
      series.xcentre = x;
      x += maxr;
      return maxr * 2;
    })
  );

  // make scales for position and colour
  var scale = d3.scale.linear().domain([0,totalWidth]).range([0, width]);
  var colScale = d3.scale.category10();

  // add a group per series, position the group according to the values and position scale  we calculated above
 var groups = svg.selectAll("g").data(data);
 groups.enter().append("g");
 groups.attr("transform", function(d) {
        return ("translate("+scale(d.xcentre)+",0)");
 });

 // then add circles per series, biggest first as items are sorted
 // colour according to index (the property we inserted previously so we can
 // keep track of their original position in the series)
 var circles = groups.selectAll("circle").data(function(d) { return d.items;}, function(d) { return d.index; });
 circles.enter().append("circle").attr("cy", height/2).attr("cx",0);

 circles
    .attr("r", function(d) { return scale(Math.sqrt (d.value)); })
  .style ("fill", function (d) { return colScale(d.index); });

答案 1 :(得分:1)

mgraham的回答太棒了!但是因为我已经把它写出来了(然后不得不去参加一个会议),这就是我将如何编写代码:

$(document).ready(function() {


  var el = $('.serieschart');
  var w = el.data("width");
  var h = el.data("height");


  var margin = {
    top: 65,
    right: 90,
    bottom: 5,
    left: 150
  };

  var svg = d3.select(el[0]).append("svg")
    .attr("class", "series")
    .attr("width", w + margin.left + margin.right)
    .attr("height", h + margin.top + margin.bottom)
    .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");


  var data = [{
    "name": "Twitter",
    "items": [{
      "value": 2000
    }, {
      "value": 3000
    }]
  }, {
    "name": "Facebook",
    "items": [{
      "value": 300
    }, {
      "value": 200
    }]
  }, {
    "name": "Ebay",
    "items": [{
      "value": 1000
    }, {
      "value": 2000
    }]
  }, {
    "name": "Foursquare",
    "items": [{
      "value": 2000
    }, {
      "value": 3000
    }]
  }]


  // sort items array descending by size
  // this will help us draw the bigger one first
  // introduce an index for color assignment
  data.forEach(function(d){
  	d.items.forEach(function(d1,i){
      d1.id = i;
    })
    d.items.sort(function(x, y){
      return d3.descending(x.value, y.value);
    });
  });
  
  circleMaker();

  function circleMaker() {

    var colors = d3.scale.category10();
    var counter = 0,
        prevR = 0;

    svg.selectAll("g")
      .data(data)
      .enter()
      .append("g")
      .selectAll("circle")
      .data(function(d){      	
      	return d.items;
      })
      .enter()
      .append("circle")
      .attr("cy", 60)
      .attr("cx", function(d, i) {
        d.r = Math.sqrt(d.value);
        if (i === 0) {
          counter += prevR + d.r;
          prevR = d.r;
        }
        return counter;
      })
      .attr("r", function(d){
        return d.r;
      })
      .style("fill", function(d){
        return colors(d.id);
      });
  }

});
body {
  background: #eeeeee;
}
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="http://d3js.org/d3.v3.min.js"></script>
<div id="holder">
  <div class="serieschart" data-role="serieschart" data-width=450 data-height=180></div>
</div>