如何使 SVG Overlay 的 viewBox 与下面的图像大小相同?

问题描述 投票:0回答:1

我想使用 Python NiceGUI 库构建一个小型 GUI。 对于我的应用程序,我使用网格元素将界面分为两列。这很好用。左侧有一些带有复选框的卡片,可以查看叠加层。

在右栏中,我插入了一张 T 恤图像,并希望在该图像上覆盖一个小红色框,该红色框标记了 T 恤上的一个洞。框的坐标在与原始图像大小一起使用的列表中给出。 (我已经使用

plt.imshow()
对此进行了测试)。

我已经弄清楚如何显示 viewBox,绘制红色框并将其覆盖在图像上。

只是覆盖层的尺寸与图像的尺寸还不匹配。由于某种原因,覆盖层周围有未指定数量的填充,我似乎无法访问或获取其 ID。

我认为这应该可以使用

.props()
.style()
.classes()
方法或列的宽度来修复,但我不知道使用哪一种以及如何使用。对于我的应用程序,图像和视图框有多大并不重要,只要它们相同即可使红色框位于正确的位置。

我不熟悉 html 或 CSS,因此代码中的那些部分可能存在我不知道的错误。 (我也愿意接受风格改进。)

在我看来,NiceGUI 在其文档中给出的示例也有类似的问题。 (参见https://nicegui.io/documentation/section_audiovisual_elements#captions_and_overlays) 如果您手动检查飞机图片的元素并手动将

cx
更改为 960,将
cy
更改为 638(视图框的尺寸),则飞机周围会出现圆圈,这对我来说更有意义。

这是一个小工作示例: (任何图像都应该有效,但这就是我得到我的图像的地方: https://www.ebay.com/itm/225367896573

from nicegui import ui

complete_im = plt.imread("test_file_large.jpg")
y_dim, x_dim = complete_im.shape[1], complete_im.shape[0]

tile = complete_im[355:385, 895:935]  # This was saved to 'test_hole_3.jpg'

tile_files = ['test_hole_3.jpg']
tile_ids = (355, 385, 895, 935)
tile_dims = (30, 40)

with ui.grid(columns=2).classes("w-auto").style():
    with ui.card():
        ui.image(tile_files[0])
        ui.space()
        checkbox_0 = ui.checkbox('Show hole')
        checkbox_0.value = True

    with ui.image('test_file_large.jpg').style('object-position: top right;'):
        # .props('fit=contain'):
        svg_code = f'''
                  <svg viewBox="0 0 {y_dim} {x_dim}" width="100%" height="100%" 
                       xmlns="http://www.w3.org/2000/svg" style="color: transparent;">
                  <rect width="{str(tile_dims[1])}" height="{str(tile_dims[0])}" 
                      x="{str(tile_ids[2])}" y="{str(tile_ids[0])}" 
                      style="stroke:red;stroke-width:5;fill-opacity:0.0;stroke-opacity:0.99" />
                      </svg>'''

        ui.html(svg_code).bind_visibility_from(checkbox_0, 'value')

ui.run()
python html css viewbox nicegui
1个回答
0
投票

为了让 SVG 填充完整图像尺寸,您可以添加一个“w-full”类,如下所示:

with ui.image('https://cdn.stocksnap.io/img-thumbs/960w/airplane-sky_DYPWDEEILG.jpg'):
    ui.html('''
        <svg viewBox="0 0 960 638" width="100%" height="100%" xmlns="http://www.w3.org/2000/svg">
        <circle cx="445" cy="300" r="100" fill="none" stroke="red" stroke-width="10" />
        </svg>
    ''').classes('w-full bg-transparent')

(我正在使用 NiceGUI 网站上的示例,因为您的代码需要更多工作才能运行。)

顺便说一下,你正确地发现了官方示例中的一个错误。我们将在下一次网站更新时修复它。

除此之外,

ui.interactive_image
可能比常规的
ui.image
更适合,因为它带有开箱即用的正确缩放的SVG:

ui.interactive_image(
    'https://cdn.stocksnap.io/img-thumbs/960w/airplane-sky_DYPWDEEILG.jpg',
    content='<circle cx="445" cy="300" r="100" fill="none" stroke="red" stroke-width="10" />',
)
© www.soinside.com 2019 - 2024. All rights reserved.