【问题标题】:d3 multi circle series data chartd3多圈系列数据图
【发布时间】:2017-08-21 21:06:10
【问题描述】:

这将如何适应叠加第二组圆圈?

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

}

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

【问题讨论】:

  • second set of circlesitems 数组中的第二个值吗?
  • 当然 -- { "name": "Twitter", "items": [{ "value": 2000 }, { "value": 3000 }
  • 想法是——如果我们添加第三组——然后显示 3 个圆圈,但是——以最大的圆圈为基础,然后像 2D 金字塔一样构建它。
  • 这是您应该在问题中包含的重要信息。

标签: javascript d3.js


【解决方案1】:

其中大部分只是在绘制数据之前组织数据。在每个系列中给每个项目一个索引,然后按值排序。 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); });

【讨论】:

【解决方案2】:

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>

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2022-09-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多