d3js:在可重复使用的图表中单击事件

时间:2014-04-29 17:06:32

标签: javascript d3.js charts mouseclick-event

我有一张可以重复使用的图表。我将以下简单代码添加到可重用图表中,期望它会将click监听器添加到由它创建的所有图表中。

d3.cloudshapes.barChart = function module() {
    var margin = {top: 10, right: 10, bottom: 20, left: 20},
        width = 500,
        height = 500,
        gap = 0,
        ease = "bounce";
    var svg;


    // Define the 'inner' function: which, through the surreal nature of JavaScript scoping, can access
    // the above variables. 
    function exports(_selection) {
        _selection.each(function(_data) {
            var chartW = 60,
                chartH = 60;

        var test_data = _data.value;

            var x1 = d3.scale.ordinal()
                    .domain(test_data.map(function(d) { return d.x; }))
                    .rangeRoundBands([0, chartW], 0.1);

            var y1 = d3.scale.linear()
                    .domain([0, 36])
                    .range([chartH, 0]);

        var color = d3.scale.category10();

        // If no SVG exists, create one - and add key groups:
            if (!svg) {
                svg = d3.select(this)
                     .append("svg")
             .attr("width", width)
             .attr("height", height)
                     .classed("chart", true);
                var container = svg.append("g").classed("container-group", true);
                container.append("g").classed("chart-group", true);
        container.attr({transform: "translate(" + 60*_data.row + "," + 60*_data.col + ")"});
        container.on("click", click);

            }

        // Transition the width and height of the main SVG and the key 'g' group: 
            svg.classed("chart", true).transition().attr({width: width, height: height});
           var container = svg.append("g").classed("container-group", true);
        container.append("g").classed("chart-group", true);
        container.attr({transform: "translate(" + 60*_data.row + "," + 60*_data.col + ")"});

        container.on("click", click);

            function click()  {
                console.log("I got clicked");
            }

        // Define gap between bars: 
            var gapSize = x1.rangeBand() / 100 * gap;

        // Define width of each bar: 
            var barW = x1.rangeBand() - gapSize;

            // Select all bars and bind data:  
            var bars = svg.selectAll(".chart-group")
                        .selectAll(".bar")
                        .data(test_data);

        bars.enter().append("rect")
            .classed("bar", "true")
            .attr({
                width: barW,
                x: function (d) {                   
                    return x1(d.x) + gapSize / 2; },
                y: function(d) { return y1(d.y); },
                height: function(d) { return chartH - y1(d.y); }
        })
            .attr("fill", function(d) { return color(d.x); });



        });
    }

但是click函数仅适用于可重用图表呈现的最后一个图形实例。如何将点击侦听器添加到可重用图表呈现的每个图表中?

这里有一个更简单的版本fiddle。我想在点击小条形图时添加缩放的弹出式条形图svg。我认为问题在于动态创建div,因为当我尝试在预定义div中创建图表时,点击功能正常工作。

任何帮助将不胜感激!

1 个答案:

答案 0 :(得分:0)

svg变量的范围导致了问题。在您的代码中,svg变量值通过可重用函数的所有实例共享。您可能希望使用enter()来创建SVG元素和内部组件,并将click侦听器添加到组件中。 svg变量应在exports函数内定义。

// rest of the code...
function exports(selection) {
    selection.each(function(data) {

        // Select the SVG element
        var svg = d3.select(this).selectAll('svg').data([data]);

        // Create the SVG element on enter, set it's size
        svg.enter().append('svg')
            .attr('width', width)
            .attr('height', height);

        var component = svg.selectAll('g.component').data([data]);

        // Create the component group on enter and set its attributes
        component.enter().append('g');

        // Add other elements...

        // click listener
        component.on('click', function(d) {
            // click callback.
        });


    });
}