d3.js noob : How to pass dynamic variable as data

2019-07-24 04:11发布

问题:

I'm trying to change the data set via a variable passed from the clicked button.

Here's an example of what I'm doing so far: http://jsfiddle.net/earlybirdtechie/qmC9E/

d3.selectAll('button.decadeBtn')
    .on("click", function() {
        var currentDecadeName = $(this).attr('data-decade');
        console.log('currentDecadeName: '+ currentDecadeName); 
        svg.selectAll("rect.bars")
        .data(currentDecadeName, function(d) { return d.id })
        .transition()
        .duration(1499)
        .ease("bounce")
        .attr({
            height: function(d,i) {
                return d.value;
            }
        })

In the jsFiddle example above when you click on any of the buttons, the bars should change based on the data for it's decade. Yet, the code is expecting the name of the data, not a dynamic variable name. So, if you go to line 43 in the js code and replace the variable name 'currentDecadeName' with 'seventies', then the bars will change to the seventies data once any button is clicked. How can I get this to work with a dynamic variable instead of a static data variable?

When I posted this question in google groups, I was told to use the map object, yet, I'm a noob and not clear on how d3.map works.

Can anyone clear up how one can use d3.map in this situation, or point me to a tutorial on how the map object works in d3?

Thanks!

回答1:

Taking a look at the source code, the map class seems to be very simple. It's basically the equivalent of a map/hash/dictionary/object, similar to a normal JavaScript object, with some convenience functions. I'm not too familiar with d3, so perhaps map is designed to integrate well with other parts of the library.

In essence, what you want to do is collect your data in some sort of "mapping" from names (strings) to values (arrays of datapoints). You don't actually need to use d3.map - a simple object would suffice in this case.

Here's an example with a simple JavaScript object. You just need to keep a mapping in scope:

var sixties = [ ... ];
var seventies = [ ... ];

// Create mapping as an object
var map = {
    sixties: sixties,
    seventies: seventies
}

...

d3.selectAll('button.decadeBtn')
.on("click", function() {
    var currentDecadeName = $(this).attr('data-decade');
    svg.selectAll("rect.bars")
    // Lookup the current decade name in the mapping
    .data(map[currentDecadeName], function(d) { return d.id })
...

And here's a JsFiddle illustrating the same thing using d3.map, which uses the .get() function to access elements.