Python Pyecharts动态气泡图代码:适合大屏展示的渲染实现

闻溪
闻溪
发布时间:2026-11-01 | 4人浏览过
原创

本文详解使用 Python Pyecharts 库构建适合大屏展示的动态气泡图完整方案。包含 Timeline 时间轮播与 Scatter 散点图的维度映射、大屏深色主题调优、坐标轴防抖锁定、完整可运行代码以及上线校验清单。

在企业数据指挥中心、经营监控中心或展厅可视化大屏中,静态散点图往往难以表达多维指标随着时间推进的演化格局。借助 Python 的 Pyecharts 库,通过将时间轮播组件 Timeline 与散点图 Scatter 深度集成,能够以单图承载 X轴指标、Y轴指标、气泡半径(第三指标)、色彩区分(行业分类)以及时间步进(时间维度)共五维数据。本文直接提供一套面向大屏展示环境的动态气泡图完整构建方案与生产级代码,解决大屏场景下的深色主题匹配、自动循环播控、坐标轴防抖锁定及全屏容器自适应等核心问题。

一、多维数据映射与Timeline播控联动机制

动态气泡图在技术实现上不是简单的一张图,而是一个“时序切片播放序列”。Pyecharts 的底层逻辑基于百度开源的 ECharts 架构:外部由 Timeline 组件担当时间轴控制器,内部维护每个时间切片(例如各年度、各季度或各监控批次)对应的独立 Scatter 实例。通过统一配置视觉映射组件 VisualMapOpts,动态将某一核心度量数值缩放映射至图形符号的大小 symbol_size 上,从而生成直观的气泡形态。

Python Pyecharts动态气泡图代码:适合大屏展示的渲染实现
图1:Pyecharts 动态气泡图核心架构与多维映射机制

二、开发准备与时序数据结构组织

在开始编写代码前,确保安装了较新版本的 Pyecharts(建议 2.0.0 以上版本)。使用 pip 命令直接安装:

pip install pyecharts

为了在大屏上展示气泡图,输入数据需要按“时间切片”组织。每个切片包含若干观测主体(例如代表各家企业或业务单元的泡泡)。为了实现平滑切换与准确的视觉对比,数据应当规范为包含主体名称、X轴度量、Y轴度量、气泡尺寸度量和分类标签的结构化列表。以下示例构建了 2020 年至 2024 年 5 个连续年度下,多家代表性科技企业的模拟发展数据:

字段名 数据类型 大屏展示含义 示例取值
year 字符串 / 整数 Timeline 切换切片标记 "2024年"
name 字符串 气泡对应的主体标签 "企业A"
x_value 浮点数 横向位置:研发投入(亿元) 128.5
y_value 浮点数 纵向位置:营业收入(亿元) 640.2
size_value 浮点数 气泡面积映射:净利润(亿元) 92.4
category 字符串 散点所属行业,决定色彩分组 "智能制造"

三、适合大屏展示的完整工程代码

以下是经过大屏场景针对性调优后的完整 Python 代码。代码中内置了深色主题初始化、坐标轴极值全局固定、气泡半透明度调校、自动播放及大屏容器适配配置。可以直接保存为独立 Python 文件运行:

# -*- coding: utf-8 -*-
"""
Python Pyecharts 动态气泡图:大屏展示渲染实现
功能说明:
1. 使用 Timeline + Scatter 呈现 2020-2024 年度动态演进
2. 采用 ThemeType.DARK 保证深色大屏视觉沉浸感
3. 全局固定坐标轴极值,彻底消除翻帧抖动
4. 配置气泡半透明与高光层叠,兼顾多主体遮挡问题
"""

from pyecharts import options as opts
from pyecharts.charts import Scatter, Timeline
from pyecharts.globals import ThemeType
from pyecharts.commons.utils import JsCode

# 1. 模拟 2020-2024 年大屏业务数据
# 格式: [研发投入(X), 营业收入(Y), 净利润(Size), 实体名称(Name), 所属板块(Category)]
years = ["2020年", "2021年", "2022年", "2023年", "2024年"]

dataset = {
    "2020年": [
        [35, 120, 18, "星云智造", "智能制造"],
        [20, 80, 12, "极光软件", "基础软件"],
        [50, 210, 35, "天脉生物", "生物医药"],
        [15, 60, 8, "华芯微电", "半导体"],
        [40, 150, 22, "量子数能", "新能源"],
    ],
    "2021年": [
        [45, 160, 26, "星云智造", "智能制造"],
        [28, 110, 19, "极光软件", "基础软件"],
        [68, 290, 52, "天脉生物", "生物医药"],
        [25, 95, 16, "华芯微电", "半导体"],
        [58, 220, 38, "量子数能", "新能源"],
    ],
    "2022年": [
        [60, 220, 38, "星云智造", "智能制造"],
        [42, 160, 30, "极光软件", "基础软件"],
        [85, 380, 70, "天脉生物", "生物医药"],
        [40, 150, 28, "华芯微电", "半导体"],
        [82, 310, 55, "量子数能", "新能源"],
    ],
    "2023年": [
        [78, 290, 54, "星云智造", "智能制造"],
        [58, 220, 42, "极光软件", "基础软件"],
        [110, 490, 95, "天脉生物", "生物医药"],
        [62, 230, 45, "华芯微电", "半导体"],
        [105, 420, 78, "量子数能", "新能源"],
    ],
    "2024年": [
        [102, 380, 75, "星云智造", "智能制造"],
        [76, 290, 58, "极光软件", "基础软件"],
        [140, 620, 130, "天脉生物", "生物医药"],
        [88, 330, 68, "华芯微电", "半导体"],
        [135, 540, 105, "量子数能", "新能源"],
    ],
}

# 2. 提取全局坐标轴的最大值,防止帧间切换坐标轴跳动
max_x = max(max(item[0] for item in data) for data in dataset.values()) * 1.15
max_y = max(max(item[1] for item in data) for data in dataset.values()) * 1.15
max_size = max(max(item[2] for item in data) for data in dataset.values())

# 3. 初始化时间轮播组件 (Timeline)
# 大屏展示必须指定 width/height 为 100%,或设定适配大屏的宽高像素
timeline = Timeline(
    init_opts=opts.InitOpts(
        theme=ThemeType.DARK,
        width="100%",
        height="100%",
        bg_color="#141b24",  # 大屏专业深灰蓝背景
        page_title="经营全景动态气泡图-大屏可视化"
    )
)

# 4. 逐年构建单帧 Scatter 散点图并挂载至 Timeline
for year in years:
    current_data = dataset[year]
    
    # 格式化数据,Pyecharts Scatter 接收的数据格式为 [x, y, size, name, category]
    scatter_data = [
        [item[0], item[1], item[2], item[3], item[4]]
        for item in current_data
    ]
    
    scatter = (
        Scatter(init_opts=opts.InitOpts(theme=ThemeType.DARK))
        .add_xaxis([d[0] for d in scatter_data])
        .add_yaxis(
            series_name="核心企业监控",
            y_axis=[[d[1], d[2], d[3], d[4]] for d in scatter_data],
            # 气泡半径动态映射:通过 JS 代码或系数计算基础像素大小
            symbol_size=JsCode(
                """
                function(val) {
                    // val[2] 为净利润数值,乘以缩放系数 + 基础像素半径
                    return Math.sqrt(val[2]) * 5 + 10;
                }
                """
            ),
            label_opts=opts.LabelOpts(
                is_show=True,
                position="right",
                formatter=JsCode("function(param){ return param.data[3]; }"),
                color="#ffffff",
                font_size=12,
                font_weight="bold"
            ),
            # 气泡半透明与柔和阴影,避免大屏密集重叠时无法辨识
            itemstyle_opts=opts.ItemStyleOpts(
                opacity=0.78,
                border_color="#ad8b58",
                border_width=1.5
            )
        )
        .set_global_opts(
            title_opts=opts.TitleOpts(
                title=f"重点企业多维成长动态走势 ({year})",
                subtitle="横轴:研发投入(亿元) | 纵轴:营业收入(亿元) | 气泡大小:净利润",
                pos_left="3%",
                pos_top="2%",
                title_textstyle_opts=opts.TextStyleOpts(font_size=20, color="#ffffff"),
                subtitle_textstyle_opts=opts.TextStyleOpts(font_size=13, color="#ad8b58")
            ),
            tooltip_opts=opts.TooltipOpts(
                is_show=True,
                trigger="item",
                formatter=JsCode(
                    """
                    function(params) {
                        var d = params.data;
                        return '
' + '' + d[3] + ' (' + d[4] + ')
' + '年度: """ + year + """
' + '研发投入: ' + d[0] + ' 亿元
' + '营业收入: ' + d[1] + ' 亿元
' + '净利润: ' + d[2] + ' 亿元' + '
'; } """ ), background_color="rgba(30, 41, 59, 0.95)", border_color="#ad8b58", border_width=1 ), # 必须固定 X 轴范围 xaxis_opts=opts.AxisOpts( name="研发投入 (亿元)", name_location="end", type_="value", min_=0, max_=int(max_x), splitline_opts=opts.SplitLineOpts(is_show=True, linestyle_opts=opts.LineStyleOpts(color="#223040")), axisline_opts=opts.AxisLineOpts(linestyle_opts=opts.LineStyleOpts(color="#64748b")), axistick_opts=opts.AxisTickOpts(is_show=True) ), # 必须固定 Y 轴范围 yaxis_opts=opts.AxisOpts( name="营业收入 (亿元)", name_location="end", type_="value", min_=0, max_=int(max_y), splitline_opts=opts.SplitLineOpts(is_show=True, linestyle_opts=opts.LineStyleOpts(color="#223040")), axisline_opts=opts.AxisLineOpts(linestyle_opts=opts.LineStyleOpts(color="#64748b")), axistick_opts=opts.AxisTickOpts(is_show=True) ), legend_opts=opts.LegendOpts(is_show=False) ) ) # 将该年图表挂入 Timeline timeline.add(scatter, time_point=year) # 5. 配置 Timeline 轮播属性 (关键大屏播控配置) timeline.add_schema( is_auto_play=True, # 启动自动轮播 is_loop_play=True, # 循环播控 play_interval=2000, # 切换间隔 (2000毫秒 = 2秒) is_timeline_show=True, # 显示底部时间轴供大屏操作员手动干预 control_position="left", # 播放/暂停控制按钮置于左侧 pos_bottom="20px", pos_left="5%", pos_right="5%", # 时间轴高光与深色样式 linestyle_opts=opts.LineStyleOpts(color="#394957", width=2), label_opts=opts.LabelOpts(color="#94a3b8", font_size=12) ) # 6. 生成输出 HTML if __name__ == "__main__": output_filename = "dynamic_bubble_screen.html" timeline.render(output_filename) print(f"动态气泡图渲染完成,输出路径: {output_filename}")

四、构建流程与核心配置深度解析

为了让这套代码在大屏工程环境中长期稳定运行,必须理解从原始切片到渲染交付的流水线细节。下图总结了整个构建流程的五个核心阶段:

Python Pyecharts动态气泡图代码:适合大屏展示的渲染实现
图2:动态气泡图端到端构建与大屏渲染流程

关键原理提醒:为什么不能用默认坐标轴自适应?

在普通静态图表中,ECharts 默认会根据当前单帧数据的最小值与最大值自动计算坐标范围。但在 Timeline 动态轮播时,如果 2020 年 X 轴最大值是 50,而 2024 年增加到 140,若不固定极值,坐标轴会在每一帧切换时剧烈伸缩。这会导致一个实际高速增长的气泡在屏幕像素位置上“原地踏步甚至后退”。因此,先遍历全部时序切片求出全量最大值并显式写入 min_ 和 max_,是动态气泡图不发生感知偏差的首要前提。

五、面向大屏展示环境的 4 项关键调优策略

将动态气泡图放入展厅大屏或指挥中心时,环境从“个人电脑前 50 厘米近距离浏览”转变为“距屏幕 3 至 10 米远距离观察”。这种视距差异对色彩、排版、交互提出了截然不同的要求:

Python Pyecharts动态气泡图代码:适合大屏展示的渲染实现
图3:普通报表模式与大屏专业模式的工程配置参数对比

1. 气泡尺寸的开方映射算法(避免“大球吞小球”)

如果直接将净利润数值传递给气泡半径,气泡的“面积”实际上会随数值的平方倍增。例如净利润 100 亿与 10 亿相比,数值差 10 倍,如果半径差 10 倍,面积将相差 100 倍!这会导致大企业的气泡遮蔽半个屏幕,而中小企业的气泡缩成一个看不见的点。因此必须通过开方(Math.sqrt)算法对数值进行几何压缩,再叠加底线基础半径:

symbol_size=JsCode("""
    function(val) {
        // val[2] 代表第三维度数据值
        var sizeMetric = val[2];
        if (sizeMetric <= 0) return 6; // 保证非正数有基本占位
        return Math.sqrt(sizeMetric) * 5 + 8;
    }
""")

2. 气泡半透明与高光描边(处理多图元重叠)

在大屏多企业同场竞逐时,坐标接近的企业难免发生空间重叠。配置 opacity=0.78 并辅以 1.5 像素的高反差描边(如暗金 #ad8b58 或冷白),可以使上下层气泡在交叠时产生类似玻璃切片的通透感,观察者即使在远距离也能清晰看清底层气泡的轮廓和名称。

3. 时间线轮播与播放控制器微调

在大屏展出时,播放控件的位置通常不宜占据顶部或图表正中。推荐使用 pos_bottom="20px" 将时间轴置于底部,并将播放按钮(Play/Pause)放在左下角。对于不需要人工操作的无人巡检模式,甚至可以将控制按钮隐藏,仅保留时间刻度点。

六、上线交付与集成运行检查清单

在将生成的 HTML 页面交付至大屏系统或通过 iframe 挂载进前端看板之前,请对照以下检查清单完成技术复盘:

Python Pyecharts动态气泡图代码:适合大屏展示的渲染实现
图4:大屏动态气泡图上线与运维检查清单

七、大屏 HTML 容器集成范例

当通过 Python 成功生成 dynamic_bubble_screen.html 之后,在前端或大屏系统的综合看板中,可以通过以下标准的纯净全屏 iframe 容器代码将其无缝嵌入,达到完全无边界的沉浸式效果:

<!-- 大屏仪表盘网格容器示例 -->
<div style="width: 100vw; height: 100vh; background-color: #141b24; overflow: hidden; position: relative;">
  <iframe 
    src="./dynamic_bubble_screen.html" 
    frameborder="0" 
    scrolling="no" 
    style="width: 100%; height: 100%; border: none; display: block;">
  </iframe>
</div>

通过本文提供的完整代码与参数方案,你可以快速将多维时序数据转化为具有专业视觉张力、动感流畅且符合大屏工程规范的动态气泡图,为企业数据大屏增添深度洞察力。

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表