You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular中Highcharts气泡图与下拉选择器联动功能实现咨询

实现方案

以下是完整的实现步骤和代码,可直接复用后根据实际业务调整下拉逻辑:

第一步:导入双向绑定依赖

如果使用Angular的双向绑定语法,需要先在app.module.ts中导入FormsModule:

// app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms'; // 新增导入
import { AppComponent } from './app.component';

@NgModule({
  imports: [BrowserModule, FormsModule], // 把FormsModule加入导入列表
  declarations: [AppComponent],
  bootstrap: [AppComponent]
})
export class AppModule { }

第二步:修改HTML模板,新增下拉选择器

替换app.component.html的原有内容,新增两个下拉选择器,绑定选中值和变化事件:

<h1 style="text-align:center">Angular气泡图示例</h1>
<!-- 下拉选择器区域 -->
<div style="display: flex; gap: 20px; padding: 0 20px 20px;">
  <div>
    <label>筛选展示区域:</label>
    <select [(ngModel)]="selectedRegion" (change)="updateChart()">
      <option *ngFor="let option of regionOptions" [value]="option.value">{{option.label}}</option>
    </select>
  </div>
  <div>
    <label>气泡大小对应指标:</label>
    <select [(ngModel)]="selectedBubbleMetric" (change)="updateChart()">
      <option *ngFor="let option of metricOptions" [value]="option.value">{{option.label}}</option>
    </select>
  </div>
</div>
<div id="container"></div>

第三步:修改TS逻辑,实现数据联动更新

核心改动点:将原本写死在配置里的图表数据抽离为独立变量,存储Highcharts实例方便更新,新增下拉变化后的图表重绘逻辑,完整代码如下:

import { Component, OnInit } from '@angular/core';
import * as Highcharts from 'highcharts';

declare var require: any;
const More = require('highcharts/highcharts-more');
More(Highcharts);

const Exporting = require('highcharts/modules/exporting');
Exporting(Highcharts);

const ExportData = require('highcharts/modules/export-data');
ExportData(Highcharts);

const Accessibility = require('highcharts/modules/accessibility');
Accessibility(Highcharts);

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  implements OnInit{
  // 下拉选项数组,可根据业务需求自定义修改
  public regionOptions = [
    {label: '全部国家', value: 'all'},
    {label: '欧洲', value: 'europe'},
    {label: '美洲/大洋洲', value: 'other'}
  ];
  public metricOptions = [
    {label: '肥胖率', value: 'obesity'},
    {label: '糖分摄入量', value: 'sugar'},
    {label: '脂肪摄入量', value: 'fat'}
  ];

  // 下拉选中默认值
  public selectedRegion = 'all';
  public selectedBubbleMetric = 'obesity';

  // 原始全量图表数据,从原有配置中抽离出来
  private originalData = [
    { x: 95, y: 95, z: 13.8, name: 'BE', country: '比利时', region: 'europe' },
    { x: 86.5, y: 102.9, z: 14.7, name: 'DE', country: '德国', region: 'europe' },
    { x: 80.8, y: 91.5, z: 15.8, name: 'FI', country: '芬兰', region: 'europe' },
    { x: 80.4, y: 102.5, z: 12, name: 'NL', country: '荷兰', region: 'europe' },
    { x: 80.3, y: 86.1, z: 11.8, name: 'SE', country: '瑞典', region: 'europe' },
    { x: 78.4, y: 70.1, z: 16.6, name: 'ES', country: '西班牙', region: 'europe' },
    { x: 74.2, y: 68.5, z: 14.5, name: 'FR', country: '法国', region: 'europe' },
    { x: 73.5, y: 83.1, z: 10, name: 'NO', country: '挪威', region: 'europe' },
    { x: 71, y: 93.2, z: 24.7, name: 'UK', country: '英国', region: 'europe' },
    { x: 69.2, y: 57.6, z: 10.4, name: 'IT', country: '意大利', region: 'europe' },
    { x: 68.6, y: 20, z: 16, name: 'RU', country: '俄罗斯', region: 'europe' },
    { x: 65.5, y: 126.4, z: 35.3, name: 'US', country: '美国', region: 'other' },
    { x: 65.4, y: 50.8, z: 28.5, name: 'HU', country: '匈牙利', region: 'europe' },
    { x: 63.4, y: 51.8, z: 15.4, name: 'PT', country: '葡萄牙', region: 'europe' },
    { x: 64, y: 82.9, z: 31.3, name: 'NZ', country: '新西兰', region: 'other' }
  ];

  // 存储Highcharts实例,用于后续更新操作
  private chartInstance: Highcharts.Chart;

  public options: any = {
    chart: {
        type: 'bubble',
        plotBorderWidth: 1,
        zoomType: 'xy'
    },
    legend: {
        enabled: false
    },
    title: {
        text: '各国糖分与脂肪摄入量统计'
    },
    accessibility: {
        point: {
            valueDescriptionFormat: '{index}. {point.name}, 脂肪: {point.x}g, 糖分: {point.y}g, 肥胖率: {point.z}%.'
        }
    },
   xAxis: {
        gridLineWidth: 1,
        title: {
            text: '每日脂肪摄入量'
        },
        labels: {
            format: '{value} 克'
        },
        plotLines: [{
            color: 'black',
            dashStyle: 'dot',
            width: 2,
            value: 65,
            label: {
                rotation: 0,
                y: 15,
                style: {
                    fontStyle: 'italic'
                },
                text: '推荐脂肪摄入量上限 65克/天'
            },
            zIndex: 3
        }],
        accessibility: {
            rangeDescription: '范围:60到100克'
        }
    },
    yAxis: {
        startOnTick: false,
        endOnTick: false,
        title: {
            text: '每日糖分摄入量'
        },
        labels: {
            format: '{value} 克'
        },
        maxPadding: 0.2,
        plotLines: [{
            color: 'black',
            dashStyle: 'dot',
            width: 2,
            value: 50,
            label: {
                align: 'right',
                style: {
                    fontStyle: 'italic'
                },
                text: '推荐糖分摄入量上限 50克/天',
                x: -10
            },
            zIndex: 3
        }],
        accessibility: {
            rangeDescription: '范围:0到160克'
        }
    },
    tooltip: {
        useHTML: true,
        headerFormat: '<table>',
        pointFormat: '<tr><th colspan="2"><h3>{point.country}</h3></th></tr>' +
            '<tr><th>脂肪摄入量:</th><td>{point.x}g</td></tr>' +
            '<tr><th>糖分摄入量:</th><td>{point.y}g</td></tr>' +
            '<tr><th>成年人口肥胖率:</th><td>{point.z}%</td></tr>',
        footerFormat: '</table>',
        followPointer: true
    },
    plotOptions: {
        series: {
            dataLabels: {
                enabled: true,
                format: '{point.name}'
            }
        }
    },
    series: [{
        data: [] // 初始化为空,初始化时再赋值
    }]
  }

  constructor() { }

  ngOnInit(){
    this.chartInstance = Highcharts.chart('container', this.options);
    // 初始化渲染默认数据
    this.updateChart();
  }

  // 下拉选项变化时触发图表更新
  updateChart() {
    // 按选中区域过滤数据
    let filteredData = [...this.originalData];
    if (this.selectedRegion !== 'all') {
      filteredData = filteredData.filter(item => item.region === this.selectedRegion);
    }

    // 按选中指标修改气泡大小(z值)
    const processedData = filteredData.map(item => {
      let zVal = item.z;
      switch(this.selectedBubbleMetric) {
        case 'sugar': zVal = item.y; break;
        case 'fat': zVal = item.x; break;
        default: zVal = item.z;
      }
      return {...item, z: zVal};
    });

    // 更新图表数据,自动触发重绘
    this.chartInstance.series[0].setData(processedData);
  }
}

如果你的业务逻辑和示例不同,只需要调整下拉选项配置和updateChart方法内的数据处理规则即可,核心逻辑都是「根据选中值处理数据→调用setData方法更新图表」。

内容的提问来源于stack exchange,提问作者Rahul

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 07:18:02