Files
ComfyUI_frontend/src/components/common/ComfyImage.vue

113 lines
2.1 KiB
Vue

<!-- A image with placeholder fallback on error -->
<template>
<span
v-if="!imageBroken"
class="comfy-image-wrap"
:class="[{ contain: contain }]"
>
<img
v-if="contain"
:src="src"
@error="handleImageError"
:data-test="src"
class="comfy-image-blur"
:style="{ 'background-image': `url(${src})` }"
:alt="alt"
/>
<img
:src="src"
@error="handleImageError"
class="comfy-image-main"
:class="[...classArray]"
:alt="alt"
/>
</span>
<div v-if="imageBroken" class="broken-image-placeholder">
<i class="pi pi-image"></i>
<span>{{ $t('g.imageFailedToLoad') }}</span>
</div>
</template>
<script setup lang="ts">
import { computed, ref } from 'vue'
const props = withDefaults(
defineProps<{
src: string
class?: string | string[] | object
contain: boolean
alt?: string
}>(),
{
contain: false,
alt: 'Image content'
}
)
const imageBroken = ref(false)
const handleImageError = (e: Event) => {
imageBroken.value = true
}
const classArray = computed(() => {
if (Array.isArray(props.class)) {
return props.class
} else if (typeof props.class === 'string') {
return props.class.split(' ')
} else if (typeof props.class === 'object') {
return Object.keys(props.class).filter((key) => props.class[key])
}
return []
})
</script>
<style scoped>
.comfy-image-wrap {
display: contents;
}
.comfy-image-blur {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: cover;
}
.comfy-image-main {
width: 100%;
height: 100%;
object-fit: cover;
object-position: center;
z-index: 1;
}
.contain .comfy-image-wrap {
position: relative;
width: 100%;
height: 100%;
}
.contain .comfy-image-main {
object-fit: contain;
backdrop-filter: blur(10px);
position: absolute;
}
.broken-image-placeholder {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
margin: 2rem;
}
.broken-image-placeholder i {
font-size: 3rem;
margin-bottom: 0.5rem;
}
</style>