如何使用 geoChoroplethChart 和 dc.js 在 Mapchart 的路径上添加标签或自定义值?

How to add label or custom value on Mapchart's path using geoChoroplethChart and dc.js?

var IndChart = dc.geoChoroplethChart("#india-chart");

var states = data.dimension(function (d) {
            return d["state_name"];
        });

var stateRaisedSum = states.group().reduceSum(function (d) {
            return d["popolation"];
        });

     IndChart
                        .width(700)
                        .height(500)
                        .dimension(states)
                        .group(stateRaisedSum)
                        .colors(d3.scale.ordinal().domain().range(["#27AE60", "#F1C40F", "#F39C12","#CB4335"]))
                        .overlayGeoJson(statesJson.features, "state", function (d) { //console.log(d.properties.name);
                            return d.id;
                        })
                        .projection(d3.geo.mercator().center([95, 22]).scale(940))
                        .renderLabel(true)
                         .title(function (d) { console.log(d); return d.key + " : " + d.value ;
                        })
                        .label(function (d) { console.log(d);}) ;

想使用 dc.js.

在地图图表中为每个路径添加标签或自定义值(25%,在地图图表屏幕截图中添加)

在上面的评论中,您找到或创建了一个 working example 来回答您的原始问题。然后你问如何让它对同一页上的两个图表起作用。

这只是让 select 正确,以及了解 dc.js 渲染和重绘如何工作的问题。

首先,这个例子确实

var labelG = d3.select("svg")

这将始终 select 页面上的第一个 svg 元素。您可以通过使 select 或更具体,即 #us-chart svg#us-chart2 svg 来解决此问题,但我更喜欢使用 chart.select() 函数,其中 selects特定图表的 DOM 树。

接下来,请务必记住,当您呈现图表时,它会删除所有内容并从头开始。此示例调用 dc.renderAll() 两次,因此对第一个图表所做的任何修改都将在第二个渲染中丢失。

相比之下,当任何过滤器发生变化时都会发生重绘,并且它会逐步更改图表,同时保持之前的内容。

我更喜欢听dc.js chart events然后再做修改。这样,每次渲染或重绘图表时,都可以进行修改。

特别是,我尽量使用 pretransition 事件来修改图表。这会在绘图后立即发生,因此您有机会在没有任何故障或停顿的情况下进行更改。

始终在呈现图表之前添加事件侦听器。

为两个图表添加(相同的)处理程序然后呈现,如下所示:

    usChart.on('pretransition', function(chart) {
        var project = d3.geo.albersUsa();

        var labelG = chart.select("svg")
            .selectAll('g.Title')
              .data([0])
            .enter()
            .append("svg:g")
            .attr("id", "labelG")
            .attr("class", "Title");

        labelG.selectAll("text")
            .data(labels.features)
            .enter().append("svg:text")
            .text(function(d){return d.properties.name;})
            .attr("x", function(d){return project(d.geometry.coordinates)[0];})
            .attr("y", function(d){return project(d.geometry.coordinates)[1];})
            .attr("dx", "-1em");
    });

    usChart2.on('pretransition', function(chart) {
        var project = d3.geo.albersUsa();

        var labelG = chart.select("svg")
            .selectAll('g.Title')
              .data([0])
            .enter()
            .append("svg:g")
            .attr("id", "labelG")
            .attr("class", "Title");

        labelG.selectAll("text")
            .data(labels.features)
            .enter().append("svg:text")
            .text(function(d){return d.properties.name;})
            .attr("x", function(d){return project(d.geometry.coordinates)[0];})
            .attr("y", function(d){return project(d.geometry.coordinates)[1];})
            .attr("dx", "-1em");
    });
    dc.renderAll();

我在那里又使用了一个技巧:因为 pretransition 发生在渲染和重绘中,但我们只想添加这些标签一次,所以我使用了这个模式:

        .selectAll('g.Title')
          .data([0])
        .enter()
        .append("svg:g")
        .attr("class", "Title");

这是最简单的data binding:它说我们想要一个g.Title,它的数据就是值0。因为我们给 g 元素 Title class,这确保我们只添加一次这个元素。

最后,这个表达式的结果是一个输入selection,所以我们只会在Title层是新的时候添加text个元素。

Fork of your fiddle.