最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Stacked D3JS Bubble Chart - Stack Overflow

programmeradmin2浏览0评论

Hey I'm using D3JS as a chart library and I'm really interested in exploiting the cool features in the Bubble Chart. On the main D3JS chart site the following Bubble Chart is used to pare two sets of data:

Bubble Chart.

I was wondering if anybody actually had any idea of how to create a bubble chart like this, I'm struggling to get it work past using a size variable.

I just really want to be able to pare two sets of data for example:

Hostnames (45,955,158) VS Active Sites (21,335,629)

The code I am using is below, I use JSON to retrieve my data, I'm a major newbie when it es to js and even more so this jQuery library so would appreciate any help.

index.html

<div class="four columns browserstats2003">
            <h3>Browser Stats 2003</h3>

        </div>        
    <div class="four columns mobilephonestats">
       <h3>Smartphone Sales 2003</h3>
       <p>The first smartphone had not been released in 2003.</p>
               <div id=""></div>


    </div>

mobile.json

{
 "name": "flare",
 "children": [
  {
   "name": "analytics",
   "children": [
    {
     "name": "cluster",
     "children": [
      {"name": "Smartphone Sales", "size": 11111},
  {"name": "Smartphone Salesa", "size": 2111}
     ]
    }
   ]
  }
 ]
}

js/js.js // JavaScript Document

$(document).ready(function () {

        //  2003 bubble chart
            var diameter = 360,
                format = d3.format(",d"),
                color = d3.scale.category20c();

            var bubble = d3.layout.pack()
                .sort(null)
                .size([diameter, diameter])
                .padding(1.5);

            var svg = d3.select(".mobilephonestats").append("svg")
                .attr("width", diameter)
                .attr("height", diameter)
                .attr("class", "bubble");

            d3.json("mobile.json", function(error, root) {
              var node = svg.selectAll(".node")
                  .data(bubble.nodes(classes(root))
                  .filter(function(d) { return !d.children; }))
                .enter().append("g")
                  .attr("class", "node")
                  .attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });

              node.append("title")
                  .text(function(d) { return d.className + ": " + format(d.value); });

              node.append("circle")
                  .attr("r", function(d) { return d.r; })
                  .style("fill", function(d) { return color(d.packageName); });

              node.append("text")
                  .attr("dy", ".3em")
                  .style("text-anchor", "middle")
                  .text(function(d) { return d.className.substring(0, d.r / 3); });
            });

            // Returns a flattened hierarchy containing all leaf nodes under the root.
            function classes(root) {
              var classes = [];

              function recurse(name, node) {
                if (node.children) node.children.forEach(function(child) { recurse(node.name, child); });
                else classes.push({packageName: name, className: node.name, value: node.size});
              }

              recurse(null, root);
              return {children: classes};
            }

            d3.select(self.frameElement).style("height", diameter + "px");

// end bubble year 

        });

Hey I'm using D3JS as a chart library and I'm really interested in exploiting the cool features in the Bubble Chart. On the main D3JS chart site the following Bubble Chart is used to pare two sets of data:

Bubble Chart.

I was wondering if anybody actually had any idea of how to create a bubble chart like this, I'm struggling to get it work past using a size variable.

I just really want to be able to pare two sets of data for example:

Hostnames (45,955,158) VS Active Sites (21,335,629)

The code I am using is below, I use JSON to retrieve my data, I'm a major newbie when it es to js and even more so this jQuery library so would appreciate any help.

index.html

<div class="four columns browserstats2003">
            <h3>Browser Stats 2003</h3>

        </div>        
    <div class="four columns mobilephonestats">
       <h3>Smartphone Sales 2003</h3>
       <p>The first smartphone had not been released in 2003.</p>
               <div id=""></div>


    </div>

mobile.json

{
 "name": "flare",
 "children": [
  {
   "name": "analytics",
   "children": [
    {
     "name": "cluster",
     "children": [
      {"name": "Smartphone Sales", "size": 11111},
  {"name": "Smartphone Salesa", "size": 2111}
     ]
    }
   ]
  }
 ]
}

js/js.js // JavaScript Document

$(document).ready(function () {

        //  2003 bubble chart
            var diameter = 360,
                format = d3.format(",d"),
                color = d3.scale.category20c();

            var bubble = d3.layout.pack()
                .sort(null)
                .size([diameter, diameter])
                .padding(1.5);

            var svg = d3.select(".mobilephonestats").append("svg")
                .attr("width", diameter)
                .attr("height", diameter)
                .attr("class", "bubble");

            d3.json("mobile.json", function(error, root) {
              var node = svg.selectAll(".node")
                  .data(bubble.nodes(classes(root))
                  .filter(function(d) { return !d.children; }))
                .enter().append("g")
                  .attr("class", "node")
                  .attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });

              node.append("title")
                  .text(function(d) { return d.className + ": " + format(d.value); });

              node.append("circle")
                  .attr("r", function(d) { return d.r; })
                  .style("fill", function(d) { return color(d.packageName); });

              node.append("text")
                  .attr("dy", ".3em")
                  .style("text-anchor", "middle")
                  .text(function(d) { return d.className.substring(0, d.r / 3); });
            });

            // Returns a flattened hierarchy containing all leaf nodes under the root.
            function classes(root) {
              var classes = [];

              function recurse(name, node) {
                if (node.children) node.children.forEach(function(child) { recurse(node.name, child); });
                else classes.push({packageName: name, className: node.name, value: node.size});
              }

              recurse(null, root);
              return {children: classes};
            }

            d3.select(self.frameElement).style("height", diameter + "px");

// end bubble year 

        });
Share Improve this question edited Jun 26, 2014 at 18:36 VividD 10.5k8 gold badges66 silver badges112 bronze badges asked Dec 10, 2013 at 17:16 user0129e021939232user0129e021939232 6,35524 gold badges91 silver badges141 bronze badges 3
  • Did you have a look at any of the other bubble chart examples? – Lars Kotthoff Commented Dec 10, 2013 at 17:58
  • @LarsKotthoff yes i did but none of the examples are like the ones i need – user0129e021939232 Commented Dec 11, 2013 at 9:10
  • It looks to me like all you would have to do is fill the bubbles with a hard gradient. Oh and maybe have a force layout instead of the pack layout if you want to go for more or less exactly the same thing. – Lars Kotthoff Commented Dec 11, 2013 at 9:22
Add a ment  | 

1 Answer 1

Reset to default 6

In the example you provided, he's definitely using a force layout, which is a bit more plicated that the Bubble Chart you're using. You'll have to take into consideration things like collisions and animation.

Why not just have a look at the JavaScript he used to generate it.

Jim Vallandingham wrote an extensive tutorial on Bubble Clouds, which should get you started.

To create the split in the middle of the cirlce as a way of doing some form of data parison, "clip-paths" are the way forward:

  • Append two circles, one for each data-set.
  • Append two clip-path, one for each data-set
  • Append a rectange to each clip-path.
  • Set the rectangle x attributes and width, which defines the position of the split in the middle. This has to be a function of the data.
  • Crop the rectangles and circles

Here's the code:

var nodeEnter = node.enter().append("a")
      .attr("class", "g-node")
      .call(force.drag);

  var democratEnter = nodeEnter.append("g")
      .attr("class", "g-democrat");

  democratEnter.append("clipPath") // clip-path to crop the rectangle
      .attr("id", function(d) { return "g-clip-democrat-" + d.id; })
    .append("rect");

  democratEnter.append("circle");

  var republicanEnter = nodeEnter.append("g")
      .attr("class", "g-republican");

  republicanEnter.append("clipPath") // Clip-path to crop the rectangle
     .attr("id", function(d) { return "g-clip-republican-" + d.id; })
     .append("rect");

  republicanEnter.append("circle");

  node.selectAll("rect")
      .attr("y", function(d) { return -d.r - clipPadding; })
      .attr("height", function(d) { return 2 * d.r + 2 * clipPadding; });

  // Defining the x-attr and width of the rectangle, which effectively splits the circle
  node.select(".g-democrat rect")
      .attr("x", function(d) { return -d.r - clipPadding; }) 
      .attr("width", function(d) { return 2 * d.r * d.k + clipPadding; });

  node.select(".g-republican rect")
      .attr("x", function(d) { return -d.r + 2 * d.r * d.k; })
      .attr("width", function(d) { return 2 * d.r; });

  // Setting the clip-path to crop the circles
  node.select(".g-democrat circle")
      .attr("clip-path", function(d) { return d.k < 1 ? "url(#g-clip-democrat-" + d.id + ")" : null; });

  node.select(".g-republican circle")
      .attr("clip-path", function(d) { return d.k > 0 ? "url(#g-clip-republican-" + d.id + ")" : null; });

This should generate something like this:

<g class="g-democrat">
    <clipPath id="g-clip-democrat-43">
        <rect y="-63.36487389363757" height="126.72974778727514" x="-63.36487389363757" width="59.449375597303515">
        </rect>
    </clipPath>
    <circle clip-path="url(#g-clip-democrat-43)" r="59.36487389363757">
</circle></g>
<g class="g-republican">
    <clipPath id="g-clip-republican-43">
        <rect y="-63.36487389363757" height="126.72974778727514" x="-3.915498296334057" width="118.72974778727514">
        </rect>
    </clipPath>
    <circle clip-path="url(#g-clip-republican-43)" r="59.36487389363757">
</circle></g>
发布评论

评论列表(0)

  1. 暂无评论