如何从AmChart更新clickMapObject侦听器中的全局数据

时间:2018-12-03 17:23:23

标签: javascript angular amcharts

我正在了解AmChart js lib,我对此有些疑问。

我有一张地图,显示了数据库中注册的所有设备(请看下面的打印内容)

enter image description here

因此,我想实现一种功能,当用户单击地图中某个国家/地区的气泡时,表格列表按国家/地区过滤,因此,在设备中,表格应仅显示来自以下国家/地区的设备:用户点击的气泡。

为了在用户单击气泡时执行此过滤,我使用的是Amchart(clickjMapObject)的addListener,如下例所示。

 this.map.addListener('clickMapObject', function (event) {
    console.log(event);
    console.log(this.deviceList).
 });

console.log(event)正常工作,但是当我尝试打印"deviceList"时不工作。我收到以下错误:

  

错误TypeError:无法读取未定义的属性'devicesList'

我不知道是否可以在侦听器中访问全局数组,所以,我不知道这是什么问题。你能帮我吗?

按照下面的完整代码进行操作。 (在这段代码中,您可以看到如何填充"deviceList"

export class DevicesLocationComponent implements OnInit {

  public devicesList: Device[];
  public images = [];
  public country_location = [];
  public map: any;

  @ViewChild(DatatableComponent) table: DatatableComponent;

  constructor(private http: HttpClient, private deviceService: DeviceService) 
  {
    this.getCountryLocationJSON().subscribe(data => {
      this.country_location = data;
    });
  }


  /**
   * Build initial the chart and load devices location
   *
   * @memberof DevicesLocationComponent
   */
   public ngOnInit() {
     this.loadDeviceDataTable();
   }


   /**
    * This function is responsible to load datatable with devices data
    */
    private loadDeviceDataTable() {

      // load last used devices data
      this.deviceService.getAllDevices()
         .subscribe(((listDevices: Device[]) => {
              this.devicesList = listDevices;

             this.buildMapChart();   
      }));
    }

    /**
     * This function is responsible to build the map chart after load devices data on datatable.
     */
     private buildMapChart() {

        // get min and max values for define bubble size frm map chart
        const minBulletSize = 10;
        const maxBulletSize = 40;
        let min = Infinity;
        let max = -Infinity;
        for (const key in this.tardisDevicesGrouped) {
           if (this.tardisDevicesGrouped.hasOwnProperty(key)) {
               const value = this.tardisDevicesGrouped[key].length;
               if ( value < min ) {
                  min = value;
               }
               if ( value > max ) {
                 max = value;
               }
           }
        }

       // it's better to use circle square to show difference between values, not a radius
      const maxSquare = maxBulletSize * maxBulletSize * 2 * Math.PI;
      const minSquare = minBulletSize * minBulletSize * 2 * Math.PI;

      // create circle for each country
      for (const key in this.tardisDevicesGrouped) {
        if (this.tardisDevicesGrouped.hasOwnProperty(key)) {
          const value = this.tardisDevicesGrouped[key].length;
          const country_location = this.getLatLongCountry(key);

          // calculate size of a bubble
         let square = ( value - min ) / ( max - min ) * ( maxSquare - minSquare ) + minSquare;
         if ( square < minSquare ) {
           square = minSquare;
         }
         const size = Math.sqrt( square / ( Math.PI * 2 ) );

         // set each bubble size, value and colors for each country
         this.images.push( {
         'type': 'circle',
         'theme': 'light',
         'width': size,
         'height': size,
         'longitude': country_location.longitude,
         'latitude': country_location.latitude,
         'color': country_location.color,
         'title': country_location.country_name,
         'selectable': true,
         'value': value
       });
     }
   }

   this.map = AmCharts.makeChart('allocation-map', {
     'type': 'map',
     'hideCredits': true,
     'theme': 'light',
     'colorSteps': 10,
     'dataProvider': {
       'map': 'worldLow',
       'images': this.images,
       'zoomLevel': 1.0,
       'zoomLongitude': 10,
       'zoomLatitude': 52
     },
     'areasSettings': {
        'autoZoom': true,
        'selectable': true
     }
   });

   console.log(this.devicesList);  // It's working 

   this.map.addListener('clickMapObject', function (event) {
     console.log(event);
     console.log(this.devicesList);   // It's not working
    });
  }
}

1 个答案:

答案 0 :(得分:2)

在事件侦听器上方,您应该声明一个存储当前作用域的变量

var self = this

然后在该事件触发的函数内部,应将此引用更改为self

console.log(self.devicesList);

最后,您的代码应如下所示:

 console.log(this.devicesList);  // It's working 
 var self = this;
   this.map.addListener('clickMapObject', function (event) {
     console.log(event);
     console.log(self.devicesList);   // Now it will work
    });
  }

之所以会发生这种情况,是因为范围根据您所在的位置而变化,因此,“ this”在事件侦听器内部的含义与在组件内部的含义不同,引用会发生变化