mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-04-28 02:02:08 +00:00
Add thumbnails for workflow templates (#2729)
Co-authored-by: github-actions <github-actions@github.com>
This commit is contained in:
15
src/components/templates/thumbnails/AudioThumbnail.vue
Normal file
15
src/components/templates/thumbnails/AudioThumbnail.vue
Normal file
@@ -0,0 +1,15 @@
|
||||
<template>
|
||||
<BaseThumbnail>
|
||||
<div class="w-64 h-64 flex items-center justify-center p-4">
|
||||
<audio controls class="w-full relative" :src="src" @click.stop />
|
||||
</div>
|
||||
</BaseThumbnail>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import BaseThumbnail from '@/components/templates/thumbnails/BaseThumbnail.vue'
|
||||
|
||||
defineProps<{
|
||||
src: string
|
||||
}>()
|
||||
</script>
|
||||
30
src/components/templates/thumbnails/BaseThumbnail.vue
Normal file
30
src/components/templates/thumbnails/BaseThumbnail.vue
Normal file
@@ -0,0 +1,30 @@
|
||||
<template>
|
||||
<div class="relative w-64 h-64 rounded-t-lg overflow-hidden select-none">
|
||||
<div v-if="!error" ref="contentRef">
|
||||
<slot />
|
||||
</div>
|
||||
<div
|
||||
v-else
|
||||
class="w-full h-full flex items-center justify-center bg-surface-card"
|
||||
>
|
||||
<i class="pi pi-file text-4xl text-surface-600" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useEventListener } from '@vueuse/core'
|
||||
import { onMounted, ref } from 'vue'
|
||||
|
||||
const error = ref(false)
|
||||
const contentRef = ref<HTMLElement | null>(null)
|
||||
|
||||
onMounted(() => {
|
||||
const images = Array.from(contentRef.value?.getElementsByTagName('img') ?? [])
|
||||
images.forEach((img) => {
|
||||
useEventListener(img, 'error', () => {
|
||||
error.value = true
|
||||
})
|
||||
})
|
||||
})
|
||||
</script>
|
||||
@@ -0,0 +1,51 @@
|
||||
<template>
|
||||
<BaseThumbnail>
|
||||
<img :src="baseImageSrc" :alt="alt" class="w-full h-full object-cover" />
|
||||
<div ref="containerRef" class="absolute inset-0">
|
||||
<img
|
||||
:src="overlayImageSrc"
|
||||
:alt="alt"
|
||||
class="w-full h-full object-cover"
|
||||
:style="{
|
||||
clipPath: `inset(0 ${100 - sliderPosition}% 0 0)`
|
||||
}"
|
||||
/>
|
||||
<div
|
||||
class="absolute inset-y-0 w-0.5 bg-white/30 backdrop-blur-sm z-10 pointer-events-none"
|
||||
:style="{
|
||||
left: `${sliderPosition}%`
|
||||
}"
|
||||
/>
|
||||
</div>
|
||||
</BaseThumbnail>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useMouseInElement } from '@vueuse/core'
|
||||
import { ref, watch } from 'vue'
|
||||
|
||||
import BaseThumbnail from '@/components/templates/thumbnails/BaseThumbnail.vue'
|
||||
|
||||
const { isHovered } = defineProps<{
|
||||
baseImageSrc: string
|
||||
overlayImageSrc: string
|
||||
alt: string
|
||||
isHovered?: boolean
|
||||
}>()
|
||||
|
||||
const sliderPosition = ref(21)
|
||||
const containerRef = ref<HTMLElement | null>(null)
|
||||
|
||||
const { elementX, elementWidth, isOutside } = useMouseInElement(containerRef)
|
||||
|
||||
// Update slider position based on mouse position when hovered
|
||||
watch(
|
||||
[() => isHovered, elementX, elementWidth, isOutside],
|
||||
([isHovered, x, width, outside]) => {
|
||||
if (!isHovered) return
|
||||
if (!outside) {
|
||||
sliderPosition.value = (x / width) * 100
|
||||
}
|
||||
}
|
||||
)
|
||||
</script>
|
||||
37
src/components/templates/thumbnails/DefaultThumbnail.vue
Normal file
37
src/components/templates/thumbnails/DefaultThumbnail.vue
Normal file
@@ -0,0 +1,37 @@
|
||||
<template>
|
||||
<BaseThumbnail>
|
||||
<div ref="containerRef" class="overflow-hidden">
|
||||
<img
|
||||
:src="src"
|
||||
:alt="alt"
|
||||
draggable="false"
|
||||
class="w-64 h-64 object-cover transform-gpu transition-transform duration-300 ease-out"
|
||||
:style="
|
||||
isHovered ? { transform: `scale(${1 + hoverZoom / 100})` } : undefined
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
</BaseThumbnail>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useElementHover } from '@vueuse/core'
|
||||
import { ref } from 'vue'
|
||||
|
||||
import BaseThumbnail from '@/components/templates/thumbnails/BaseThumbnail.vue'
|
||||
|
||||
const { hoverZoom = 8 } = defineProps<{
|
||||
src: string
|
||||
alt: string
|
||||
hoverZoom?: number
|
||||
}>()
|
||||
|
||||
const containerRef = ref<HTMLElement | null>(null)
|
||||
const isHovered = useElementHover(containerRef)
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
img {
|
||||
transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,30 @@
|
||||
<template>
|
||||
<BaseThumbnail>
|
||||
<div class="relative w-full h-full">
|
||||
<img
|
||||
:src="baseImageSrc"
|
||||
:alt="alt"
|
||||
draggable="false"
|
||||
class="absolute inset-0 w-64 h-64 object-cover"
|
||||
/>
|
||||
<img
|
||||
:src="overlayImageSrc"
|
||||
:alt="alt"
|
||||
draggable="false"
|
||||
class="absolute inset-0 w-64 h-64 object-cover transition-opacity duration-300"
|
||||
:class="{ 'opacity-100': isHovered, 'opacity-0': !isHovered }"
|
||||
/>
|
||||
</div>
|
||||
</BaseThumbnail>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import BaseThumbnail from '@/components/templates/thumbnails/BaseThumbnail.vue'
|
||||
|
||||
defineProps<{
|
||||
baseImageSrc: string
|
||||
overlayImageSrc: string
|
||||
alt: string
|
||||
isHovered: boolean
|
||||
}>()
|
||||
</script>
|
||||
Reference in New Issue
Block a user