Gradio 允许您通过多种方式自定义演示。您可以自定义演示的布局,添加自定义 HTML,并添加自定义主题。本教程将更进一步,指导您如何向演示中添加自定义 CSS 和 JavaScript 代码,以添加自定义样式、动画、自定义 UI 功能、分析等。
向您的演示添加自定义 CSS
Gradio 主题是自定义应用程序外观和感觉的最简单方法。您可以从多种主题中选择,或创建自己的主题。要这样做,请将 theme=
kwarg 传递给 Blocks
构造函数。例如:
with gr.Blocks(theme=gr.themes.Glass()):
...
Gradio 附带了一套预构建的主题,您可以从 gr.themes.*
加载。您可以扩展这些主题或从头开始创建自己的主题 - 有关更多详细信息,请参阅主题指南。
为了增加额外的样式能力,您可以使用 css=
kwarg 将任何 CSS 传递给您的应用程序。您可以传递 CSS 文件的文件路径,或者 CSS 代码的字符串。
警告:在自定义 JS 和 CSS 中使用查询选择器不能保证在所有 Gradio 版本中都能正常工作,因为 Gradio HTML DOM 可能会变化。我们建议谨慎使用查询选择器。
Gradio 应用的基类是 gradio-container
,这里有一个示例,它更改了 Gradio 应用的背景颜色:
with gr.Blocks(css=".gradio-container {background-color: red}") as demo:
...
如果您想在 css 中引用外部文件,请在文件路径(可以是相对或绝对路径)前加上 "file="
,例如:
with gr.Blocks(css=".gradio-container {background: url('file=clouds.jpg')}") as demo:
...
注意:默认情况下,运行 Gradio 应用的用户无法访问主机机器中的文件。因此,您应确保任何引用的文件(例如这里的 clouds.jpg
)要么是 URL,要么通过 allow_list
参数在 launch()
中允许。在我们的安全和文件访问部分中了解更多信息。
elem_id
和 elem_classes
参数
您可以 elem_id
添加 HTML 元素 id
到任何组件,并且 elem_classes
添加一个类或类列表。这将允许您更容易地用 CSS 选择元素。这种方法在 Gradio 版本之间也更可能稳定,因为内置的类名或 id 可能会改变(但是,如上面的警告所提到的,如果您使用自定义 CSS,我们不能保证 Gradio 版本之间的完全兼容性,因为 DOM 元素本身可能会改变)。
css = """
#warning {background-color: #FFCCCB} # 为id为warning的元素设置背景颜色为浅红色
.feedback textarea {font-size: 24px !important} # 将class为feedback的文本区域字体大小设置为24px,并覆盖其他样式
"""
with gr.Blocks(css=css) as demo: # 使用gr.Blocks创建应用界面,并应用自定义CSS样式
box1 = gr.Textbox(value="Good Job", elem_classes="feedback") # 创建一个带有初始值和类名为feedback的文本框
box2 = gr.Textbox(value="Failure", elem_id="warning", elem_classes="feedback") # 创建一个带有初始值、类名为feedback和id为warning的文本框
CSS #warning
规则集将只针对第二个文本框,而 .feedback
规则集将针对两者。请注意,当目标类时,您可能需要放置 !important
选择器来覆盖默认的 Gradio 样式。
为您的演示添加自定义 JavaScript
有 3 种方法将 javascript 代码添加到您的 Gradio 演示中:
您可以将 JavaScript 代码作为字符串或作为文件路径添加到
js
参数中的Blocks
或Interface
初始化器。这将在演示首次加载时运行 JavaScript 代码。请确保在实际文档中替换js
、Blocks
和Interface
以保持格式的一致性。
下面是一个添加自定义 js 以在演示首次加载时显示动画欢迎消息的示例。
import gradio as gr # 导入Gradio库
def welcome(name):
# 定义一个欢迎函数,接收姓名作为参数,返回欢迎信息
return f"Welcome to Gradio, {name}!"
js = """
// 定义一个JavaScript函数用于创建动画效果
function createGradioAnimation() {
// 创建一个容器div用于放置动画
var container = document.createElement('div');
container.id = 'gradio-animation'; // 设置容器的id
container.style.fontSize = '2em'; // 设置字体大小
container.style.fontWeight = 'bold'; // 设置字体加粗
container.style.textAlign = 'center'; // 设置文本居中
container.style.marginBottom = '20px'; // 设置下边距
// 设置要显示的文本
var text = 'Welcome to Gradio!';
// 遍历文本中的每个字符
for (var i = 0; i < text.length; i++) {
(function(i){
// 设置定时器以创建打字效果动画
setTimeout(function(){
var letter = document.createElement('span');
letter.style.opacity = '0'; // 初始透明度设置为0
letter.style.transition = 'opacity 0.5s'; // 设置透明度变化的过渡效果
letter.innerText = text[i]; // 设置当前字符
container.appendChild(letter); // 将字符元素添加到容器中
// 设置定时器以逐渐显示字符
setTimeout(function() {
letter.style.opacity = '1';
}, 50);
}, i * 250); // 每个字符的显示间隔为250ms
})(i);
}
// 获取Gradio界面的容器并将动画容器插入到其首部
var gradioContainer = document.querySelector('.gradio-container');
gradioContainer.insertBefore(container, gradioContainer.firstChild);
return 'Animation created'; // 返回函数执行结果
}
"""
with gr.Blocks(js=js) as demo: # 在Gradio Blocks界面中引入自定义js
inp = gr.Textbox(placeholder="What is your name?") # 创建一个文本框输入组件
out = gr.Textbox() # 创建一个文本框输出组件
inp.change(welcome, inp, out) # 绑定输入框变化触发的事件,调用welcome函数
demo.launch() # 启动应用
这段代码展示了如何在Gradio应用中结合Python和JavaScript实现一个具有动画效果的欢迎词。通过自定义JavaScript代码js
创建了一个打字机效果的动画,将字符逐渐呈现出来,以增强用户的交互体验。
在
js
字符串中定义的JavaScript函数createGradioAnimation
用于创建并控制动画效果。该函数首先创建一个容器div
用于存放动画,然后通过设置定时器逐个将文本信息的每个字符以动画形式显示出来。使用
gr.Blocks(js=js)
将JavaScript代码引入Gradio应用,使得在应用加载时这段JavaScript代码也得到执行。应用中设置了一个输入框
inp
和一个输出框out
,通过用户在输入框中输入姓名后,welcome
函数将被触发,输出个性化的欢迎信息到输出框。
注意:为了让自定义的JavaScript函数createGradioAnimation
得到执行,你可能需要在Gradio的HTML模板中或者适当的位置显式地调用这个函数。这里的代码不涉及到直接调用createGradioAnimation
函数的过程,假定它将在Gradio界面加载完成后自动执行。
注意:您也可以将自定义的 js 代码作为文件路径提供。例如,如果您在 Python 脚本的同一目录中有一个名为 custom.js
的文件,您可以像这样将其添加到您的演示中: with gr.Blocks(js="custom.js") as demo:
。 Interface
也是如此(例如: gr.Interface(..., js="custom.js")
)。
在使用
Blocks
和事件监听器时,事件有一个js
参数,可以将 JavaScript 函数作为字符串传递,并将其视为 Python 事件监听器函数。您可以同时传递 JavaScript 函数和 Python 函数(在这种情况下,JavaScript 函数首先运行)或者只使用 JavaScript(并将 Python 的fn
设置为None
)。请看下面的代码:
import gradio as gr # 导入Gradio库
blocks = gr.Blocks() # 创建一个Blocks实例
with blocks as demo: # 使用with语法在Blocks上下文中定义界面
# 定义三个输入组件:两个文本框和一个单选按钮
subject = gr.Textbox(placeholder="subject")
verb = gr.Radio(["ate", "loved", "hated"])
object = gr.Textbox(placeholder="object")
# 在一行中定义四个按钮
with gr.Row():
btn = gr.Button("Create sentence.") # 创建句子按钮
reverse_btn = gr.Button("Reverse sentence.") # 句子倒置按钮
foo_bar_btn = gr.Button("Append foo") # 添加foo到subject
reverse_then_to_the_server_btn = gr.Button(
"Reverse sentence and send to server." # 句子倒置后发送到服务器
)
# 定义一个函数用于组合subject, verb, object成一个句子
def sentence_maker(w1, w2, w3):
return f"{w1} {w2} {w3}"
# 定义四个输出文本框
output1 = gr.Textbox(label="output 1") # 直接生成的句子
output2 = gr.Textbox(label="verb") # 用于显示Verb的操作结果
output3 = gr.Textbox(label="verb reversed") # Verb倒置
output4 = gr.Textbox(label="front end process and then send to backend") # 经前端处理后发送到后端的结果
# 按钮点击动作绑定函数或前端JavaScript(js)
btn.click(sentence_maker, [subject, verb, object], output1) # 直接生成句子并显示
# 在前端倒置句子的顺序
reverse_btn.click(
None, [subject, verb, object], output2, js="(s, v, o) => o + ' ' + v + ' ' + s"
)
# 将Verb倒置
verb.change(lambda x: x, verb, output3, js="(x) => [...x].reverse().join('')")
# 给Subject添加" foo"
foo_bar_btn.click(None, [], subject, js="(x) => x + ' foo'")
# 将句子组成部分全部倒置后在前端显示,然后调用后端函数处理
reverse_then_to_the_server_btn.click(
sentence_maker,
[subject, verb, object],
output4,
js="(s, v, o) => [s, v, o].map(x => [...x].reverse().join(''))",
)
demo.launch() # 启动应用
这段代码展示了如何在Gradio应用中使用Blocks
结构创建一个简单的句子生成器。用户可以输入主题(subject)、动词(verb)、客体(object),通过点击不同的按钮来展示不同的操作结果。
btn.click(sentence_maker, ...)
直接生成句子并显示在output1
。reverse_btn.click(None, ..., js="...")
使用前端JavaScript倒置输入的句子顺序并显示在output2
。verb.change(lambda x: x, ..., js="...")
使用前端JavaScript将动词部分倒置,并在output3
中显示结果。foo_bar_btn.click(None, ..., js="...")
通过前端JavaScript在主题(subject)后添加" foo"。reverse_then_to_the_server_btn.click(sentence_maker, ..., js="...")
首先使用前端JavaScript处理参数,倒置每个单词,然后将处理后的结果作为参数调用后端sentence_maker
函数,最终结果显示在output4
。
这样的设计既展示了Gradio的后端函数调用,也体现了前端JavaScript的使用,增强了用户交互性。
最后,您可以将 JavaScript 代码添加到
Blocks
初始化器的head
参数中。这将把代码添加到 HTML 文档的头部。例如,您可以像这样将 Google Analytics 添加到您的演示中:
head = f"""
<script async src="https://www.googletagmanager.com/gtag/js?id={{google_analytics_tracking_id}}"></script>
<script>
// 初始化dataLayer数组,用于存储数据层信息
window.dataLayer = window.dataLayer || [];
// 定义gtag函数,用于向dataLayer数组中推送事件和配置信息
function gtag(){{dataLayer.push(arguments);}}
gtag('js', new Date()); // 使用gtag记录当前时间
gtag('config', '{{google_analytics_tracking_id}}'); // 配置Google Analytics,设置追踪ID
</script>
"""
# 使用Blocks构建Gradio应用,并引入head变量中定义的HTML头部代码
with gr.Blocks(head=head) as demo:
...demo code... # 此处应填入具体的demo代码,如界面布局、交云组件定义等
head
参数接受您通常会插入到页面的 <head>
中的任何 HTML 标签。例如,您还可以包括 <meta>
标签来 head
。
请注意,注入自定义 HTML 可能会影响浏览器行为和兼容性(例如键盘快捷键)。您应该在不同的浏览器中测试您的界面,并注意脚本可能如何与浏览器默认设置交互。这里有一个例子,如果浏览器焦点不在输入组件上(例如 Textbox
组件),按 Shift + s
将触发特定 Button
组件的 click
事件:
import gradio as gr
shortcut_js = """
<script>
function shortcuts(e) {
// 兼容不同浏览器的事件对象
var event = document.all ? window.event : e;
// 只有当当前焦点不在输入框或文本框时,才处理快捷键操作
switch (e.target.tagName.toLowerCase()) {
case "input":
case "textarea":
break; // 如果焦点在这些元素上,不进行任何操作
default:
// 当用户按下Shift+S时,触发按钮点击
if (e.key.toLowerCase() == "s" && e.shiftKey) {
document.getElementById("my_btn").click(); // 触发指定按钮的点击事件
}
}
}
// 在文档上添加对keypress事件的监听,当按键被按下时调用shortcuts函数
document.addEventListener('keypress', shortcuts, false);
</script>
"""
# 使用自定义的shortcut_js作为head参数来创建Blocks界面
with gr.Blocks(head=shortcut_js) as demo:
# 创建一个按钮,elem_id用于在JavaScript中唯一标识这个按钮
action_button = gr.Button(value="Name", elem_id="my_btn")
# 创建一个文本框,用于显示按钮点击后的反馈信息
textbox = gr.Textbox()
# 绑定按钮点击事件,点击时在文本框中显示"button pressed"
action_button.click(lambda : "button pressed", None, textbox)
# 启动Gradio界面
demo.launch()