adf0d17497
publish / version_or_publish (push) Has been cancelled
storybook-build / changes (push) Has been cancelled
storybook-build / :storybook-build (push) Has been cancelled
Sync Gradio Skills to Hugging Face / sync-skills (push) Has been cancelled
functional / changes (push) Has been cancelled
functional / build-frontend (push) Has been cancelled
functional / functional-test-SSR=false (push) Has been cancelled
functional / functional-reload (push) Has been cancelled
js / changes (push) Has been cancelled
js / js-test (push) Has been cancelled
docs-build / changes (push) Has been cancelled
docs-build / docs-build (push) Has been cancelled
docs-build / website-build (push) Has been cancelled
functional / functional-test-SSR=true (push) Has been cancelled
hygiene / hygiene-test (push) Has been cancelled
python / changes (push) Has been cancelled
python / build (push) Has been cancelled
python / test-ubuntu-latest-flaky (push) Has been cancelled
python / test-ubuntu-latest-not-flaky (push) Has been cancelled
python / test-windows-latest-flaky (push) Has been cancelled
python / test-windows-latest-not-flaky (push) Has been cancelled
194 lines
4.7 KiB
Svelte
194 lines
4.7 KiB
Svelte
<script lang="ts">
|
|
import {
|
|
Block,
|
|
BlockLabel,
|
|
Empty,
|
|
IconButtonWrapper,
|
|
FullscreenButton
|
|
} from "@gradio/atoms";
|
|
import type { CustomButton as CustomButtonType } from "@gradio/utils";
|
|
import { Image } from "@gradio/icons";
|
|
import { StatusTracker } from "@gradio/statustracker";
|
|
import { Gradio } from "@gradio/utils";
|
|
import type { AnnotatedImageProps, AnnotatedImageEvents } from "./types";
|
|
|
|
const props = $props();
|
|
const gradio = new Gradio<AnnotatedImageEvents, AnnotatedImageProps>(props);
|
|
|
|
let active: string | null = $state(null);
|
|
let image_container: HTMLElement;
|
|
let fullscreen = $state(false);
|
|
let label = $derived(
|
|
gradio.shared.label || gradio.i18n("annotated_image.annotated_image")
|
|
);
|
|
|
|
gradio.watch_for_change();
|
|
|
|
function handle_mouseover(_label: string): void {
|
|
active = _label;
|
|
}
|
|
|
|
function handle_mouseout(): void {
|
|
active = null;
|
|
}
|
|
|
|
function handle_click(i: number, value: string): void {
|
|
gradio.dispatch("select", {
|
|
value: value,
|
|
index: i
|
|
});
|
|
}
|
|
</script>
|
|
|
|
<Block
|
|
visible={gradio.shared.visible}
|
|
elem_id={gradio.shared.elem_id}
|
|
elem_classes={gradio.shared.elem_classes}
|
|
padding={false}
|
|
height={gradio.props.height}
|
|
width={gradio.props.width}
|
|
allow_overflow={false}
|
|
container={gradio.shared.container}
|
|
scale={gradio.shared.scale}
|
|
min_width={gradio.shared.min_width}
|
|
bind:fullscreen
|
|
>
|
|
<StatusTracker
|
|
autoscroll={gradio.shared.autoscroll}
|
|
i18n={gradio.i18n}
|
|
{...gradio.shared.loading_status}
|
|
/>
|
|
<BlockLabel show_label={gradio.shared.show_label} Icon={Image} {label} />
|
|
|
|
<div class="container">
|
|
{#if gradio.props.value == null}
|
|
<Empty size="large" unpadded_box={true}><Image /></Empty>
|
|
{:else}
|
|
<div class="image-container" bind:this={image_container}>
|
|
<IconButtonWrapper
|
|
buttons={gradio.props.buttons || []}
|
|
on_custom_button_click={(id) => {
|
|
gradio.dispatch("custom_button_click", { id });
|
|
}}
|
|
>
|
|
{#if (gradio.props.buttons || []).some((btn) => typeof btn === "string" && btn === "fullscreen")}
|
|
<FullscreenButton
|
|
{fullscreen}
|
|
onclick={(fs) => (fullscreen = fs)}
|
|
/>
|
|
{/if}
|
|
</IconButtonWrapper>
|
|
|
|
<img
|
|
class="base-image"
|
|
class:fit-height={gradio.props.height && !fullscreen}
|
|
src={gradio.props.value ? gradio.props.value.image.url : null}
|
|
alt="the base file that is annotated"
|
|
/>
|
|
{#each gradio.props.value ? gradio.props.value.annotations : [] as ann, i}
|
|
<img
|
|
alt="segmentation mask identifying {gradio.shared
|
|
.label} within the uploaded file"
|
|
class="mask fit-height"
|
|
class:fit-height={!fullscreen}
|
|
class:active={active == ann.label}
|
|
class:inactive={active != ann.label && active != null}
|
|
src={ann.image.url}
|
|
style={gradio.props.color_map && ann.label in gradio.props.color_map
|
|
? null
|
|
: `filter: hue-rotate(${Math.round(
|
|
(i * 360) / (gradio.props.value?.annotations.length ?? 1)
|
|
)}deg);`}
|
|
/>
|
|
{/each}
|
|
</div>
|
|
{#if gradio.props.show_legend && gradio.props.value}
|
|
<div class="legend">
|
|
{#each gradio.props.value.annotations as ann, i}
|
|
<button
|
|
class="legend-item"
|
|
style="background-color: {gradio.props.color_map &&
|
|
ann.label in gradio.props.color_map
|
|
? gradio.props.color_map[ann.label] + '88'
|
|
: `hsla(${Math.round(
|
|
(i * 360) / gradio.props.value.annotations.length
|
|
)}, 100%, 50%, 0.3)`}"
|
|
on:mouseover={() => handle_mouseover(ann.label)}
|
|
on:focus={() => handle_mouseover(ann.label)}
|
|
on:mouseout={() => handle_mouseout()}
|
|
on:blur={() => handle_mouseout()}
|
|
on:click={() => handle_click(i, ann.label)}
|
|
>
|
|
{ann.label}
|
|
</button>
|
|
{/each}
|
|
</div>
|
|
{/if}
|
|
{/if}
|
|
</div>
|
|
</Block>
|
|
|
|
<style>
|
|
.base-image {
|
|
display: block;
|
|
width: 100%;
|
|
height: auto;
|
|
}
|
|
.container {
|
|
display: flex;
|
|
position: relative;
|
|
flex-direction: column;
|
|
justify-content: center;
|
|
align-items: center;
|
|
width: var(--size-full);
|
|
height: var(--size-full);
|
|
}
|
|
.image-container {
|
|
position: relative;
|
|
top: 0;
|
|
left: 0;
|
|
flex-grow: 1;
|
|
width: 100%;
|
|
overflow: hidden;
|
|
}
|
|
.fit-height {
|
|
top: 0;
|
|
left: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
object-fit: contain;
|
|
}
|
|
.mask {
|
|
opacity: 0.85;
|
|
transition: all 0.2s ease-in-out;
|
|
position: absolute;
|
|
}
|
|
.image-container:hover .mask {
|
|
opacity: 0.3;
|
|
}
|
|
.mask.active {
|
|
opacity: 1;
|
|
}
|
|
.mask.inactive {
|
|
opacity: 0;
|
|
}
|
|
.legend {
|
|
display: flex;
|
|
flex-direction: row;
|
|
flex-wrap: wrap;
|
|
align-content: center;
|
|
justify-content: center;
|
|
align-items: center;
|
|
gap: var(--spacing-sm);
|
|
padding: var(--spacing-sm);
|
|
}
|
|
.legend-item {
|
|
display: flex;
|
|
flex-direction: row;
|
|
align-items: center;
|
|
cursor: pointer;
|
|
border-radius: var(--radius-sm);
|
|
padding: var(--spacing-sm);
|
|
}
|
|
</style>
|