代码之家  ›  专栏  ›  技术社区  ›  fredmaggiowski Alex

在传单弹出窗口中插入NVD3图表

  •  1
  • fredmaggiowski Alex  · 技术社区  · 8 年前

    在我的 AngularJs 我正在使用的web应用程序构建地图 Leaflet.js Leaflet markercluster .

    要渲染我使用的图表 nvd3.js 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}}
    }
    

    这意味着在地图中 圆形标记 将在美国和意大利的中心展出。

    现在让我们来讨论这个问题,我在每个上绑定一个弹出窗口 圆形标记 ,我希望每个弹出窗口都包含一个 nvd3 饼图(特别是甜甜圈),它将显示 rate 对于那个特定的国家。

    问题是当前地图渲染正确,标记放置完美,但当我单击标记时,出现的弹出窗口为空(见图)。我用谷歌搜索了一下,但找不到任何可以帮助我的东西。

    Empty Popup


    这就是我如何构建 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)
    

    更新

    我改变了一些事情。首先,我延长了 圆形标记

    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;
      })
    })
    

    遗憾的是,这又不起作用了。。 not working again

    注释 :我没有使用有棱角的传单指令,因为我觉得它太过分了,而且不太喜欢它。你认为我用它更好吗?

    1 回复  |  直到 8 年前
        1
  •  2
  •   fredmaggiowski Alex    8 年前

    我自己解决了这个问题,我正在发布一个答案,因为它可能会对未来的用户有所帮助。

    我忘记的最重要的事情是插入一个 <svg> 元素,这导致图表无法呈现,因为没有“画布”,我们的库可以呈现它。。

    标记生成:

    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)
    })
    

    图表生成由 $emit 在上调用 click :

    $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;
    }
    

    最终结果是:

    final result