简体   繁体   中英

d3 multi circle series data chart

在此处输入图片说明

How would this be adapted to superimpose a second set of circles?

  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
    }]
  }]

with the option of adding other data sets - the goal to create a 2D pyramid of sorts with different coloured circles representing the different data sets -- with the largest dataset taking the base circle.

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);
      });

}

eventually maybe even flip between the different data sets to always place the largest circle as the background. So like this

在此处输入图片说明

Most of it is just organising the data before plotting it. Within each series give each item an index, and then sort by value. The index property will then tell us the initial position of each item in the series. The first item in each series will now be the biggest value. Use this to build an offset for each series, and sum all these offsets to make a scale for positioning.

Then make group elements for each series, positioning using the offset we calculated.

Within each group, draw the circle elements. Since we sorted them they'll be drawn biggest first. The .index property can be used to colour by their original place in the series.

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); });

mgraham's answer is great! But since I had already written this out (and then had to go to a meeting) here's how I would code it:

 $(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) { dr = Math.sqrt(d.value); if (i === 0) { counter += prevR + dr; prevR = dr; } return counter; }) .attr("r", function(d){ return dr; }) .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> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM