如果您希望在应用程序中创建自定义 HTML,请使用 `gr.HTML` 组件。这是一个基本的“纯 HTML”示例:
gr.HTML(value="<h1>Hello World!</h1>")您还可以使用 HTML 模板来组织您的 HTML。请看下面的示例:
gr.HTML(value="John", html_template"<h1>Hello, {{value}}!</h1><p>${value.length} letters</p>")当注入到模板中时,“John”变为 `value`,结果如下:
<h1>Hello, John!</h1><p>4 letters</p>请注意,我们支持两种模板语法:`$ {}` 用于自定义 JavaScript 表达式,`{{}}` 用于 Handlebars 模板。您可以在模板中使用其中一种或两种——`$ {}` 允许完全自定义的 JS 逻辑,而 Handlebars 为循环和条件提供了结构化模板。
让我们看另一个显示项目列表的示例:
gr.HTML(value=["apple", "banana", "cherry"], html_templates="""
<h1>${value.length} fruits:</h1>
<ul>
{{#each value}}
<li>{{this}}</li>
{{/each}}
</ul>
""")默认情况下,gr.HTML 的内容会应用一些 CSS 样式以匹配 Gradio 主题。您可以使用 `apply_default_css=False` 禁用此功能。您还可以通过 `css_template` 参数提供自己的 CSS 样式,如下一个示例所示。
让我们使用 `gr.HTML` 构建一个简单的星级评分组件,然后扩展它的更多功能。
import gradio as gr
with gr.Blocks() as demo:
three_star_rating = gr.HTML("""
<h2>Star Rating:</h2>
<img src='https://upload.wikimedia.org/wikipedia/commons/d/df/Award-star-gold-3d.svg'>
<img src='https://upload.wikimedia.org/wikipedia/commons/d/df/Award-star-gold-3d.svg'>
<img src='https://upload.wikimedia.org/wikipedia/commons/d/df/Award-star-gold-3d.svg'>
<img class='faded' src='https://upload.wikimedia.org/wikipedia/commons/d/df/Award-star-gold-3d.svg'>
<img class='faded' src='https://upload.wikimedia.org/wikipedia/commons/d/df/Award-star-gold-3d.svg'>
""", css_template="""
img { height: 50px; display: inline-block; }
.faded { filter: grayscale(100%); opacity: 0.3; }
""")
demo.launch()请注意我们如何使用 `css_template` 参数来添加自定义 CSS,为 `gr.HTML` 组件内的 HTML 设置样式。
让我们看看当我们更新值时模板是如何自动更新的。
import gradio as gr
with gr.Blocks() as demo:
star_rating = gr.HTML(
value=3,
html_template="""
<h2>Star Rating:</h2>
${Array.from({length: 5}, (_, i) => `<img class='${i < value ? '' : 'faded'}' src='https://upload.wikimedia.org/wikipedia/commons/d/df/Award-star-gold-3d.svg'>`).join('')}""",
css_template="""
img { height: 50px; display: inline-block; }
.faded { filter: grayscale(100%); opacity: 0.3; }
""")
rating_slider = gr.Slider(0, 5, 3, step=1, label="Select Rating")
rating_slider.change(fn=lambda x: x, inputs=rating_slider, outputs=star_rating)
demo.launch()我们可能希望向 `html_template` 传递除 `value` 以外的其他 props。只需将这些 props 添加到您的模板中,并将它们作为 kwargs 传递给 `gr.HTML` 组件即可。例如,让我们向星级评分组件添加 `size` 和 `max_stars` props。
import gradio as gr
with gr.Blocks() as demo:
star_rating = gr.HTML(
7,
size=40,
max_stars=10,
html_template="""
<h2>Star Rating:</h2>
${Array.from({length: max_stars}, (_, i) => `<img class='${i < value ? '' : 'faded'}' src='https://upload.wikimedia.org/wikipedia/commons/d/df/Award-star-gold-3d.svg'>`).join('')}""",
css_template="""
img { height: ${size}px; display: inline-block; }
.faded { filter: grayscale(100%); opacity: 0.3; }
"""
)
rating_slider = gr.Slider(0, 10, step=1, label="Select Rating")
rating_slider.change(fn=lambda x: x, inputs=rating_slider, outputs=star_rating)
size_slider = gr.Slider(20, 100, 40, step=1, label="Select Size")
size_slider.change(fn=lambda x: gr.HTML(size=x), inputs=size_slider, outputs=star_rating)
demo.launch()请注意 `html_template` 和 `css_template` 如何格式化这些额外的 props。另请注意,这些 props 中的任何一个都可以通过 Gradio 事件监听器进行更新。
`gr.HTML` 组件还可以通过触发事件来创建自定义输入组件。您将提供 `js_on_load`,即组件加载时运行的 javascript 代码。代码可以访问 `trigger` 函数来触发 Gradio 可以监听的事件,以及对象 `props`,该对象可以访问组件的所有 props,包括 `value`。
import gradio as gr
with gr.Blocks() as demo:
star_rating = gr.HTML(
value=3,
html_template="""
<h2>Star Rating:</h2>
${Array.from({length: 5}, (_, i) => `<img class='${i < value ? '' : 'faded'}' src='https://upload.wikimedia.org/wikipedia/commons/d/df/Award-star-gold-3d.svg'>`).join('')}
<button id='submit-btn'>Submit Rating</button>
""",
css_template="""
img { height: 50px; display: inline-block; cursor: pointer; }
.faded { filter: grayscale(100%); opacity: 0.3; }
""",
js_on_load="""
const imgs = element.querySelectorAll('img');
imgs.forEach((img, index) => {
img.addEventListener('click', () => {
props.value = index + 1;
});
});
const submitBtn = element.querySelector('#submit-btn');
submitBtn.addEventListener('click', () => {
trigger('submit');
});
""")
rating_output = gr.Textbox(label="Submitted Rating")
star_rating.submit(lambda x: x, inputs=star_rating, outputs=rating_output)
demo.launch()请查看上面的 `js_on_load` 代码。我们为每个星形图像添加了点击事件监听器,以便在点击星星时通过 `props.value` 更新值。这也会重新渲染模板以显示更新后的值。我们还为提交按钮添加了一个点击事件监听器,用于触发 `submit` 事件。在我们的应用程序中,我们监听此触发器以运行一个输出星级评分 `value` 的函数。
您可以通过 `props.<prop_name>` 更新组件的任何其他 props,并通过 `trigger('<event_name>')` 触发事件。触发事件也可以发送事件数据,例如:
trigger('event_name', { key: value, count: 123 });这些事件数据将可通过 `gr.EventData` 访问 Python 事件监听函数。
def handle_event(evt: gr.EventData):
print(evt.key)
print(evt.count)
star_rating.event(fn=handle_event, inputs=[], outputs=[])请记住,附加在 `js_on_load` 中的事件监听器仅在组件首次渲染时附加一次。如果您的组件动态创建需要事件监听器的新元素,请将事件监听器附加到组件加载时存在的父元素上,并检查目标。例如:
element.addEventListener('click', (e) =>
if (e.target && e.target.matches('.child-element')) {
props.value = e.target.dataset.value;
}
);如果您在多个地方重用同一个 HTML 组件,您可以通过继承 `gr.HTML` 并设置模板和其他参数的默认值来创建自定义组件类。这是一个创建可重用 StarRating 组件的示例。
import gradio as gr
class StarRating(gr.HTML):
def __init__(self, label, value=0, **kwargs):
html_template = """
<h2>${label} rating:</h2>
${Array.from({length: 5}, (_, i) => `<img class='${i < value ? '' : 'faded'}' src='https://upload.wikimedia.org/wikipedia/commons/d/df/Award-star-gold-3d.svg'>`).join('')}
"""
css_template = """
img { height: 50px; display: inline-block; cursor: pointer; }
.faded { filter: grayscale(100%); opacity: 0.3; }
"""
js_on_load = """
const imgs = element.querySelectorAll('img');
imgs.forEach((img, index) => {
img.addEventListener('click', () => {
props.value = index + 1;
});
});
"""
super().__init__(value=value, label=label, html_template=html_template, css_template=css_template, js_on_load=js_on_load, **kwargs)
def api_info(self):
return {"type": "integer", "minimum": 0, "maximum": 5}
with gr.Blocks() as demo:
gr.Markdown("# Restaurant Review")
food_rating = StarRating(label="Food", value=3)
service_rating = StarRating(label="Service", value=3)
ambience_rating = StarRating(label="Ambience", value=3)
average_btn = gr.Button("Calculate Average Rating")
rating_output = StarRating(label="Average", value=3)
def calculate_average(food, service, ambience):
return round((food + service + ambience) / 3)
average_btn.click(
fn=calculate_average,
inputs=[food_rating, service_rating, ambience_rating],
outputs=rating_output
)
demo.launch()
注意:Gradio 要求所有组件都接受某些参数,例如 `render`。您不需要处理这些参数,但您需要在组件构造函数中接受它们并将它们传递给父 `gr.HTML` 类。否则,您的组件可能无法正常运行。最简单的方法是向您的 `__init__` 方法添加 `**kwargs` 并将其传递给 `super().__init__()`,就像上面的代码示例一样。
我们已经创建了几个自定义 HTML 组件作为可重用组件示例,您可以在 此目录 中参考。
为了使您的自定义 HTML 组件与 Gradio 内置的 API 和 MCP(模型上下文协议)支持配合使用,您需要定义如何序列化其数据。有两种方法可以实现此目的:
选项 1:定义 `api_info()` 方法
添加一个 `api_info()` 方法,该方法返回一个描述组件数据格式的 JSON 模式字典。这就是我们在上面的 StarRating 类中所做的。
选项 2:定义 Pydantic 数据模型
对于更复杂的数据结构,您可以定义一个继承自 `GradioModel` 或 `GradioRootModel` 的 Pydantic 模型
from gradio.data_classes import GradioModel, GradioRootModel
class MyComponentData(GradioModel):
items: List[str]
count: int
class MyComponent(gr.HTML):
data_model = MyComponentData当您的数据是一个带有命名字段的字典时,请使用 `GradioModel`;当您的数据是一个不需要包装在字典中的简单类型(字符串、列表等)时,请使用 `GradioRootModel`。通过定义 `data_model`,您的组件会自动实现 API 方法。
请记住,使用 `gr.HTML` 创建自定义组件涉及将原始 HTML 和 JavaScript 注入到 Gradio 应用程序中。在 `html_template` 和 `js_on_load` 中使用不受信任的用户输入时要小心,因为这可能导致跨站点脚本 (XSS) 漏洞。
您还应该预料到,任何将 `gr.HTML` 组件作为输入的 Python 事件监听器都可能被传入任意值,而不仅仅是您期望前端能够为 `value` 设置的值。在公共应用程序中,请适当清理和验证用户输入。
请查看 此目录 中可以构建的自定义组件示例。