在传单弹出窗口中插入 NVD3 图表
Inserting NVD3 chart in Leaflet popup
在我的 AngularJs
网络应用程序中,我正在使用 Leaflet.js and Leaflet markercluster 构建地图。
我使用 nvd3.js and the nvd3-angular-directive
渲染图表
我有来自世界各地的不同数据,我为每个收到数据的国家展示了一个简单的 CircleMarker
。
我的数据是这样组织的:
{
US : {country:"US", count:10, rate: {high: 3, medium: 4, low: 3}},
IT : {country:"IT", count:4, rate: {high: 1, medium: 1, low: 2}}
}
这意味着在地图中 CircleMarker
将显示在美国和意大利的中心。
现在让我们开始讨论这个问题,我在每个 CircleMarker
上绑定一个弹出窗口,我希望每个弹出窗口都包含一个 nvd3
饼图(特别是圆环图)来显示分布该特定国家/地区的 rate
s。
问题是当前地图渲染正确并且标记位置完美,但是当我单击标记时出现的弹出窗口是空的(见图)。我用谷歌搜索,但没能找到任何可以帮助我的东西。
这就是我构建 CircleMarkers
和集群的方式:
var markers = L.markerClusterGroup({
maxClusterRadius: 120,
iconCreateFunction: function (cluster) {
return L.divIcon({html: '<b>' + cluster.getChildCount() + '</b>', className: 'mycluster', iconSize: L.point(40, 40)});
}
})
var geolocData = {
US : {country:"US", count:10, rate: {high: 3, medium: 4, low: 3}},
IT : {country:"IT", count:4, rate: {high: 1, medium: 1, low: 2}}
}
for (key in geolocData){
var latlng = retrieveLatLongFromCountryCode(key)
var marker = new L.circleMarker(latlng, {stroke: false, className:'the-marker-class', fillOpacity: 1, color:'#00FF00', weight: 1})
var popupChartOptions = {
chart: {
type: 'pieChart',
height: 140,
donut: true,
donutRatio: 0.40,
x: function(d) { return d.label },
y: function(d) { return d.value },
color: [
'#2ecc71',
'#f1c40f',
'#e74c3c',
],
valueFormat: d3.format(',.0d')
}
}
var popupChartData = [{
label: 'low',
value: geolocData[key].rate.low
}, {
label: 'medium',
value: geolocData[key].rate.medium
}, {
label: 'high',
value: geolocData[key].rate.high
}]
marker.bindPopup('<nvd3 options="chartOptions" data="chartData"></nvd3>')
markers.addLayers(marker)
}
map.addLayer(markers)
更新
我做了一些改动。首先,我扩展了 CircleMarker
class
var customCircleMarker = L.CircleMarker.extend({
options: {
countrycode: '',
rates: {},
count: 0
}
})
然后我在我的地图
中使用这个CustomCircleMarker
var marker = new customCircleMarker(latlng, {stroke: false, className: 'the-class-name', fillOpacity: 1, weight: 1})
var popupChartData = [{
label: 'low',
value: [geolocLoad[key].rate.low]
}, {
label: 'medium',
value: [geolocLoad[key].rate.medium]
}, {
label: 'high',
value: [geolocLoad[key].rate.high]
}]
然后我绑定弹出窗口,用我的自定义数据填充标记并创建一个 on click
回调,它发出一条包含我的有用数据的消息。
marker.bindPopup('<div id="chart-' + key + '"></div>')
marker.countrycode = key
marker.rates = popupChartData
marker.count = geolocLoad[key].count
marker.on('click', function(e){
$scope.$emit('marker:click', this.countrycode, this.count, this.rates)
})
接收方将获取数据并以这种方式呈现图表:
$scope.$on('marker:click', function(caller, countrycode, count, rates){
console.log('received', countrycode, count, rates)
var width = 500,
height = 500
nv.addGraph(function(){
var chart = nv.models.pieChart()
.x(function(d) { return d.label })
.y(function(d) { return d.value })
.width(width)
.height(height);
d3.select("#chart-"+countrycode)
.datum(rates)
.attr('width', width)
.attr('height', height)
.call(chart);
return chart;
})
})
遗憾的是,这不再有效了..
注意:我没有使用 angular-leaflet-directive,因为我发现它太过分了而且不太喜欢它。你觉得我还是用它比较好吗?
我已经自己解决了这个问题,我发布了一个答案,因为它可能对未来的用户有帮助。
我忘记的最重要的事情是在弹出窗口中插入一个 <svg>
元素,这导致图表无法呈现,因为没有 'canvas' 我们库可以呈现它..
标记生成:
var marker = new customCircleMarker(countries.names[c].latlng, {stroke: false, className: 'the-class-name', fillOpacity: 1, weight: 1})
marker.bindPopup('<div id="chart-' + key + '" class="country-popup-chart-container"><svg class="country-popup-chart"></svg></div>', {closeButton: false})
marker.countrycode = key
marker.rates = geolocLoad[key].rate
marker.count = geolocLoad[key].count
marker.on('click', function(e){
$scope.$emit('marker:click', this.countrycode, this.count, this.rates)
})
图表生成由在 click
上调用的 $emit
触发:
$scope.$on('marker:click', function(caller, countrycode, count, rates) {
var popupChartData = [{
label: 'low',
value: rates.low,
color: '#2ecc71'
}, {
label: 'medium',
value: rates.medium,
color: '#f1c40f'
}, {
label: 'high',
value: rates.high,
color: '#e74c3c'
}]
nv.addGraph(function(){
var chart = nv.models.pieChart()
.x(function(d) { return d.label })
.y(function(d) { return d.value })
.showLabels(false)
.donut(true)
.donutRatio(0.5)
d3.select('#chart-' + countrycode + ' svg')
.datum(popupChartData)
.call(chart)
return chart
})
})
根据以下 CSS
进行评估:
div.country-popup-chart-container{
height: 80px;
width: 200px;
}
最后的结果是:
在我的 AngularJs
网络应用程序中,我正在使用 Leaflet.js and Leaflet markercluster 构建地图。
我使用 nvd3.js and the nvd3-angular-directive
渲染图表我有来自世界各地的不同数据,我为每个收到数据的国家展示了一个简单的 CircleMarker
。
我的数据是这样组织的:
{
US : {country:"US", count:10, rate: {high: 3, medium: 4, low: 3}},
IT : {country:"IT", count:4, rate: {high: 1, medium: 1, low: 2}}
}
这意味着在地图中 CircleMarker
将显示在美国和意大利的中心。
现在让我们开始讨论这个问题,我在每个 CircleMarker
上绑定一个弹出窗口,我希望每个弹出窗口都包含一个 nvd3
饼图(特别是圆环图)来显示分布该特定国家/地区的 rate
s。
问题是当前地图渲染正确并且标记位置完美,但是当我单击标记时出现的弹出窗口是空的(见图)。我用谷歌搜索,但没能找到任何可以帮助我的东西。
这就是我构建
CircleMarkers
和集群的方式:
var markers = L.markerClusterGroup({
maxClusterRadius: 120,
iconCreateFunction: function (cluster) {
return L.divIcon({html: '<b>' + cluster.getChildCount() + '</b>', className: 'mycluster', iconSize: L.point(40, 40)});
}
})
var geolocData = {
US : {country:"US", count:10, rate: {high: 3, medium: 4, low: 3}},
IT : {country:"IT", count:4, rate: {high: 1, medium: 1, low: 2}}
}
for (key in geolocData){
var latlng = retrieveLatLongFromCountryCode(key)
var marker = new L.circleMarker(latlng, {stroke: false, className:'the-marker-class', fillOpacity: 1, color:'#00FF00', weight: 1})
var popupChartOptions = {
chart: {
type: 'pieChart',
height: 140,
donut: true,
donutRatio: 0.40,
x: function(d) { return d.label },
y: function(d) { return d.value },
color: [
'#2ecc71',
'#f1c40f',
'#e74c3c',
],
valueFormat: d3.format(',.0d')
}
}
var popupChartData = [{
label: 'low',
value: geolocData[key].rate.low
}, {
label: 'medium',
value: geolocData[key].rate.medium
}, {
label: 'high',
value: geolocData[key].rate.high
}]
marker.bindPopup('<nvd3 options="chartOptions" data="chartData"></nvd3>')
markers.addLayers(marker)
}
map.addLayer(markers)
更新
我做了一些改动。首先,我扩展了 CircleMarker
class
var customCircleMarker = L.CircleMarker.extend({
options: {
countrycode: '',
rates: {},
count: 0
}
})
然后我在我的地图
中使用这个CustomCircleMarker
var marker = new customCircleMarker(latlng, {stroke: false, className: 'the-class-name', fillOpacity: 1, weight: 1})
var popupChartData = [{
label: 'low',
value: [geolocLoad[key].rate.low]
}, {
label: 'medium',
value: [geolocLoad[key].rate.medium]
}, {
label: 'high',
value: [geolocLoad[key].rate.high]
}]
然后我绑定弹出窗口,用我的自定义数据填充标记并创建一个 on click
回调,它发出一条包含我的有用数据的消息。
marker.bindPopup('<div id="chart-' + key + '"></div>')
marker.countrycode = key
marker.rates = popupChartData
marker.count = geolocLoad[key].count
marker.on('click', function(e){
$scope.$emit('marker:click', this.countrycode, this.count, this.rates)
})
接收方将获取数据并以这种方式呈现图表:
$scope.$on('marker:click', function(caller, countrycode, count, rates){
console.log('received', countrycode, count, rates)
var width = 500,
height = 500
nv.addGraph(function(){
var chart = nv.models.pieChart()
.x(function(d) { return d.label })
.y(function(d) { return d.value })
.width(width)
.height(height);
d3.select("#chart-"+countrycode)
.datum(rates)
.attr('width', width)
.attr('height', height)
.call(chart);
return chart;
})
})
遗憾的是,这不再有效了..
注意:我没有使用 angular-leaflet-directive,因为我发现它太过分了而且不太喜欢它。你觉得我还是用它比较好吗?
我已经自己解决了这个问题,我发布了一个答案,因为它可能对未来的用户有帮助。
我忘记的最重要的事情是在弹出窗口中插入一个 <svg>
元素,这导致图表无法呈现,因为没有 'canvas' 我们库可以呈现它..
标记生成:
var marker = new customCircleMarker(countries.names[c].latlng, {stroke: false, className: 'the-class-name', fillOpacity: 1, weight: 1})
marker.bindPopup('<div id="chart-' + key + '" class="country-popup-chart-container"><svg class="country-popup-chart"></svg></div>', {closeButton: false})
marker.countrycode = key
marker.rates = geolocLoad[key].rate
marker.count = geolocLoad[key].count
marker.on('click', function(e){
$scope.$emit('marker:click', this.countrycode, this.count, this.rates)
})
图表生成由在 click
上调用的 $emit
触发:
$scope.$on('marker:click', function(caller, countrycode, count, rates) {
var popupChartData = [{
label: 'low',
value: rates.low,
color: '#2ecc71'
}, {
label: 'medium',
value: rates.medium,
color: '#f1c40f'
}, {
label: 'high',
value: rates.high,
color: '#e74c3c'
}]
nv.addGraph(function(){
var chart = nv.models.pieChart()
.x(function(d) { return d.label })
.y(function(d) { return d.value })
.showLabels(false)
.donut(true)
.donutRatio(0.5)
d3.select('#chart-' + countrycode + ' svg')
.datum(popupChartData)
.call(chart)
return chart
})
})
根据以下 CSS
进行评估:
div.country-popup-chart-container{
height: 80px;
width: 200px;
}
最后的结果是: