javascript - D3 气泡图切换按钮

标签 javascript jquery html css d3.js

我是 D3.js 的新手,正在尝试创建一个带有切换按钮的气泡图来切换不同的总统竞选候选人。我设法仅为一名候选人创建了图表,但在使用 D3.js 进行切换时遇到了问题。我正在尝试做类似 this 的事情,但不太复杂且动画较少。我该怎么做呢?

我的HTML如下:

 <link rel = "stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<link rel = "stylesheet" href = "style.css">
<link rel="stylesheet" href="//rawgithub.com/Caged/d3-tip/master/examples/example-styles.css">
<script src= "http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src= "http://d3js.org/d3.v3.min.js"></script>
<script src= "d3-tip.js"></script>

<div class="container">
    <h1> Who's Giving Them Money? </h1>

    <div class="row">
      <div class="col-sm-6">
        <p> A look at the individual contributions to prominent candidates in the 2016 presidential campaign. The visualization below looks at the amount per 1,000 persons in each state of the US. Data has been sourced from the <strong> Federal Election Commission </strong> website, and is from April 1, 2015 to September 30, 2015. </p>
      </div>
    </div>

    <div class="btn-group-lg" role="group" aria-label="...">
        <button type="button" class="btn btn-default hillary dem">Hillary Clinton</button>
        <button type="button" class="btn btn-default rubio rep">Marco Rubio</button>
        <button type="button" class="btn btn-default sanders dem">Bernie Sanders</button>
        <button type="button" class="btn btn-default bush rep">Jeb Bush</button>
        <button type="button" class="btn btn-default cruz rep">Ted Cruz</button>
        <button type="button" class="btn btn-default trump rep">Donald Trump</button>
    </div>

    <div id ="viz">

    </div>
    <script src= "script.js"></script>


</div>

这是我的javascript:

    var tooltip = d3.tip().attr('class', 'd3-tip').html(
function(d) { return d['Name'] + ': $' + d['Amount'];
});


    var diameter = 500
    var color = d3.scale.ordinal()
                  .domain(['R','D'])
                  .range(['#B2182B','#2166AC']);


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

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


    /* modified d3-tip boilerplate */
    /* Invoke the tip in the context of your visualization */
    svg.call(tooltip);

    d3.csv("Candidates.csv", function(error, data) {

        var nest = d3.nest()
                     .key(function(d){return d['Candidate'] })
                     .entries(data);

var button = d3.select("")


data = data.map(function(d) {
    d.value = +d["Amount"];
    return d;
});

var nodes = bubble.nodes({children: data }).filter(function(d) {
    return !d.children;
});


var bubbles = svg.append("g")
    .attr("transform", "translate(0,0)")
    .selectAll(".bubble")
    .data(nodes)
    .enter();

bubbles.append("circle")
    .attr("r", function(d) { return d.r; })
    .attr("cx", function(d) {return d.x; })
    .attr("cy", function(d) { return d.y; })
    .style("fill", function(d) {
        return color(d["Past"]);
    })


//format the text for each bubble
bubbles.append("text")
    .attr("x", function(d) {
        return d.x;
    })
    .attr("y", function(d) {
        return d.y + 5;
    })
    .attr("text-anchor", "middle")
    //.text(function(d){ return d["State"] ; })
    .text(function(d) {
        return d["State"];
    });

bubbles.append("circle")
    .attr("r", function(d) { return d.r; })
    .attr("cx", function(d) {return d.x; })
    .attr("cy", function(d) { return d.y; })
    .style("fill", function(d) {
        return "rgba(0,0,0,0)";
    })
    .on('mouseover', tooltip.show)
    .on('mouseout', tooltip.hide);

});

这是我的 CSV 文件示例。完整文件可见here :

    Candidate,State,Name,Past,Amount
    Marco Rubio,AK,Alaska,R,10.5
    Hillary Clinton,AL,Alabama,R,10.47
    Jeb Bush,AR,Arkansas,R,4.55
    Donald Trump,AZ,Arizona,R,46.13
    Ted Cruz,CA,California,D,82.55

为了澄清起见,“过去”字段显示各州过去的投票情况(共和党/民主党),如果我在帖子中有任何错误,我深表歉意。这是我的第一篇文章!如果你能帮助我,我将不胜感激。谢谢你!

最佳答案

// d3.tip
// Copyright (c) 2013 Justin Palmer
//
// Tooltips for d3.js SVG visualizations

(function (root, factory) {
  if (typeof define === 'function' && define.amd) {
    // AMD. Register as an anonymous module with d3 as a dependency.
    define(['d3'], factory)
  } else if (typeof module === 'object' && module.exports) {
    // CommonJS
    module.exports = function(d3) {
      d3.tip = factory(d3)
      return d3.tip
    }
  } else {
    // Browser global.
    root.d3.tip = factory(root.d3)
  }
}(this, function (d3) {

  // Public - contructs a new tooltip
  //
  // Returns a tip
  return function() {
    var direction = d3_tip_direction,
        offset    = d3_tip_offset,
        html      = d3_tip_html,
        node      = initNode(),
        svg       = null,
        point     = null,
        target    = null

    function tip(vis) {
      svg = getSVGNode(vis)
      point = svg.createSVGPoint()
      document.body.appendChild(node)
    }

    // Public - show the tooltip on the screen
    //
    // Returns a tip
    tip.show = function() {
      var args = Array.prototype.slice.call(arguments)
      if(args[args.length - 1] instanceof SVGElement) target = args.pop()

      var content = html.apply(this, args),
          poffset = offset.apply(this, args),
          dir     = direction.apply(this, args),
          nodel   = getNodeEl(),
          i       = directions.length,
          coords,
          scrollTop  = document.documentElement.scrollTop || document.body.scrollTop,
          scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft

      nodel.html(content)
        .style({ opacity: 1, 'pointer-events': 'all' })

      while(i--) nodel.classed(directions[i], false)
      coords = direction_callbacks.get(dir).apply(this)
      nodel.classed(dir, true).style({
        top: (coords.top +  poffset[0]) + scrollTop + 'px',
        left: (coords.left + poffset[1]) + scrollLeft + 'px'
      })

      return tip
    }

    // Public - hide the tooltip
    //
    // Returns a tip
    tip.hide = function() {
      var nodel = getNodeEl()
      nodel.style({ opacity: 0, 'pointer-events': 'none' })
      return tip
    }

    // Public: Proxy attr calls to the d3 tip container.  Sets or gets attribute value.
    //
    // n - name of the attribute
    // v - value of the attribute
    //
    // Returns tip or attribute value
    tip.attr = function(n, v) {
      if (arguments.length < 2 && typeof n === 'string') {
        return getNodeEl().attr(n)
      } else {
        var args =  Array.prototype.slice.call(arguments)
        d3.selection.prototype.attr.apply(getNodeEl(), args)
      }

      return tip
    }

    // Public: Proxy style calls to the d3 tip container.  Sets or gets a style value.
    //
    // n - name of the property
    // v - value of the property
    //
    // Returns tip or style property value
    tip.style = function(n, v) {
      if (arguments.length < 2 && typeof n === 'string') {
        return getNodeEl().style(n)
      } else {
        var args =  Array.prototype.slice.call(arguments)
        d3.selection.prototype.style.apply(getNodeEl(), args)
      }

      return tip
    }

    // Public: Set or get the direction of the tooltip
    //
    // v - One of n(north), s(south), e(east), or w(west), nw(northwest),
    //     sw(southwest), ne(northeast) or se(southeast)
    //
    // Returns tip or direction
    tip.direction = function(v) {
      if (!arguments.length) return direction
      direction = v == null ? v : d3.functor(v)

      return tip
    }

    // Public: Sets or gets the offset of the tip
    //
    // v - Array of [x, y] offset
    //
    // Returns offset or
    tip.offset = function(v) {
      if (!arguments.length) return offset
      offset = v == null ? v : d3.functor(v)

      return tip
    }

    // Public: sets or gets the html value of the tooltip
    //
    // v - String value of the tip
    //
    // Returns html value or tip
    tip.html = function(v) {
      if (!arguments.length) return html
      html = v == null ? v : d3.functor(v)

      return tip
    }

    // Public: destroys the tooltip and removes it from the DOM
    //
    // Returns a tip
    tip.destroy = function() {
      if(node) {
        getNodeEl().remove();
        node = null;
      }
      return tip;
    }

    function d3_tip_direction() { return 'n' }
    function d3_tip_offset() { return [0, 0] }
    function d3_tip_html() { return ' ' }

    var direction_callbacks = d3.map({
      n:  direction_n,
      s:  direction_s,
      e:  direction_e,
      w:  direction_w,
      nw: direction_nw,
      ne: direction_ne,
      sw: direction_sw,
      se: direction_se
    }),

    directions = direction_callbacks.keys()

    function direction_n() {
      var bbox = getScreenBBox()
      return {
        top:  bbox.n.y - node.offsetHeight,
        left: bbox.n.x - node.offsetWidth / 2
      }
    }

    function direction_s() {
      var bbox = getScreenBBox()
      return {
        top:  bbox.s.y,
        left: bbox.s.x - node.offsetWidth / 2
      }
    }

    function direction_e() {
      var bbox = getScreenBBox()
      return {
        top:  bbox.e.y - node.offsetHeight / 2,
        left: bbox.e.x
      }
    }

    function direction_w() {
      var bbox = getScreenBBox()
      return {
        top:  bbox.w.y - node.offsetHeight / 2,
        left: bbox.w.x - node.offsetWidth
      }
    }

    function direction_nw() {
      var bbox = getScreenBBox()
      return {
        top:  bbox.nw.y - node.offsetHeight,
        left: bbox.nw.x - node.offsetWidth
      }
    }

    function direction_ne() {
      var bbox = getScreenBBox()
      return {
        top:  bbox.ne.y - node.offsetHeight,
        left: bbox.ne.x
      }
    }

    function direction_sw() {
      var bbox = getScreenBBox()
      return {
        top:  bbox.sw.y,
        left: bbox.sw.x - node.offsetWidth
      }
    }

    function direction_se() {
      var bbox = getScreenBBox()
      return {
        top:  bbox.se.y,
        left: bbox.e.x
      }
    }

    function initNode() {
      var node = d3.select(document.createElement('div'))
      node.style({
        position: 'absolute',
        top: 0,
        opacity: 0,
        'pointer-events': 'none',
        'box-sizing': 'border-box'
      })

      return node.node()
    }

    function getSVGNode(el) {
      el = el.node()
      if(el.tagName.toLowerCase() === 'svg')
        return el

      return el.ownerSVGElement
    }

    function getNodeEl() {
      if(node === null) {
        node = initNode();
        // re-add node to DOM
        document.body.appendChild(node);
      };
      return d3.select(node);
    }

    // Private - gets the screen coordinates of a shape
    //
    // Given a shape on the screen, will return an SVGPoint for the directions
    // n(north), s(south), e(east), w(west), ne(northeast), se(southeast), nw(northwest),
    // sw(southwest).
    //
    //    +-+-+
    //    |   |
    //    +   +
    //    |   |
    //    +-+-+
    //
    // Returns an Object {n, s, e, w, nw, sw, ne, se}
    function getScreenBBox() {
      var targetel   = target || d3.event.target;

      while ('undefined' === typeof targetel.getScreenCTM && 'undefined' === targetel.parentNode) {
          targetel = targetel.parentNode;
      }

      var bbox       = {},
          matrix     = targetel.getScreenCTM(),
          tbbox      = targetel.getBBox(),
          width      = tbbox.width,
          height     = tbbox.height,
          x          = tbbox.x,
          y          = tbbox.y

      point.x = x
      point.y = y
      bbox.nw = point.matrixTransform(matrix)
      point.x += width
      bbox.ne = point.matrixTransform(matrix)
      point.y += height
      bbox.se = point.matrixTransform(matrix)
      point.x -= width
      bbox.sw = point.matrixTransform(matrix)
      point.y -= height / 2
      bbox.w  = point.matrixTransform(matrix)
      point.x += width
      bbox.e = point.matrixTransform(matrix)
      point.x -= width / 2
      point.y -= height / 2
      bbox.n = point.matrixTransform(matrix)
      point.y += height
      bbox.s = point.matrixTransform(matrix)

      return bbox
    }

    return tip
  };

}));


var tooltip = d3.tip().attr('class', 'd3-tip').html(
function(d) { return d['Name'] + ': $' + d['Amount'];
});


    var diameter = 500
    var color = d3.scale.ordinal()
                  .domain(['R','D'])
                  .range(['#B2182B','#2166AC']);


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

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


    /* modified d3-tip boilerplate */
    /* Invoke the tip in the context of your visualization */
    svg.call(tooltip);
var data=[
{Candidate:"Marco",State:"AK",Name:"Alaska",Past:"R",Amount:10.5},
{Candidate:"Hillary Clinton",State:"AL",Name:"Alabama",Past:"R",Amount:10.47},
{Candidate:"Jeb Bush",State:"AR",Name:"Arkansas",Past:"R",Amount:4.55},
{Candidate:"Donald Trump",State:"AZ",Name:"Arizona",Past:"R",Amount:46.13},
{Candidate:"Ted Cruz",State:"CA",Name:"California",Past:"D",Amount:82.55}
];
draw(data);
    //d3.csv("Candidates.csv", function(error, data) {
function draw(data){
        var nest = d3.nest()
                     .key(function(d){return d['Candidate'] })
                     .entries(data);

//var button = d3.select("")


data = data.map(function(d) {
    d.value = +d["Amount"];
    return d;
});

var nodes = bubble.nodes({children: data }).filter(function(d) {
    return !d.children;
});

console.log(nodes);
var bubbles = svg.append("g")
    .attr("transform", "translate(0,0)")
    .selectAll(".bubble")
    .data(nodes)
    .enter();

bubbles.append("circle")
    .attr("r", function(d) { return d.r; })
    .attr("cx", function(d) {return d.x; })
    .attr("cy", function(d) { return d.y; })
    .style("fill", function(d) {
        return color(d["Past"]);
    })


//format the text for each bubble
bubbles.append("text")
    .attr("x", function(d) {
        return d.x;
    })
    .attr("y", function(d) {
        return d.y + 5;
    })
    .attr("text-anchor", "middle")
    //.text(function(d){ return d["State"] ; })
    .text(function(d) {
        return d["State"];
    });

bubbles.append("circle")
    .attr("r", function(d) { return d.r; })
    .attr("cx", function(d) {return d.x; })
    .attr("cy", function(d) { return d.y; })
    .style("fill", function(d) {
        return "rgba(0,0,0,0)";
    })
    .on('mouseover', tooltip.show)
    .on('mouseout', tooltip.hide);
    //});
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" type="text/css" rel="stylesheet"/>


<link href="https://rawgithub.com/Caged/d3-tip/master/examples/example-styles.css" type="text/css" rel="stylesheet"/>
<script src="http://vallandingham.me/vis/gates/js/CustomTooltip.js" type="text/javascript"></script>

<div class="container">
    <h1> Who's Giving Them Money? </h1>

    <div class="row">
      <div class="col-sm-6">
        <p> A look at the individual contributions to prominent candidates in the 2016 presidential campaign. The visualization below looks at the amount per 1,000 persons in each state of the US. Data has been sourced from the <strong> Federal Election Commission </strong> website, and is from April 1, 2015 to September 30, 2015. </p>
      </div>
    </div>

    <div class="btn-group-lg" role="group" aria-label="...">
        <button type="button" class="btn btn-default hillary dem">Hillary Clinton</button>
        <button type="button" class="btn btn-default rubio rep">Marco Rubio</button>
        <button type="button" class="btn btn-default sanders dem">Bernie Sanders</button>
        <button type="button" class="btn btn-default bush rep">Jeb Bush</button>
        <button type="button" class="btn btn-default cruz rep">Ted Cruz</button>
        <button type="button" class="btn btn-default trump rep">Donald Trump</button>
    </div>

    <div id ="viz">

    </div>
    


</div>

我已经完成了这里, 每当我们按下希拉里克林顿、马可卢比奥、伯尼桑德斯等按钮时,你都在寻找你想展示什么...... 稍微描述一下,这样我们就可以实现了。 希望你明白。

关于javascript - D3 气泡图切换按钮,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33688586/

相关文章:

javascript - JS : how to shift each letter in the given string N places down in the alphabet?

jQuery:选择器问题(图片)

javascript - jQuery 下拉菜单打开所有子菜单

c# - 使用 Controller 返回的值填充图表

javascript - 在react中点击img时添加一个圆圈

jquery - 使用 jQuery attr() 设置 “css”

html - 如何获取任何 URL 或网页的 Google 缓存年龄?

html - Razor CSS 文件位置作为变量

html - 我怎样才能摆脱这个 firefox 控制台警告?

javascript - ServiceWorker 注册失败 : The script has an unsupported MIME type - reactjs