feat: 为特色图选择器增加预览功能与自适应高度支持
This commit is contained in:
1 parent
9e33fabdbe
commit
edcf251945
1 file changed
+62
-4
@@ -1,19 +1,32 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { addToast } from '$lib/stores/toast.svelte';
|
import { addToast } from '$lib/stores/toast.svelte';
|
||||||
|
import { Fancybox } from '@fancyapps/ui/dist/index.js';
|
||||||
|
import '@fancyapps/ui/dist/fancybox/fancybox.css';
|
||||||
|
import { onMount } from 'svelte';
|
||||||
import Tabs from './Tabs.svelte';
|
import Tabs from './Tabs.svelte';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
cover = $bindable(''),
|
cover = $bindable(''),
|
||||||
title = '特色图',
|
title = '特色图',
|
||||||
inputName = 'cover',
|
inputName = 'cover',
|
||||||
aspectRatio = '16/9'
|
aspectRatio = '16/9',
|
||||||
|
adaptiveHeight = false,
|
||||||
|
previewable = false
|
||||||
} = $props<{
|
} = $props<{
|
||||||
cover?: string | null;
|
cover?: string | null;
|
||||||
title?: string;
|
title?: string;
|
||||||
inputName?: string;
|
inputName?: string;
|
||||||
aspectRatio?: string;
|
aspectRatio?: string;
|
||||||
|
adaptiveHeight?: boolean;
|
||||||
|
previewable?: boolean;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
|
let pickerElement = $state<HTMLDivElement>();
|
||||||
|
let previewHeightRatio = $derived((() => {
|
||||||
|
const [width, height] = aspectRatio.split('/').map(Number);
|
||||||
|
return width > 0 && height > 0 ? height / width : 9 / 16;
|
||||||
|
})());
|
||||||
|
|
||||||
let activeTab = $state('url');
|
let activeTab = $state('url');
|
||||||
let isUploading = $state(false);
|
let isUploading = $state(false);
|
||||||
|
|
||||||
@@ -22,6 +35,16 @@
|
|||||||
let hasMore = $state(true);
|
let hasMore = $state(true);
|
||||||
let isLoadingLibrary = $state(false);
|
let isLoadingLibrary = $state(false);
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
if (!previewable || !pickerElement) return;
|
||||||
|
|
||||||
|
const selector = '[data-fancybox="featured-image-preview"]';
|
||||||
|
const container = pickerElement;
|
||||||
|
Fancybox.bind(container, selector, {});
|
||||||
|
|
||||||
|
return () => Fancybox.unbind(container, selector);
|
||||||
|
});
|
||||||
|
|
||||||
async function loadLibrary(reset = false) {
|
async function loadLibrary(reset = false) {
|
||||||
if (reset) {
|
if (reset) {
|
||||||
page = 1;
|
page = 1;
|
||||||
@@ -89,14 +112,31 @@
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="sidebar-box">
|
<div class="sidebar-box" bind:this={pickerElement}>
|
||||||
{#if title}
|
{#if title}
|
||||||
<h3>{title}</h3>
|
<h3>{title}</h3>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if cover}
|
{#if cover}
|
||||||
<div class="cover-preview">
|
<div
|
||||||
<img src={cover} alt="图片预览" style:aspect-ratio={aspectRatio} />
|
class="cover-preview"
|
||||||
|
class:adaptive-height={adaptiveHeight}
|
||||||
|
style={`--preview-aspect-ratio: ${aspectRatio}; --preview-height-ratio: ${previewHeightRatio}`}
|
||||||
|
>
|
||||||
|
{#if previewable}
|
||||||
|
<a
|
||||||
|
class="cover-preview-link"
|
||||||
|
href={cover}
|
||||||
|
data-fancybox="featured-image-preview"
|
||||||
|
data-caption={title || '特色图'}
|
||||||
|
aria-label="查看特色图大图"
|
||||||
|
title="点击查看大图"
|
||||||
|
>
|
||||||
|
<img src={cover} alt="图片预览" />
|
||||||
|
</a>
|
||||||
|
{:else}
|
||||||
|
<img src={cover} alt="图片预览" />
|
||||||
|
{/if}
|
||||||
<button type="button" class="btn-clear" onclick={() => cover = ''}>移除</button>
|
<button type="button" class="btn-clear" onclick={() => cover = ''}>移除</button>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
@@ -166,6 +206,16 @@
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.cover-preview.adaptive-height {
|
||||||
|
container-type: inline-size;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cover-preview-link {
|
||||||
|
display: block;
|
||||||
|
background: #f5f5f5;
|
||||||
|
cursor: zoom-in;
|
||||||
|
}
|
||||||
|
|
||||||
.cover-preview img {
|
.cover-preview img {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: auto;
|
height: auto;
|
||||||
@@ -174,6 +224,14 @@
|
|||||||
max-height: 280px;
|
max-height: 280px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.cover-preview:not(.adaptive-height) img {
|
||||||
|
aspect-ratio: var(--preview-aspect-ratio);
|
||||||
|
}
|
||||||
|
|
||||||
|
.cover-preview.adaptive-height img {
|
||||||
|
max-height: min(280px, calc(100cqw * var(--preview-height-ratio)));
|
||||||
|
}
|
||||||
|
|
||||||
.btn-clear {
|
.btn-clear {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 8px;
|
top: 8px;
|
||||||
|
|||||||
Reference in new issue
Block a user