Gradio 允许你以多种方式自定义你的演示。你可以自定义演示的布局,添加自定义的 HTML,以及添加自定义主题。本教程将更进一步,带你了解如何向你的演示中添加自定义的 CSS 和 JavaScript 代码,以便添加自定义样式、动画、自定义 UI 功能、分析等。
Gradio 主题是自定义应用程序外观和感觉的最简单方法。您可以从多种主题中选择,或者创建自己的主题。为此,请将 theme=
关键字参数传递给 Blocks
构造函数。例如:
with gr.Blocks(theme=gr.themes.Glass()):
...
Gradio 附带了一组预构建的主题,您可以从 gr.themes.*
加载。您可以扩展这些主题或从头开始创建自己的主题 - 有关更多详细信息,请参阅 Theming guide。
为了获得额外的样式能力,您可以使用css=
关键字参数向您的应用程序传递任何CSS。您可以传递CSS文件的路径,或者一段CSS代码字符串。
警告:在自定义JS和CSS中使用查询选择器不保证在绑定到Gradio自己的HTML元素的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,要么通过launch()
中的allow_list
参数允许访问。更多信息请参阅我们的安全和文件访问部分。
elem_id
和 elem_classes
参数你可以使用elem_id
为任何组件添加一个HTML元素的id
,并使用elem_classes
添加一个类或类列表。这将使你能够更轻松地使用CSS选择元素。这种方法在Gradio版本之间也更可能保持稳定,因为内置的类名或id可能会发生变化(然而,如上文警告中提到的,如果你使用自定义CSS,我们不能保证Gradio版本之间的完全兼容性,因为DOM元素本身可能会发生变化)。
css = """
#warning {background-color: #FFCCCB}
.feedback textarea {font-size: 24px !important}
"""
with gr.Blocks(css=css) as demo:
box1 = gr.Textbox(value="Good Job", elem_classes="feedback")
box2 = gr.Textbox(value="Failure", elem_id="warning", elem_classes="feedback")
CSS #warning
规则集将仅针对第二个文本框,而 .feedback
规则集将同时针对两者。请注意,在针对类时,您可能需要使用 !important
选择器来覆盖默认的 Gradio 样式。
有3种方法可以将javascript代码添加到你的Gradio演示中:
Blocks
或Interface
初始化器的js
参数中。这将在首次加载演示时运行JavaScript代码。下面是一个示例,演示了在演示首次加载时添加自定义js以显示动画欢迎消息。
import gradio as gr
def welcome(name):
return f"Welcome to Gradio, {name}!"
js = """
function createGradioAnimation() {
var container = document.createElement('div');
container.id = 'gradio-animation';
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';
letter.style.transition = 'opacity 0.5s';
letter.innerText = text[i];
container.appendChild(letter);
setTimeout(function() {
letter.style.opacity = '1';
}, 50);
}, i * 250);
})(i);
}
var gradioContainer = document.querySelector('.gradio-container');
gradioContainer.insertBefore(container, gradioContainer.firstChild);
return 'Animation created';
}
"""
with gr.Blocks(js=js) as demo:
inp = gr.Textbox(placeholder="What is your name?")
out = gr.Textbox()
inp.change(welcome, inp, out)
demo.launch()
注意:您还可以将自定义的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
blocks = gr.Blocks()
with blocks as demo:
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")
reverse_then_to_the_server_btn = gr.Button(
"Reverse sentence and send to server."
)
def sentence_maker(w1, w2, w3):
return f"{w1} {w2} {w3}"
output1 = gr.Textbox(label="output 1")
output2 = gr.Textbox(label="verb")
output3 = gr.Textbox(label="verb reversed")
output4 = gr.Textbox(label="front end process and then send to backend")
btn.click(sentence_maker, [subject, verb, object], output1)
reverse_btn.click(
None, [subject, verb, object], output2, js="(s, v, o) => o + ' ' + v + ' ' + s"
)
verb.change(lambda x: x, verb, output3, js="(x) => [...x].reverse().join('')")
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()
Blocks
初始化器的head
参数中。这会将代码添加到HTML文档的头部。例如,你可以像这样将Google Analytics添加到你的演示中:head = f"""
<script async src="https://www.googletagmanager.com/gtag/js?id={google_analytics_tracking_id}"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){{dataLayer.push(arguments);}}
gtag('js', new Date());
gtag('config', '{google_analytics_tracking_id}');
</script>
"""
with gr.Blocks(head=head) as demo:
...demo code...
head
参数接受您通常会插入到页面的
中的任何 HTML 标签。例如,您还可以将 标签包含到
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:
if (e.key.toLowerCase() == "s" && e.shiftKey) {
document.getElementById("my_btn").click();
}
}
}
document.addEventListener('keypress', shortcuts, false);
</script>
"""
with gr.Blocks(head=shortcut_js) as demo:
action_button = gr.Button(value="Name", elem_id="my_btn")
textbox = gr.Textbox()
action_button.click(lambda : "button pressed", None, textbox)
demo.launch()