R

ReflexKR

Reflex 官方文档

组件工坊:Reflex 组件库 100 例

·

课程概览

布局

·

Box

·

Flex

·

Stack

·

Grid

·

Container

·

Section

·

Center

·

Spacer

·

Separator

·

Card

·

Inset

·

Aspect Ratio

·

Fragment

排版

·

Text

·

Heading

·

Link

·

Code

·

Markdown

·

Blockquote

·

Quote

·

Strong

·

Em

·

Kbd

表单

·

Button

·

Input

·

Text Area

·

Checkbox

·

Switch

·

Radio Group

·

Select

·

Slider

·

Form

·

Upload

数据展示

·

Badge

·

Avatar

·

Icon

·

Callout

·

List

·

Data List

·

Code Block

·

Progress

·

Spinner

·

Scroll Area

·

Moment

展开与切换

·

Tabs

·

Accordion

·

Segmented Control

浮层

·

Tooltip

·

Popover

·

Hover Card

·

Dialog

·

Alert Dialog

·

Drawer

·

Dropdown Menu

·

Context Menu

·

Toast

动态渲染

·

Cond

·

Match

·

Foreach

·

Auto Scroll

媒体

·

Image

·

Audio

·

Video

表格与数据网格

·

Table

·

Data Table

·

Data Editor

图表

·

Area Chart

·

Bar Chart

·

Line Chart

·

Composed Chart

·

Pie Chart

·

Radar Chart

·

Radial Bar Chart

·

Scatter Chart

·

Funnel Chart

·

Treemap

·

Sankey Chart

·

Error Bar

图表部件

·

Axis

·

Cartesian Grid

·

Chart Tooltip

·

Legend

·

Label

·

Reference

·

Brush

其他图表库

·

Plotly

·

Pyplot

HTML 元素

·

HTML

·

HTML Text

·

HTML Layout

·

HTML Forms

·

HTML Media

·

HTML Tables

·

SVG

其他工具

·

Theme

·

Skeleton

·

Clipboard

·

Html Embed

·

Script

·

Memo

组件工坊:Reflex 组件库 100 例
其他图表库

Plotly

rx.plotly

官方文档

工坊订单

请把各产品一年的销售额做成可以缩放查看的交互式图表,选择产品时图表随之切换。

Plotly 是用来制作可缩放、可平移、可悬停查看的交互式图表的 Python 库。rx.plotly 直接接收 Plotly 的 Figure 并在浏览器中绘制。折线、柱形等基础图表自不必说,连热力图、3D、金融图表也都不用写 JavaScript。

不像平常写脚本那样调用 fig.show(),而是在 UI 代码里用 rx.plotly(data=fig) 传入。需要的包是 plotly,本课程用 plotly.graph_objects(go)来绘图。

import plotly.graph_objects as go

plotly_years = [1952, 1957, 1962, 1967, 1972, 1977, 1982, 1987, 1992, 1997, 2002, 2007]
plotly_canada = [68.75, 69.96, 71.3, 72.13, 72.88, 74.21, 75.76, 76.86, 77.95, 78.61, 79.77, 80.65]

plotly_line_fig = go.Figure(go.Scatter(x=plotly_years, y=plotly_canada, mode="lines", name="Canada"))
plotly_line_fig.update_layout(title="Life expectancy in Canada")


rx.plotly(data=plotly_line_fig, width="100%")

官方文档的示例大多使用 plotly.express(px)。px 依赖 pandas,所以本页改用 go 画出同样的图,数据则写成 Python 列表。用 px 画出的图也是 Figure,传给 rx.plotly 的方法完全一样。

试着改属性

给 layout 传一个 dict,会覆盖到图的布局之上。在图不变的前提下,只从界面一侧改标题、高度、背景时很方便。下面的实验台和部分示例直接使用上面的 plotly_line_fig。

试着改属性

title

height

400

showlegend

plot_bgcolor

locale

rx.plotly(
    data=plotly_line_fig,
    layout={"title": {"text": "Life expectancy"}, "height": 400, "showlegend": False, "plot_bgcolor": "rgba(0,0,0,0)"},
    locale="en",
    width="100%",
)
layout 会覆盖图的布局,locale 会改变数字格式以及右上角工具栏的提示文字。
属性取值默认值用途
datago.Figure 或其 dict-要绘制的图。也可以是 State 值
layoutdict-覆盖到图布局上的值
templatePlotly Template浅色模式 plotly,深色模式 plotly_dark整体配色与字体主题
configdict-工具栏、滚轮缩放等 Plotly 设置
locale"de" "ko" …-数字、日期格式和工具栏文字的语言
use_resize_handlerTrue / FalseTrue窗口尺寸变化时重新适配
on_click · on_hover · on_unhover · on_selected · on_selecting事件-传入点的列表(list[dict])
on_relayout · on_double_click · on_deselect · on_after_plot 等事件-缩放与平移、双击、取消选择、重绘之后(无参数)

不设 template 时,Reflex 会根据浅色模式和深色模式自动切换主题。Reflex 0.10 的 rx.plotly 还有官方文档表格里没有列出的 on_click 和 on_double_click。

各种图表

下面是把官方文档的 Plotly Express 示例改写成 go 的版本。无论哪种图,都同样用 rx.plotly(data=图) 传入。数据是为示例生成的值。

柱形图

放入多个 go.Bar,用 barmode="group" 让它们并排。相当于 px.bar(..., color="country")。

import plotly.graph_objects as go

plotly_bar_fig = go.Figure([
    go.Bar(name="Chairs", x=["Q1", "Q2", "Q3", "Q4"], y=[120, 150, 170, 210]),
    go.Bar(name="Tables", x=["Q1", "Q2", "Q3", "Q4"], y=[80, 95, 130, 120]),
])
plotly_bar_fig.update_layout(barmode="group", title="Orders by quarter")


rx.plotly(data=plotly_bar_fig, width="100%")

散点图

给 go.Scatter 设 mode="markers" 就只画点。每个分组各建一个 trace,颜色和图例就会分开。

import random
import plotly.graph_objects as go

plotly_scatter_rng = random.Random(7)
plotly_scatter_fig = go.Figure([
    go.Scatter(
        x=[plotly_scatter_rng.gauss(cx, 0.3) for _ in range(30)],
        y=[plotly_scatter_rng.gauss(cy, 0.4) for _ in range(30)],
        mode="markers",
        name=name,
    )
    for name, cx, cy in [("A", 3.4, 5.0), ("B", 2.8, 5.9), ("C", 3.0, 6.6)]
])
plotly_scatter_fig.update_layout(title="Sample clusters", xaxis_title="width", yaxis_title="length")


rx.plotly(data=plotly_scatter_fig, width="100%")

饼图

给 go.Pie 传入名称(labels)和数值(values),比例由 Plotly 计算。

import plotly.graph_objects as go

plotly_pie_fig = go.Figure(go.Pie(labels=["Thur", "Fri", "Sat", "Sun"], values=[171.83, 51.96, 260.40, 247.39]))
plotly_pie_fig.update_layout(title="Tips by day")


rx.plotly(data=plotly_pie_fig, width="100%")

热力图

go.Histogram2d 会把两个值的组合越密集的格子涂得越深(px.density_heatmap)。如果已经有算好的表格,就用 go.Heatmap(z=...)。

import random
import plotly.graph_objects as go

plotly_heat_rng = random.Random(3)
plotly_bills = [plotly_heat_rng.gauss(20, 8) for _ in range(300)]
plotly_tips = [b * 0.15 + plotly_heat_rng.gauss(0, 0.8) for b in plotly_bills]

plotly_heatmap_fig = go.Figure(go.Histogram2d(x=plotly_bills, y=plotly_tips, nbinsx=20, nbinsy=15))
plotly_heatmap_fig.update_layout(title="Bill vs tip density heatmap")


rx.plotly(data=plotly_heatmap_fig, width="100%")

直方图

go.Histogram 把数值划分成区间并计数。nbinsx 是区间数的上限。

import random
import plotly.graph_objects as go

plotly_hist_rng = random.Random(5)
plotly_hist_fig = go.Figure(go.Histogram(x=[plotly_hist_rng.gauss(20, 8) for _ in range(250)], nbinsx=20))
plotly_hist_fig.update_layout(title="Distribution of total bills")


rx.plotly(data=plotly_hist_fig, width="100%")

箱线图

go.Box 用一个箱子展示中位数、四分位数和离群值。每个分组各放一个 trace。

import random
import plotly.graph_objects as go

plotly_box_rng = random.Random(11)
plotly_box_fig = go.Figure([
    go.Box(y=[plotly_box_rng.gauss(mean, 6) for _ in range(40)], name=day)
    for day, mean in [("Thur", 17), ("Fri", 17), ("Sat", 20), ("Sun", 21)]
])
plotly_box_fig.update_layout(title="Total bill by day")


rx.plotly(data=plotly_box_fig, width="100%")

气泡图

在散点图里用点的大小(marker.size)表示第三个值。把 x 轴改成 type="log",就等同于 px.scatter(..., log_x=True)。

import plotly.graph_objects as go

plotly_bubble_fig = go.Figure(go.Scatter(
    x=[800, 2500, 6000, 15000, 32000, 45000],
    y=[52, 61, 68, 74, 79, 82],
    text=["A", "B", "C", "D", "E", "F"],
    mode="markers",
    marker={"size": [20, 45, 30, 60, 25, 40], "color": [1, 2, 3, 4, 5, 6], "colorscale": "Viridis"},
))
plotly_bubble_fig.update_xaxes(type="log", title="income")
plotly_bubble_fig.update_layout(title="Income vs life expectancy", yaxis_title="years")


rx.plotly(data=plotly_bubble_fig, width="100%")

甘特图

日程表用横向柱形(orientation="h")来画。柱子的起点是 base,长度是以毫秒计的时长,x 轴设为日期轴。这正是 px.timeline 在内部做的事。再把 y 轴反转,让它从上往下读。

from datetime import date
import plotly.graph_objects as go

plotly_jobs = [("Job A", "2009-01-01", "2009-02-28"), ("Job B", "2009-03-05", "2009-04-15"), ("Job C", "2009-02-20", "2009-05-30")]
plotly_gantt_fig = go.Figure(go.Bar(
    y=[job for job, start, end in plotly_jobs],
    base=[start for job, start, end in plotly_jobs],
    x=[(date.fromisoformat(end) - date.fromisoformat(start)).days * 86_400_000 for job, start, end in plotly_jobs],
    orientation="h",
))
plotly_gantt_fig.update_xaxes(type="date")
plotly_gantt_fig.update_yaxes(autorange="reversed")


rx.plotly(data=plotly_gantt_fig, width="100%")

旭日图

把层级数据从中心的根向外圈展开。用 labels 和 parents 写出父子关系。

import plotly.graph_objects as go

plotly_sunburst_fig = go.Figure(go.Sunburst(
    labels=["Eve", "Cain", "Seth", "Enos", "Noam", "Abel", "Awan", "Enoch", "Azura"],
    parents=["", "Eve", "Eve", "Seth", "Seth", "Eve", "Eve", "Awan", "Eve"],
    values=[10, 14, 12, 10, 2, 6, 6, 4, 4],
))


rx.plotly(data=plotly_sunburst_fig, width="100%")

漏斗图

展示从访问到购买的每个阶段减少了多少。适合找出在哪个阶段流失最多。

import plotly.graph_objects as go

plotly_funnel_fig = go.Figure(go.Funnel(
    x=[39, 27.4, 20.6, 11, 2],
    y=["Website visit", "Downloads", "Potential customers", "Requested price", "Invoice sent"],
))


rx.plotly(data=plotly_funnel_fig, width="100%")

语言与数字格式:locale

locale 会把数字、日期格式和工具栏提示文字换成对应语言。下面是德语。也可以同时设 config;两者都有时,locale 的值最后生效。

rx.plotly(data=plotly_line_fig, locale="de", width="100%")

3D 曲面

给 go.Surface 传入高度值的二维列表(z),就成了曲面。官方文档读取的是 CSV 文件里的山体高度数据,这里使用公式生成的值。可以拖动旋转查看。

import math
import plotly.graph_objects as go

plotly_surface_z = [[60 + 40 * math.sin(x / 4) * math.cos(y / 5) + y for x in range(30)] for y in range(30)]

plotly_surface_fig = go.Figure(data=[go.Surface(z=plotly_surface_z)])
plotly_surface_fig.update_traces(contours_z=dict(show=True, usecolormap=True, highlightcolor="limegreen", project_z=True))
plotly_surface_fig.update_layout(scene_camera_eye=dict(x=1.87, y=0.88, z=-0.64), margin=dict(l=65, r=50, b=65, t=90))


rx.plotly(data=plotly_surface_fig, width="100%")

金融图表

K 线图

每个日期用一根蜡烛画出开盘价、最高价、最低价和收盘价。实体在开盘价与收盘价之间,影线在最低价与最高价之间。

import plotly.graph_objects as go

plotly_candle_fig = go.Figure(go.Candlestick(
    x=["2024-01-02", "2024-01-03", "2024-01-04", "2024-01-05", "2024-01-08", "2024-01-09"],
    open=[187.15, 184.22, 182.15, 181.99, 182.09, 183.92],
    high=[188.44, 185.88, 183.09, 182.76, 185.60, 185.15],
    low=[183.89, 183.43, 180.88, 180.17, 181.50, 182.73],
    close=[185.64, 184.25, 181.91, 181.18, 185.56, 185.14],
))
plotly_candle_fig.update_layout(title=dict(text="Stock price"), yaxis=dict(title=dict(text="USD")))


rx.plotly(data=plotly_candle_fig, width="100%")

瀑布图

展示初始值经过各项加减后如何变化。用 measure 指定每一项是变化量("relative")还是合计("total")。

import plotly.graph_objects as go

plotly_waterfall_fig = go.Figure(go.Waterfall(
    name="2018",
    orientation="v",
    measure=["relative", "relative", "total", "relative", "relative", "total"],
    x=["Sales", "Consulting", "Net revenue", "Purchases", "Other expenses", "Profit before tax"],
    textposition="outside",
    text=["+60", "+80", "", "-40", "-20", "Total"],
    y=[60, 80, 0, -40, -20, 0],
    connector={"line": {"color": "rgb(63, 63, 63)"}},
))
plotly_waterfall_fig.update_layout(title="Profit and loss statement 2018", showlegend=True)


rx.plotly(data=plotly_waterfall_fig, width="100%")

子弹图

用来代替仪表盘的小型条形图。给 go.Indicator 设上 gauge.shape="bullet",把实际值条、区间(steps)和目标线(threshold)放在同一行里。

import plotly.graph_objects as go

plotly_bullet_fig = go.Figure(go.Indicator(
    mode="number+gauge+delta",
    value=180,
    delta={"reference": 200},
    domain={"x": [0.25, 1], "y": [0.4, 0.6]},
    title={"text": "Revenue"},
    gauge={
        "shape": "bullet",
        "axis": {"range": [None, 300]},
        "threshold": {"line": {"color": "black", "width": 2}, "thickness": 0.75, "value": 170},
        "steps": [{"range": [0, 150], "color": "gray"}, {"range": [150, 250], "color": "lightgray"}],
        "bar": {"color": "black"},
    },
))
plotly_bullet_fig.update_layout(height=250)


rx.plotly(data=plotly_bullet_fig, width="100%")

统计图表:连续误差带

不用误差棒,而是用线条周围的浅色带来表示误差。把上边界正向、下边界反向连起来,组成一条绕一圈的线,再用 fill="toself" 填充内部。

import plotly.graph_objects as go

plotly_band_x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
plotly_band_y = [1, 2, 7, 4, 5, 6, 7, 8, 9, 10]
plotly_band_upper = [2, 3, 8, 5, 6, 7, 8, 9, 10, 11]
plotly_band_lower = [0, 1, 5, 3, 4, 5, 6, 7, 8, 9]

plotly_band_fig = go.Figure([
    go.Scatter(x=plotly_band_x, y=plotly_band_y, line=dict(color="rgb(0,100,80)"), mode="lines"),
    go.Scatter(
        x=plotly_band_x + plotly_band_x[::-1],
        y=plotly_band_upper + plotly_band_lower[::-1],
        fill="toself",
        fillcolor="rgba(0,100,80,0.2)",
        line=dict(color="rgba(255,255,255,0)"),
        hoverinfo="skip",
        showlegend=False,
    ),
])


rx.plotly(data=plotly_band_fig, width="100%")

地图(仅代码)

Plotly 的地图在绘制时会从外部服务器获取地图数据。轮廓地图(Scattergeo、Choropleth)使用 Plotly CDN 的地形数据,瓦片地图(Scattermap)使用地图瓦片服务器。本课程不使用外部资源,所以只展示代码。在应用中可以照常运行。

轮廓地图

轮廓地图的设置在图的 layout.geo 中,用 update_geos 调整湖泊、河流等显示。

import plotly.graph_objects as go

geo_fig = go.Figure(go.Scattergeo())
geo_fig.update_geos(
    visible=False,
    resolution=50,
    showlakes=True,
    lakecolor="Blue",
    showrivers=True,
    rivercolor="Blue",
)
geo_fig.update_layout(height=300, margin={"r": 0, "t": 0, "l": 0, "b": 0})


def geo_map_chart():
    return rx.plotly(data=geo_fig, width="100%")

散点地图

在瓦片地图上打点。官方文档用的是 px.scatter_map,用 go 则是 go.Scattermap。地图样式在 layout.map 中设定。

import plotly.graph_objects as go

map_fig = go.Figure(go.Scattermap(
    lat=[37.57, 35.18, 35.87],
    lon=[126.98, 129.08, 128.60],
    text=["Seoul", "Busan", "Daegu"],
    mode="markers",
    marker={"size": [18, 12, 10]},
))
map_fig.update_layout(
    map={"style": "open-street-map", "center": {"lat": 36.4, "lon": 127.8}, "zoom": 5},
    margin={"r": 0, "t": 0, "l": 0, "b": 0},
)


def scatter_map_chart():
    return rx.plotly(data=map_fig, width="100%")

表格与流程图

表格

go.Table 在 header 里接收列名,在 cells 里接收每一列的值列表。支持滚动和调整列顺序。

import plotly.graph_objects as go

plotly_table_fig = go.Figure(go.Table(
    header=dict(values=["A Scores", "B Scores"]),
    cells=dict(values=[[100, 90, 80, 90], [95, 85, 75, 95]]),
))


rx.plotly(data=plotly_table_fig, width="100%")

桑基图

用带子的粗细表示流量大小。在 node.label 里写节点名称,在 link 中用节点序号把 source→target 连起来。

import plotly.graph_objects as go

plotly_sankey_fig = go.Figure(go.Sankey(
    node=dict(pad=15, thickness=20, line=dict(color="black", width=0.5), label=["A1", "A2", "B1", "B2", "C1", "C2"], color="blue"),
    link=dict(source=[0, 1, 0, 2, 3, 3], target=[2, 3, 3, 4, 4, 5], value=[8, 4, 2, 8, 4, 2]),
))
plotly_sankey_fig.update_layout(title_text="Basic Sankey Diagram", font_size=10)


rx.plotly(data=plotly_sankey_fig, width="100%")

3D 图表

3D 散点图

go.Scatter3d 把三个值之间的关系画在空间里(px.scatter_3d)。

import random
import plotly.graph_objects as go

plotly_s3d_rng = random.Random(2)
plotly_s3d_fig = go.Figure([
    go.Scatter3d(
        x=[plotly_s3d_rng.gauss(cx, 0.4) for _ in range(30)],
        y=[plotly_s3d_rng.gauss(cy, 0.3) for _ in range(30)],
        z=[plotly_s3d_rng.gauss(cz, 0.3) for _ in range(30)],
        mode="markers",
        marker={"size": 4},
        name=name,
    )
    for name, cx, cy, cz in [("A", 5.0, 3.4, 0.2), ("B", 5.9, 2.8, 1.3), ("C", 6.6, 3.0, 2.0)]
])


rx.plotly(data=plotly_s3d_fig, width="100%")

3D 坐标轴

3D 图的坐标轴位于 scene 之中。像 scene.xaxis 这样,为每根轴设定 nticks(刻度数)和 range(范围)。官方文档用的是 numpy 随机数,这里用 random 实现同样的效果。

import random
import plotly.graph_objects as go

plotly_mesh_rng = random.Random(1)
plotly_mesh_fig = go.Figure(go.Mesh3d(
    x=[70 * plotly_mesh_rng.gauss(0, 1) for _ in range(70)],
    y=[55 * plotly_mesh_rng.gauss(0, 1) for _ in range(70)],
    z=[40 * plotly_mesh_rng.gauss(0, 1) for _ in range(70)],
    opacity=0.5,
    color="rgba(244,22,100,0.6)",
))
plotly_mesh_fig.update_layout(
    scene=dict(
        xaxis=dict(nticks=4, range=[-100, 100]),
        yaxis=dict(nticks=4, range=[-50, 100]),
        zaxis=dict(nticks=4, range=[-100, 100]),
    ),
    margin=dict(r=20, l=10, b=10, t=10),
)


rx.plotly(data=plotly_mesh_fig, width="100%")

用 State 切换图

把图放进 State 值,就能在运行时修改。官方文档把 go.Figure 存进 State 变量,这里只在 State 里放一个数字,由 @rx.var 计算值来生成图。拖动滑块,计算值会重新生成,图表随之改变。

import math
import plotly.graph_objects as go


class PlotlyWaveState(rx.State):
    cycles: int = 2

    @rx.event
    def set_cycles(self, value: list[float]):
        self.cycles = int(value[0])

    @rx.var
    def figure(self) -> go.Figure:
        xs = [i / 50 for i in range(101)]
        fig = go.Figure(go.Scatter(x=xs, y=[math.sin(2 * math.pi * self.cycles * x) for x in xs], mode="lines"))
        fig.update_layout(title=f"{self.cycles} cycles", height=300)
        return fig


rx.vstack(
    rx.slider(value=[PlotlyWaveState.cycles], min=1, max=8, step=1, on_change=PlotlyWaveState.set_cycles, width="240px"),
    rx.plotly(data=PlotlyWaveState.figure, width="100%"),
    width="100%",
)

获取被点击的点

on_click、on_hover、on_selected 会传来触发事件的点的列表。每个点里都有 x、y、curveNumber(第几个 trace)、pointNumber(第几个点)等值。

Click a bar
import plotly.graph_objects as go

plotly_click_fig = go.Figure(go.Bar(x=["Mon", "Tue", "Wed", "Thu", "Fri"], y=[12, 19, 7, 15, 22]))
plotly_click_fig.update_layout(height=280)


class PlotlyClickState(rx.State):
    picked: str = "Click a bar"

    @rx.event
    def pick(self, points: list[dict]):
        if points:
            point = points[0]
            self.picked = f"{point['x']}: {point['y']}"


rx.vstack(
    rx.plotly(data=plotly_click_fig, on_click=PlotlyClickState.pick, width="100%"),
    rx.badge(PlotlyClickState.picked, size="2"),
    width="100%",
)

修饰与布局

外观在创建图时用 update_layout() 设定。标题位置(title_x)、绘图区与外部背景色、字体等所有布局属性,都在 Plotly Layout 文档里。

与其给 rx.plotly 的宽高设固定值,不如让它跟随外层容器的尺寸,这样才能随屏幕大小伸缩。

import plotly.graph_objects as go

plotly_styled_fig = go.Figure(go.Scatter(
    x=[1952, 1957, 1962, 1967, 1972, 1977, 1982, 1987, 1992, 1997, 2002, 2007],
    y=[68.75, 69.96, 71.3, 72.13, 72.88, 74.21, 75.76, 76.86, 77.95, 78.61, 79.77, 80.65],
    mode="lines",
    name="Canada",
))
plotly_styled_fig.update_layout(
    title="Life expectancy in Canada",
    title_x=0.5,
    plot_bgcolor="#c3d7f7",
    paper_bgcolor="rgba(128, 128, 128, 0.1)",
    showlegend=True,
    title_font_family="Open Sans",
    title_font_size=25,
)


rx.plotly(data=plotly_styled_fig, width="100%")

Reflex 0.10 还提供只包含所需 trace 的轻量包。rx.plotly.basic、rx.plotly.cartesian、rx.plotly.finance、rx.plotly.geo、rx.plotly.gl2d、rx.plotly.gl3d、rx.plotly.mapbox、rx.plotly.strict 接受与 rx.plotly 相同的属性,同时减少浏览器的下载量(官方文档里还没有)。

完成订单

State 里只放选中的产品名,由计算值同时画出月度柱形和累计折线。累计折线用右侧的轴(yaxis2),再用 hovermode="x unified" 把同一个月的数值汇总到一个框里。

import plotly.graph_objects as go

plotly_months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
plotly_sales = {
    "Chairs": [32, 41, 38, 52, 61, 58, 70, 66, 59, 73, 88, 95],
    "Tables": [12, 15, 21, 19, 24, 30, 28, 33, 35, 31, 40, 46],
    "Lamps": [55, 50, 47, 44, 49, 53, 60, 58, 62, 67, 80, 102],
}


class PlotlyOrderState(rx.State):
    product: str = "Chairs"

    @rx.event
    def set_product(self, value: str):
        self.product = value

    @rx.var
    def figure(self) -> go.Figure:
        monthly = plotly_sales[self.product]
        running = [sum(monthly[: i + 1]) for i in range(len(monthly))]
        fig = go.Figure([
            go.Bar(x=plotly_months, y=monthly, name="Monthly"),
            go.Scatter(x=plotly_months, y=running, name="Running total", yaxis="y2", mode="lines+markers"),
        ])
        fig.update_layout(
            title=f"{self.product} sales",
            hovermode="x unified",
            yaxis2={"overlaying": "y", "side": "right"},
            legend={"orientation": "h", "y": -0.2},
            height=360,
        )
        return fig


rx.vstack(
    rx.select(["Chairs", "Tables", "Lamps"], value=PlotlyOrderState.product, on_change=PlotlyOrderState.set_product),
    rx.plotly(data=PlotlyOrderState.figure, width="100%"),
    width="100%",
)

工坊笔记

  • 用 rx.plotly(data=fig) 代替 fig.show()。用 go 画的图和用 px 画的图都一样。

  • 用 layout=dict 覆盖布局,用 locale 改变数字格式和工具栏语言。

  • State 里放简单的值,让 @rx.var 计算值返回 go.Figure,图表就会随之更新。

  • on_click、on_hover、on_selected 会传来点的列表(x、y、curveNumber、pointNumber …)。

  • 地图会从外部获取地图数据。主题会随浅色、深色模式自动切换。

← 上一课

图表部件 · Brush

下一课 →

其他图表库 · Pyplot

订阅新课时和新课程通知

本课程新增课时或推出后续课程时,我们会发邮件通知你。

收集项目:电子邮箱 · 用途:本课程的新课时和上线通知 · 保存期限:直到你要求删除。不会用于其他用途,也不会提供给他人。回复任意通知邮件,我们会立即删除。

问答

关于本课有任何疑问都可以在这里留言。所有语言版本页面的提问会汇集在一起。

以纯文本显示,不支持链接和格式。

R

ReflexKR

动手学 Python 和 Reflex。所有示例均已在 Reflex 0.10.0 上实际运行验证。

ReflexKR 免费,没有横幅广告。如果对你有帮助,欢迎请我们喝杯咖啡。 ☕ 请我们喝杯咖啡

联盟链接与赞助说明
한국어English日本語简体中文EspañolDeutsch

© 2026 ReflexKR · Since 2026 · CC BY-NC 4.0

Built with Reflex