如何使用 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
个元素。
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
个元素。