python系列&deep_study系列:Gradio中文教程(十二)Customizing your demo with CSS and Javascript




Gradio中文教程(十二)Customizing your demo with CSS and Javascript

使用CSS和JavaScript自定义您的演示

Gradio允许您以多种方式自定义您的演示。您可以自定义演示的布局,添加自定义HTML,以及添加自定义主题。本教程将超越这些内容,指导您如何向演示中添加自定义CSSJavaScript代码,以便添加自定义样式、动画、自定义UI功能、分析等。

向您的演示添加自定义CSS

Gradio主题是自定义应用程序外观和感觉的最简单方法。您可以从多种主题中选择,或者创建自己的主题。为此,请将theme=关键字参数传递给Blocks构造函数。例如:

with gr.Blocks(theme=gr.themes.Glass()):
    ...

Gradio附带了一套预建主题,您可以从gr.themes.*加载。您可以扩展这些主题或从头开始创建自己的主题 - 有关更多详细信息,请参阅主题指南。

为了获得额外的样式能力,您可以使用css=关键字参数将任何CSS传递给您的应用程序。您可以传递CSS文件的路径,或者传递CSS代码的字符串。

警告:在自定义JSCSS中使用查询选择器不能保证在不同版本的Gradio中都能工作,因为GradioHTML 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可能会改变(然而,如上所述的警告,我们不能保证如果您使用自定义CSSGradio版本之间的完全兼容性,因为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样式

向您的演示添加自定义JavaScript

有三种方法可以将JavaScript代码添加到您的Gradio演示中:

您可以将JavaScript代码作为字符串或文件路径添加到BlocksInterface初始化器js参数中。这将使JavaScript代码在演示首次加载时运行。
下面是一个添加自定义JavaScript的示例,当演示首次加载时显示一个动画欢迎消息。

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()

注意:您也可以将自定义JavaScript代码作为文件路径提供。例如,如果您有一个名为custom.js的文件与您的Python脚本在同一目录中,您可以像这样将其添加到您的演示中:with gr.Blocks(js="custom.js") as demo:。对于Interface也是如此(例如:gr.Interface(..., js="custom.js"))

当使用Blocks和事件监听器时,事件有一个js参数,可以接受一个作为字符串的JavaScript函数,并将其视为Python事件监听器函数。您可以同时传递一个JavaScript函数和一个Python函数(在这种情况下,JavaScript函数首先运行),或者只传递JavaScript(并将Pythonfn设置为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()

最后,您可以将JavaScript代码添加到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参数接受您通常插入到页面<head>中的任何HTML标签。例如,您还可以在head中包含<meta>标签

请注意,注入自定义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()







老刘

Gradio中文教程(十二)Customizing your demo with CSS and Javascript

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

坦笑&&life

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值