组件工坊: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
工坊订单
请用环形图展示上个月访客的浏览器占比,并让每一块都显示名称和数值。
rx.recharts.pie_chart 把整体看作 100,把各部分所占的份额切成扇区来展示。扇区不超过五六个、"占整体多少"最重要时就用它。和其他图表不同,data 不是交给图表容器,而是交给 rx.recharts.pie。data_key 是扇区的大小,name_key 是扇区的名称。
在数据的某个 dict 里写上 "fill",只有那一块会用这个颜色;没写的则使用 pie 的 fill。
rx.recharts.pie_chart(
rx.recharts.pie(
data=[
{"name": "Group A", "value": 400},
{"name": "Group B", "value": 300, "fill": rx.color("teal", 9)},
{"name": "Group C", "value": 300, "fill": rx.color("orange", 9)},
{"name": "Group D", "value": 200, "fill": rx.color("plum", 9)},
],
data_key="value",
name_key="name",
fill=rx.color("accent", 9),
label=True,
),
width="100%",
height=300,
)把 inner_radius 设得大于 0,中间就会空出来,变成环形图。半径可以用数字(像素)或百分比字符串。
试着改属性
inner_radius
outer_radius
color
label
label_line
legend_type
rx.recharts.pie_chart(
rx.recharts.pie(
data=[
{"name": "Chrome", "value": 275},
{"name": "Safari", "value": 150},
{"name": "Firefox", "value": 100},
{"name": "Edge", "value": 130},
],
data_key="value",
name_key="name",
inner_radius="0%",
outer_radius="80%",
fill=rx.color("indigo", 8),
stroke=rx.color("gray", 1),
label=True,
label_line=True,
legend_type="rect",
),
rx.recharts.graphing_tooltip(),
rx.recharts.legend(),
width="100%",
height=300,
)| 属性 | 取值 | 默认值 | 用途 |
|---|---|---|---|
pie_chart(width=, height=, margin=) | 数字或百分比 / dict | "100%" | 图表尺寸和留白。data 不在这里 |
pie(data=) | dict 的列表 | 无 | 扇区数据 |
pie(data_key=, name_key=) | 字符串 | 无 / "name" | 扇区大小和名称的键 |
pie(cx=, cy=) | 数字或百分比 | "50%" | 圆心位置 |
pie(inner_radius=, outer_radius=) | 数字或百分比 | 0 / "80%" | 内半径和外半径。内半径大于 0 即为环形 |
pie(start_angle=, end_angle=) | 数字(度) | 0 / 360 | 绘制的角度范围。180 和 0 为半圆 |
pie(padding_angle=, min_angle=) | 数字(度) | 0 | 扇区之间的空隙、小扇区的最小角度 |
pie(fill=, stroke=) | 颜色 | accent 3 / accent 9 | 扇区颜色和边框颜色 |
pie(label=, label_line=) | True / False / dict | False | 数值显示和连接线 |
pie(legend_type=) | "rect" "circle" … "none" | "rect" | 图例图标 |
pie(is_animation_active=, animation_begin=, animation_duration=, animation_easing=) | True / 400 / 1500 / "ease" | 入场动画 | |
cell(fill=, stroke=) | 颜色 | 在 pie 中设定单个扇区的颜色 | |
| 事件 | on_click on_mouse_enter on_mouse_leave … | pie_chart、pie、cell 都能接收 |
放两个 pie,它们会以同一个圆心叠在一起。内层饼用 outer_radius="50%" 缩小,外环用 inner_radius="60%" 空出中间,就能在一张图里比较两组数据。padding_angle 让扇区之间按角度隔开。
rx.recharts.pie_chart(
rx.recharts.pie(
data=[
{"name": "Q1", "value": 400},
{"name": "Q2", "value": 300},
{"name": "Q3", "value": 300},
{"name": "Q4", "value": 200},
],
data_key="value",
name_key="name",
fill=rx.color("teal", 8),
inner_radius="60%",
padding_angle=5,
),
rx.recharts.pie(
data=[
{"name": "Q1", "value": 2400},
{"name": "Q2", "value": 4567},
{"name": "Q3", "value": 1398},
{"name": "Q4", "value": 9800},
],
data_key="value",
name_key="name",
fill=rx.color("accent", 8),
outer_radius="50%",
),
rx.recharts.graphing_tooltip(),
width="100%",
height=300,
)即使数据里没写颜色,也可以在 pie 里放入与扇区数量相同的 rx.recharts.cell 来定颜色。用 rx.foreach 遍历数据生成 cell,从颜色列表中取第 index 个颜色。cell 的顺序就是扇区的顺序。把 stroke 设为背景色并加粗边框,扇区之间就会出现缝隙。
piechart_data = [
{"name": "Chrome", "value": 275},
{"name": "Safari", "value": 150},
{"name": "Firefox", "value": 100},
{"name": "Edge", "value": 130},
{"name": "Other", "value": 60},
]
rx.recharts.pie_chart(
rx.recharts.pie(
rx.foreach(
piechart_data,
lambda item, index: rx.recharts.cell(
fill=rx.Var.create(["#6366F1", "#8B5CF6", "#A855F7", "#D946EF", "#EC4899"])[index % 5],
),
),
data=piechart_data,
data_key="value",
name_key="name",
inner_radius="40%",
outer_radius="80%",
padding_angle=2,
stroke="#fff",
custom_attrs={"strokeWidth": 2},
),
rx.recharts.graphing_tooltip(),
width="100%",
height=300,
)先在尺寸为 0 的 rx.el.svg 里定义 radial_gradient,再在每个 cell 的 fill 中用 url(#id) 引用。渐变定义即使在图表之外,只要在同一页面内就能找到。id 在页面中不要重复。
piechart_data = [
{"name": "Chrome", "value": 275},
{"name": "Safari", "value": 150},
{"name": "Firefox", "value": 100},
{"name": "Edge", "value": 130},
{"name": "Other", "value": 60},
]
rx.box(
rx.el.svg(
rx.el.svg.defs(
*[
rx.el.svg.radial_gradient(
rx.el.svg.stop(offset="10%", stop_color=color, stop_opacity=1),
rx.el.svg.stop(offset="95%", stop_color=color, stop_opacity=0.6),
id=f"piechart_grad_{i}",
cx="50%",
cy="50%",
r="50%",
)
for i, color in enumerate(["#6366F1", "#8B5CF6", "#EC4899", "#F59E0B"])
],
),
width=0,
height=0,
),
rx.recharts.pie_chart(
rx.recharts.pie(
*[rx.recharts.cell(fill=f"url(#piechart_grad_{i})") for i in range(4)],
data=piechart_data[:4],
data_key="value",
name_key="name",
inner_radius="60%",
outer_radius="80%",
padding_angle=5,
stroke="#fff",
custom_attrs={"strokeWidth": 2},
),
rx.recharts.graphing_tooltip(),
width="100%",
height=300,
),
width="100%",
)把 State 的值交给 pie 的 data,数字每次变化,扇区大小都会跟着变。这里用 start_angle=180、end_angle=0 做成半圆图,并把圆心下移(cy="80%")。
Wood 3
Stone 2
Gold 1
Food 4
from typing import Any
class PieChartStockState(rx.State):
stock: list[dict[str, Any]] = [
{"item": "Wood", "count": 3},
{"item": "Stone", "count": 2},
{"item": "Gold", "count": 1},
{"item": "Food", "count": 4},
]
@rx.event
def change(self, item: str, delta: int):
self.stock = [
{**row, "count": max(0, row["count"] + delta)} if row["item"] == item else row
for row in self.stock
]
rx.vstack(
rx.recharts.pie_chart(
rx.recharts.pie(
data=PieChartStockState.stock,
data_key="count",
name_key="item",
cx="50%",
cy="80%",
start_angle=180,
end_angle=0,
fill=rx.color("accent", 8),
label=True,
),
rx.recharts.graphing_tooltip(),
width="100%",
height=240,
),
rx.flex(
rx.foreach(
PieChartStockState.stock,
lambda row: rx.hstack(
rx.button("-", size="1", variant="soft", on_click=PieChartStockState.change(row["item"].to(str), -1)),
rx.text(row["item"], " ", row["count"], size="2"),
rx.button("+", size="1", variant="soft", on_click=PieChartStockState.change(row["item"].to(str), 1)),
align="center",
),
),
spacing="4",
wrap="wrap",
),
align="center",
width="100%",
)把扇区的 index 传给 cell 的 on_mouse_enter,在 on_mouse_leave 里清除。选中扇区的数值和名称用叠在环形中央的文字显示。给文字容器设置 pointer_events="none",让鼠标能碰到扇区。
Hover a slice
class PieChartHoverState(rx.State):
languages: list[dict[str, str | int]] = [
{"name": "Python", "value": 35},
{"name": "JavaScript", "value": 25},
{"name": "Java", "value": 20},
{"name": "C++", "value": 15},
{"name": "Ruby", "value": 5},
]
hovered_name: str = ""
hovered_value: int = 0
@rx.event
def enter(self, index: int):
self.hovered_name = str(self.languages[index]["name"])
self.hovered_value = int(self.languages[index]["value"])
@rx.event
def leave(self):
self.hovered_name, self.hovered_value = "", 0
rx.box(
rx.vstack(
rx.cond(
PieChartHoverState.hovered_name != "",
rx.fragment(
rx.heading(PieChartHoverState.hovered_value, "%", size="7"),
rx.text(PieChartHoverState.hovered_name, size="2"),
),
rx.text("Hover a slice", size="2", color_scheme="gray"),
),
align="center",
spacing="1",
position="absolute",
top="50%",
left="50%",
transform="translate(-50%, -50%)",
pointer_events="none",
),
rx.recharts.pie_chart(
rx.recharts.pie(
rx.foreach(
PieChartHoverState.languages,
lambda item, index: rx.recharts.cell(
fill=rx.Var.create(["#2B79D1", "#2469B3", "#1E5AA1", "#3D8EE1", "#61A9E4"])[index % 5],
on_mouse_enter=PieChartHoverState.enter(index),
on_mouse_leave=PieChartHoverState.leave,
),
),
data=PieChartHoverState.languages,
data_key="value",
name_key="name",
inner_radius=90,
stroke="0",
),
width="100%",
height=300,
),
position="relative",
width="100%",
)把五种浏览器画成环形图,用 cell 按固定顺序给每块上色。最后的 "Other" 用灰色淡化处理。数值看 label,名称看图例和提示框。
piechart_data = [
{"name": "Chrome", "value": 275},
{"name": "Safari", "value": 150},
{"name": "Firefox", "value": 100},
{"name": "Edge", "value": 130},
{"name": "Other", "value": 60},
]
rx.recharts.pie_chart(
rx.recharts.pie(
rx.foreach(
piechart_data,
lambda item, index: rx.recharts.cell(
fill=rx.Var.create([
rx.color("indigo", 9), rx.color("teal", 9), rx.color("orange", 9),
rx.color("plum", 9), rx.color("gray", 8),
])[index],
),
),
data=piechart_data,
data_key="value",
name_key="name",
inner_radius="55%",
outer_radius="80%",
padding_angle=2,
stroke=rx.color("gray", 1),
label=True,
),
rx.recharts.graphing_tooltip(),
rx.recharts.legend(),
width="100%",
height=320,
)工坊笔记
data 不交给 pie_chart,而是交给 pie。data_key 是大小,name_key 是名称。
inner_radius > 0 即为环形图,用 start_angle、end_angle 做半圆。
扇区颜色由数据中的 "fill" 键,或在 pie 里用 foreach 放入的 rx.recharts.cell 决定。
放两个 pie 会以同一圆心叠放,用 outer_radius、inner_radius 划分位置。
用 cell 的 on_mouse_enter(index) 可以把选中的扇区存进 State。
订阅新课时和新课程通知
本课程新增课时或推出后续课程时,我们会发邮件通知你。
问答
关于本课有任何疑问都可以在这里留言。所有语言版本页面的提问会汇集在一起。