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

如何用Bokeh制作带Scrubber组件的动画并导出为HTML?

用Bokeh实现带进度条(Scrubber)的动画并导出HTML

需求背景

原本在Matplotlib中可通过FuncAnimation制作动画,并用to_jshtml()导出包含进度条(Scrubber)的HTML。现在需要在Bokeh中实现相同功能,同时利用Bokeh的定制化特性。

实现方案

Bokeh可以通过Slider组件作为进度条,结合JavaScript回调实现帧切换,最终导出独立HTML文件。以下是与Matplotlib示例对应的完整可复现代码:

import xarray as xr
from bokeh.plotting import figure, save
from bokeh.models import LinearColorMapper, ColorBar, Slider, CustomJS, ColumnDataSource
from bokeh.layouts import column
from bokeh.palettes import Coolwarm

# 加载并处理数据,与Matplotlib示例保持一致
ds = xr.tutorial.open_dataset('air_temperature')
tas = ds.air - 273.15
frames = 40

# 准备初始帧数据
initial_data = tas[0, :, :].values
x = tas.lon.values
y = tas.lat.values
time_values = [str(t)[:13] for t in tas.coords['time'].values[:frames]]

# 创建颜色映射,对应coolwarm色阶
color_mapper = LinearColorMapper(palette=Coolwarm[256], vmin=-40, vmax=40)

# 创建数据源,用于动态更新
source = ColumnDataSource(data={'image': [initial_data], 'x': [x[0]], 'y': [y[0]], 
                                'dw': [x[-1]-x[0]], 'dh': [y[-1]-y[0]]})

# 创建绘图对象
p = figure(title=f"Time = {time_values[0]}", 
           x_range=(x.min(), x.max()), y_range=(y.min(), y.max()),
           width=800, height=400)

# 添加图像图层
p.image(image='image', x='x', y='y', dw='dw', dh='dh', source=source,
        color_mapper=color_mapper)

# 添加颜色条
color_bar = ColorBar(color_mapper=color_mapper, label_standoff=12, location=(0,0))
p.add_layout(color_bar, 'right')

# 创建进度条(Slider)
slider = Slider(start=0, end=frames-1, value=0, step=1, title="Frame")

# 编写回调函数,实现进度条控制帧切换
callback = CustomJS(args=dict(source=source, slider=slider, time_values=time_values, tas_data=tas.values[:frames], p=p),
                    code="""
    const frame = slider.value;
    // 更新图像数据
    source.data['image'] = [tas_data[frame]];
    // 更新标题
    p.title.text = `Time = ${time_values[frame]}`;
    source.change.emit();
""")

# 将回调绑定到进度条
slider.js_on_change('value', callback)

# 可选:添加播放按钮实现自动播放
from bokeh.models import Button

play_button = Button(label="Play", button_type="success")
play_callback = CustomJS(args=dict(slider=slider, frames=frames),
                         code="""
    let is_playing = false;
    let interval;
    if (!is_playing) {
        is_playing = true;
        this.label = "Pause";
        interval = setInterval(() => {
            let next_frame = slider.value + 1;
            if (next_frame >= frames) next_frame = 0;
            slider.value = next_frame;
        }, 200);
        this.interval = interval;
    } else {
        is_playing = false;
        this.label = "Play";
        clearInterval(this.interval);
    }
""")
play_button.js_on_click(play_callback)

# 布局组件并导出HTML
layout = column(p, slider, play_button)
save(layout, "bokeh_animation_scrubber.html")

关键细节说明

  • 进度条控制:通过Slider组件的value变化触发CustomJS回调,动态更新图像数据和标题,实现拖拽进度条切换帧的功能。
  • 颜色映射:用LinearColorMapper匹配Matplotlib的coolwarm色阶,保证视觉效果一致。
  • 导出HTML:调用save()方法直接生成独立HTML文件,无需依赖Jupyter环境,打开即可交互。
  • 定制扩展:示例中额外添加了播放/暂停按钮,可根据需求扩展更多交互(如调整播放速度、添加帧标签等)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 04:17:14