240828-Gradio结合Html+Css+Javascript制作年历

A. 最终效果

需求描述

html javascript css 按年生成2016年至2116年的日历,要求如下:

  1. 二行六例,每个单元是一个月,且每个单元包含周次信息
  2. 通过背景为红色的圆圈高亮显示当前的日期
  3. 第一页显示今年,鼠标左边或键盘左键更新上一年,鼠标右键或键盘右键更新到下一年
  4. 将html javascript css写到同一个html文件中
  5. 根据浏览器的宽度,自适应的调整每个月度单元的宽度及字体的大小
  6. 整个年历在浏览器中水平居中,年份位于日历的正上方

在这里插入图片描述


B. HTML代码

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Yearly Calendar</title>
    <style>
      body {
        display: flex;
        flex-direction: column;
        align-items: center;
        font-family: Arial, sans-serif;
        margin: 0;
        padding: 0;
      }
      #year {
        margin: 20px 0;
        font-size: 2rem;
        text-align: center;
      }
      .calendar {
        display: grid;
        grid-template-columns: repeat(6, 1fr);
        gap: 10px;
        width: 90%;
        max-width: 1200px;
      }
      .month {
        border: 1px solid #ddd;
        padding: 10px;
        box-sizing: border-box;
      }
      .month h3 {
        margin: 0;
        font-size: 1.2rem;
        text-align: center;
      }
      .weekdays,
      .days {
        display: grid;
        grid-template-columns: repeat(7, 1fr);
        text-align: center;
        font-size: 0.9rem;
      }
      .weekdays div {
        font-weight: bold;
        padding: 5px 0;
      }
      .days div {
        padding: 5px;
        cursor: pointer;
      }
      .days .today {
        background-color: red;
        border-radius: 50%;
        color: white;
      }
      @media (max-width: 800px) {
        .calendar {
          grid-template-columns: repeat(3, 1fr);
        }
        .month h3 {
          font-size: 1rem;
        }
        .weekdays,
        .days {
          font-size: 0.8rem;
        }
      }
      @media (max-width: 500px) {
        .calendar {
          grid-template-columns: repeat(2, 1fr);
        }
        .month h3 {
          font-size: 0.9rem;
        }
        .weekdays,
        .days {
          font-size: 0.7rem;
        }
      }
    </style>
  </head>
  <body>
    <div id="year"></div>
    <div class="calendar" id="calendar"></div>
    <script>
      const monthNames = [
        "January",
        "February",
        "March",
        "April",
        "May",
        "June",
        "July",
        "August",
        "September",
        "October",
        "November",
        "December",
      ];
      const weekdays = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
      let currentYear = new Date().getFullYear();

      document.addEventListener("DOMContentLoaded", () => {
        renderCalendar(currentYear);
        document.getElementById("year").innerText = currentYear;
      });

      document.addEventListener("keydown", (event) => {
        if (event.key === "ArrowLeft") {
          updateYear(-1);
        } else if (event.key === "ArrowRight") {
          updateYear(1);
        }
      });

      document.addEventListener("click", (event) => {
        if (event.button === 0) {
          // Left click
          updateYear(-1);
        }
      });

      document.addEventListener("contextmenu", (event) => {
        event.preventDefault(); // Prevent default context menu
        updateYear(1); // Right click
      });

      function updateYear(offset) {
        currentYear += offset;
        if (currentYear < 2016) currentYear = 2016;
        if (currentYear > 2116) currentYear = 2116;
        document.getElementById("year").innerText = currentYear;
        renderCalendar(currentYear);
      }

      function renderCalendar(year) {
        const calendar = document.getElementById("calendar");
        calendar.innerHTML = "";
        for (let i = 0; i < 12; i++) {
          const monthDiv = document.createElement("div");
          monthDiv.className = "month";
          const monthTitle = document.createElement("h3");
          monthTitle.innerText = monthNames[i];
          monthDiv.appendChild(monthTitle);

          const weekdaysDiv = document.createElement("div");
          weekdaysDiv.className = "weekdays";
          weekdays.forEach((day) => {
            const dayDiv = document.createElement("div");
            dayDiv.innerText = day;
            weekdaysDiv.appendChild(dayDiv);
          });
          monthDiv.appendChild(weekdaysDiv);

          const daysDiv = document.createElement("div");
          daysDiv.className = "days";
          const firstDay = new Date(year, i, 1).getDay();
          const daysInMonth = new Date(year, i + 1, 0).getDate();

          // Add empty divs for days before the first day of the month
          for (let j = 0; j < firstDay; j++) {
            daysDiv.appendChild(document.createElement("div"));
          }

          // Add days of the month
          for (let j = 1; j <= daysInMonth; j++) {
            const dayDiv = document.createElement("div");
            dayDiv.innerText = j;
            const today = new Date();
            if (
              year === today.getFullYear() &&
              i === today.getMonth() &&
              j === today.getDate()
            ) {
              dayDiv.className = "today";
            }
            daysDiv.appendChild(dayDiv);
          }

          monthDiv.appendChild(daysDiv);
          calendar.appendChild(monthDiv);
        }
      }
    </script>
  </body>
</html>

C. Gradio代码

C.1 没调整垂直组件之间的间距

import gradio as gr

html_iframe = """
<iframe srcdoc='
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Yearly Calendar</title>
    <style>
      body {
        display: flex;
        flex-direction: column;
        align-items: center;
        font-family: Arial, sans-serif;
        margin: 0;
        padding: 0;
      }
      #year {
        margin: 20px 0;
        font-size: 2rem;
        text-align: center;
      }
      .calendar {
        display: grid;
        grid-template-columns: repeat(6, 1fr);
        gap: 10px;
        width: 90%;
        max-width: 1200px;
      }
      .month {
        border: 1px solid #ddd;
        padding: 10px;
        box-sizing: border-box;
      }
      .month h3 {
        margin: 0;
        font-size: 1.2rem;
        text-align: center;
      }
      .weekdays,
      .days {
        display: grid;
        grid-template-columns: repeat(7, 1fr);
        text-align: center;
        font-size: 0.9rem;
      }
      .weekdays div {
        font-weight: bold;
        padding: 5px 0;
      }
      .days div {
        padding: 5px;
        cursor: pointer;
      }
      .days .today {
        background-color: red;
        border-radius: 50%;
        color: white;
      }
      @media (max-width: 800px) {
        .calendar {
          grid-template-columns: repeat(3, 1fr);
        }
        .month h3 {
          font-size: 1rem;
        }
        .weekdays,
        .days {
          font-size: 0.8rem;
        }
      }
      @media (max-width: 500px) {
        .calendar {
          grid-template-columns: repeat(2, 1fr);
        }
        .month h3 {
          font-size: 0.9rem;
        }
        .weekdays,
        .days {
          font-size: 0.7rem;
        }
      }
    </style>
  </head>
  <body>
    <div id="year"></div>
    <div class="calendar" id="calendar"></div>
    <script>
      const monthNames = [
        "January",
        "February",
        "March",
        "April",
        "May",
        "June",
        "July",
        "August",
        "September",
        "October",
        "November",
        "December",
      ];
      const weekdays = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
      let currentYear = new Date().getFullYear();

      document.addEventListener("DOMContentLoaded", () => {
        renderCalendar(currentYear);
        document.getElementById("year").innerText = currentYear;
      });

      document.addEventListener("keydown", (event) => {
        if (event.key === "ArrowLeft") {
          updateYear(-1);
        } else if (event.key === "ArrowRight") {
          updateYear(1);
        }
      });

      document.addEventListener("click", (event) => {
        if (event.button === 0) {
          // Left click
          updateYear(-1);
        }
      });

      document.addEventListener("contextmenu", (event) => {
        event.preventDefault(); // Prevent default context menu
        updateYear(1); // Right click
      });

      function updateYear(offset) {
        currentYear += offset;
        if (currentYear < 2016) currentYear = 2016;
        if (currentYear > 2116) currentYear = 2116;
        document.getElementById("year").innerText = currentYear;
        renderCalendar(currentYear);
      }

      function renderCalendar(year) {
        const calendar = document.getElementById("calendar");
        calendar.innerHTML = "";
        for (let i = 0; i < 12; i++) {
          const monthDiv = document.createElement("div");
          monthDiv.className = "month";
          const monthTitle = document.createElement("h3");
          monthTitle.innerText = monthNames[i];
          monthDiv.appendChild(monthTitle);

          const weekdaysDiv = document.createElement("div");
          weekdaysDiv.className = "weekdays";
          weekdays.forEach((day) => {
            const dayDiv = document.createElement("div");
            dayDiv.innerText = day;
            weekdaysDiv.appendChild(dayDiv);
          });
          monthDiv.appendChild(weekdaysDiv);

          const daysDiv = document.createElement("div");
          daysDiv.className = "days";
          const firstDay = new Date(year, i, 1).getDay();
          const daysInMonth = new Date(year, i + 1, 0).getDate();

          // Add empty divs for days before the first day of the month
          for (let j = 0; j < firstDay; j++) {
            daysDiv.appendChild(document.createElement("div"));
          }

          // Add days of the month
          for (let j = 1; j <= daysInMonth; j++) {
            const dayDiv = document.createElement("div");
            dayDiv.innerText = j;
            const today = new Date();
            if (
              year === today.getFullYear() &&
              i === today.getMonth() &&
              j === today.getDate()
            ) {
              dayDiv.className = "today";
            }
            daysDiv.appendChild(dayDiv);
          }

          monthDiv.appendChild(daysDiv);
          calendar.appendChild(monthDiv);
        }
      }
    </script>
  </body>
</html>' width="100%" height="800px" style="border:none;"></iframe>
"""

with gr.Blocks() as demo:
    gr.HTML(html_iframe)

demo.launch(inbrowser=True)

C.2 调整垂直组件之间的间距

import gradio as gr

html_iframe = """
<iframe srcdoc='
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Yearly Calendar</title>
    <style>
      body {
        display: flex;
        flex-direction: column;
        align-items: center;
        font-family: Arial, sans-serif;
        margin: 0;
        padding: 0;
      }
      #year {
        margin: 20px 0;
        font-size: 2rem;
        text-align: center;
      }
      .calendar {
        display: grid;
        grid-template-columns: repeat(6, 1fr);
        gap: 10px;
        width: 90%;
        max-width: 1200px;
      }
      .month {
        border: 1px solid #ddd;
        padding: 10px;
        box-sizing: border-box;
      }
      .month h3 {
        margin: 0;
        font-size: 1.2rem;
        text-align: center;
      }
      .weekdays,
      .days {
        display: grid;
        grid-template-columns: repeat(7, 1fr);
        text-align: center;
        font-size: 0.9rem;
      }
      .weekdays div {
        font-weight: bold;
        padding: 5px 0;
      }
      .days div {
        padding: 5px;
        cursor: pointer;
      }
      .days .today {
        background-color: red;
        border-radius: 50%;
        color: white;
      }
      @media (max-width: 800px) {
        .calendar {
          grid-template-columns: repeat(3, 1fr);
        }
        .month h3 {
          font-size: 1rem;
        }
        .weekdays,
        .days {
          font-size: 0.8rem;
        }
      }
      @media (max-width: 500px) {
        .calendar {
          grid-template-columns: repeat(2, 1fr);
        }
        .month h3 {
          font-size: 0.9rem;
        }
        .weekdays,
        .days {
          font-size: 0.7rem;
        }
      }
    </style>
  </head>
  <body>
    <div id="year"></div>
    <div class="calendar" id="calendar"></div>
    <script>
      const monthNames = [
        "January",
        "February",
        "March",
        "April",
        "May",
        "June",
        "July",
        "August",
        "September",
        "October",
        "November",
        "December",
      ];
      const weekdays = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
      let currentYear = new Date().getFullYear();

      document.addEventListener("DOMContentLoaded", () => {
        renderCalendar(currentYear);
        document.getElementById("year").innerText = currentYear;
      });

      document.addEventListener("keydown", (event) => {
        if (event.key === "ArrowLeft") {
          updateYear(-1);
        } else if (event.key === "ArrowRight") {
          updateYear(1);
        }
      });

      document.addEventListener("click", (event) => {
        if (event.button === 0) {
          // Left click
          updateYear(-1);
        }
      });

      document.addEventListener("contextmenu", (event) => {
        event.preventDefault(); // Prevent default context menu
        updateYear(1); // Right click
      });

      function updateYear(offset) {
        currentYear += offset;
        if (currentYear < 2016) currentYear = 2016;
        if (currentYear > 2116) currentYear = 2116;
        document.getElementById("year").innerText = currentYear;
        renderCalendar(currentYear);
      }

      function renderCalendar(year) {
        const calendar = document.getElementById("calendar");
        calendar.innerHTML = "";
        for (let i = 0; i < 12; i++) {
          const monthDiv = document.createElement("div");
          monthDiv.className = "month";
          const monthTitle = document.createElement("h3");
          monthTitle.innerText = monthNames[i];
          monthDiv.appendChild(monthTitle);

          const weekdaysDiv = document.createElement("div");
          weekdaysDiv.className = "weekdays";
          weekdays.forEach((day) => {
            const dayDiv = document.createElement("div");
            dayDiv.innerText = day;
            weekdaysDiv.appendChild(dayDiv);
          });
          monthDiv.appendChild(weekdaysDiv);

          const daysDiv = document.createElement("div");
          daysDiv.className = "days";
          const firstDay = new Date(year, i, 1).getDay();
          const daysInMonth = new Date(year, i + 1, 0).getDate();

          // Add empty divs for days before the first day of the month
          for (let j = 0; j < firstDay; j++) {
            daysDiv.appendChild(document.createElement("div"));
          }

          // Add days of the month
          for (let j = 1; j <= daysInMonth; j++) {
            const dayDiv = document.createElement("div");
            dayDiv.innerText = j;
            const today = new Date();
            if (
              year === today.getFullYear() &&
              i === today.getMonth() &&
              j === today.getDate()
            ) {
              dayDiv.className = "today";
            }
            daysDiv.appendChild(dayDiv);
          }

          monthDiv.appendChild(daysDiv);
          calendar.appendChild(monthDiv);
        }
      }
    </script>
  </body>
</html>' width="100%" height="800px" style="border:none;"></iframe>
"""



css = """
#warning {background-color: #C0C0C0}
.feedback textarea {font-size: 24px !important}

#element {
    //border: 1px solid black; /* 1px 宽度,实线,黑色 */
    margin-bottom: -250px; /* 使用负的外边距值 */
}

"""

with gr.Blocks(css=css) as demo:
    gr.HTML(html_iframe, elem_id="element")
    gr.Textbox(label='info', elem_id="warning", elem_classes="feedback")

demo.launch(inbrowser=True)


D. 问题分析

问题描述:

直接将html文件中的内容插入到gr.HTML()后无法显示

解决方案:

代码中没有任何显示的原因可能是由于 Gradio 的 gr.HTML 组件在显示 HTML 内容时的限制问题。gr.HTML 组件只能渲染纯 HTML 和 CSS 内容,对于包含 JavaScript 的代码,它不会自动执行脚本。因此,尽管 HTML 内容被正确加载,JavaScript 却没有执行,从而导致页面没有预期的动态效果。

为了在 Gradio 中正确展示和运行 JavaScript,可以尝试以下解决方案:

使用 IFrame: 将完整的 HTML 内容放入一个独立的 HTML 文件中,然后通过 Gradio 的 gr.HTML 加载一个 IFrame,将这个 HTML 文件嵌入其中。
托管网页并嵌入: 将 HTML 内容托管在一个 web 服务器上(例如 GitHub Pages),然后在 Gradio 中通过 IFrame 引入外部链接。

### 使用 LatentSync 与 Gradio 的集成 LatentSync 是一种用于同步潜在空间表示的技术,在机器学习模型特别是生成对抗网络 (GANs) 中非常有用。当与 Gradio 集成时,可以创建交互式的 Web 应用来展示操作这些潜在向量。 #### 安装依赖库 为了使用 LatentSync 功能并将其嵌入到 Gradio 应用程序中,首先需要确保安装了必要的 Python 包: ```bash pip install gradio torch numpy matplotlib opencv-python ``` #### 创建基本的 Gradio 接口 下面是一个简单的例子来说明如何构建一个带有 LatentSync 特性的 Gradio 应用程序[^1]: ```python import gradio as gr import numpy as np from PIL import Image import cv2 def latent_sync(image): # 假设这里有一个函数可以从图像中提取特征向量(即潜变量) features = extract_features_from_image(image) # 对于演示目的,我们只是返回随机噪声作为潜变量 random_latents = np.random.randn(512).astype(np.float32) return { "latent_vector": random_latents, "image_with_overlay": add_overlay_to_image(image, random_latents), } def extract_features_from_image(img): # 这里应该实现具体的特征提取逻辑... pass def add_overlay_to_image(base_img, latents): # 将潜变量可视化为热图或其他形式覆盖在原始图片上 heatmap = visualize_latents(latents) overlayed_img = blend_images(base_img, heatmap) return overlayed_img def visualize_latents(latents): # 可视化潜变量的方法;这只是一个占位符实现 heat_map = np.uint8((latents * 255.).reshape((16, 32))) colored_heatmap = cv2.applyColorMap(heat_map, cv2.COLORMAP_JET) resized_colored_heatmap = cv2.resize(colored_heatmap, dsize=(base_img.width, base_img.height)) return resized_colored_heatmap def blend_images(bg, fg): alpha_blended = cv2.addWeighted( bg.convert('RGB'), 0.7, Image.fromarray(fg), 0.3, 0) return alpha_blended with gr.Blocks() as demo: with gr.Row(): input_image = gr.Image(label="Input Image", type='pil') sync_button = gr.Button("Synchronize") output_group = gr.Group() with output_group: latent_output = gr.Textbox(label="Latent Vector") result_image = gr.Image(label="Image With Overlay", interactive=False) sync_button.click(fn=latent_sync, inputs=[input_image], outputs=[latent_output, result_image]) demo.launch() ``` 此代码片段展示了如何定义 `latent_sync` 函数以及相应的辅助功能,它们共同作用以接收输入图像、计算其对应的潜变量,并最终生成一张包含了该潜变量视觉化的输出图像。通过点击按钮触发这个过程,并利用 Gradio 提供的各种组件显示结果给用户查看。 请注意上述某些部分如 `extract_features_from_image()` `visualize_latents()` 实际上应由具体的应用场景决定其实现细节。这段代码仅提供了一个框架结构以便理解整体工作流程。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

GuokLiu

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

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

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

打赏作者

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

抵扣说明:

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

余额充值