diff --git a/.vitepress/theme/components/ImageViewer.vue b/.vitepress/theme/components/ImageViewer.vue index fd8289a..7f947da 100644 --- a/.vitepress/theme/components/ImageViewer.vue +++ b/.vitepress/theme/components/ImageViewer.vue @@ -86,7 +86,7 @@ const show = () => { // 延迟一帧触发动画,确保 CSS 过渡生效 isAnimating.value = true; // 将焦点转移到查看器内部的关闭按钮 - const closeBtn = document.querySelector(".btn-close"); + const closeBtn = document.querySelector(".ImageViewer .close"); closeBtn?.focus(); }); }; @@ -113,8 +113,32 @@ const hide = () => { const prevImage = () => hasPrevious.value && activeIndex.value--; const nextImage = () => hasNext.value && activeIndex.value++; -/** 键盘交互处理 */ -useEventListener("keydown", (e: KeyboardEvent) => { +/** 导航 ButtonGroup 按钮配置 */ +const BUTTONS_NAV_CONFIG = computed(() => [ + { id: "prev", icon: "chevron_left", ariaLabel: "上一张", type: "normal" }, + { + id: "index", + label: `${activeIndex.value + 1} / ${props.images.length}`, + color: "tonal", + ariaLabel: "当前页码", + }, + { id: "next", icon: "chevron_right", ariaLabel: "下一张", type: "normal" }, +]); + +/** 处理按钮组点击事件 */ +const handleButtonGroupClick = (e: Event, item: any) => { + switch (item.id) { + case "prev": + prevImage(); + break; + case "next": + nextImage(); + break; + } +}; + +/** 处理键盘快捷键 */ +const handleKeyboardShortcuts = (e: KeyboardEvent) => { if (!isVisible.value) return; // 陷阱焦点逻辑 @@ -146,7 +170,10 @@ useEventListener("keydown", (e: KeyboardEvent) => { imageScale.value = Math.max(ZOOM_CONFIG.MIN, imageScale.value - ZOOM_CONFIG.STEP); break; } -}); +}; + +/** 键盘交互处理 */ +useEventListener("keydown", handleKeyboardShortcuts); /** 滚轮缩放与翻页 */ const handleWheel = (e: WheelEvent) => { @@ -202,7 +229,7 @@ const handleTouchMove = (e: TouchEvent) => { const dist = Math.sqrt(dx * dx + dy * dy); imageScale.value = Math.min( Math.max((dist / initialTouchDist) * initialTouchScale, ZOOM_CONFIG.MIN), - ZOOM_CONFIG.MAX_TOUCH + ZOOM_CONFIG.MAX_TOUCH, ); } else if (e.touches.length === 1) { const touch = e.touches[0]; @@ -234,23 +261,15 @@ defineExpose({ show, hide }); aria-modal="true" tabindex="-1" > - - - + +
-

{{ activeIndex + 1 }} / {{ images.length }}

-
- -
diff --git a/.vitepress/theme/styles/components/ImageViewer.scss b/.vitepress/theme/styles/components/ImageViewer.scss index 39fe3a1..9775ace 100644 --- a/.vitepress/theme/styles/components/ImageViewer.scss +++ b/.vitepress/theme/styles/components/ImageViewer.scss @@ -22,47 +22,26 @@ -moz-user-select: none; z-index: 9999; - .index-text { - padding-block: 3px; - padding-inline: 9px; + .nav-group { + position: absolute; + bottom: 0px; - color: var(--md-sys-color-surface-variant); - - border-radius: var(--md-sys-shape-corner-medium); - - background-color: var(--md-sys-color-on-surface-variant); + margin-block-end: 12px; z-index: 3; } - .btn-close, - .btn-nav { - display: flex; - align-items: center; - justify-content: center; + .close { + position: absolute; + right: 0px; + top: 0px; - position: absolute !important; + margin-inline-end: 12px; + margin-block-start: 12px; z-index: 3; } - .btn-close { - right: 20px; - top: 20px; - } - - .btn-nav { - top: 50%; - - &.prev { - left: 20px; - } - - &.next { - right: 20px; - } - } - .content { display: flex; align-items: center; @@ -74,70 +53,21 @@ padding-block-start: 5vh; z-index: 2; - } - .content-image { - border-radius: var(--md-sys-shape-corner-full); + .content-image { + background-color: var(--md-sys-color-surface-variant); - background-color: var(--md-sys-color-surface-variant); + clip-path: circle(10%); + object-fit: contain; + transition: var(--md-sys-motion-spring-slow-spatial-duration) var(--md-sys-motion-spring-slow-spatial); - clip-path: circle(10%); - object-fit: contain; - transition: var(--md-sys-motion-spring-slow-spatial-duration) var(--md-sys-motion-spring-slow-spatial); + &.transitioning { + opacity: 0.6; + } - &.transitioning { - opacity: 0.6; - } - - &.notransition { - transition: none !important; - } - } - - .thumbnails { - display: flex; - gap: 8px; - - max-width: calc(100% - 66px); - - padding: 24px; - - overflow-x: auto; - overflow-y: hidden; - z-index: 3; - } - - .thumbnail { - flex-shrink: 0; - - width: 66px; - height: 66px; - - padding: 0px; - - border: 0px; - border-radius: var(--md-sys-shape-corner-large); - - cursor: pointer; - overflow: hidden; - transition: transform var(--md-sys-motion-spring-fast-spatial-duration) var(--md-sys-motion-spring-fast-spatial); - - &.active { - @include mixin.focus-ring($thickness: 1, $offset: 2); - - outline-color: var(--md-sys-color-on-surface-variant) !important; - transition: transform var(--md-sys-motion-spring-fast-spatial-duration) var(--md-sys-motion-spring-fast-spatial); - } - - &:hover { - transform: scale(0.9); - } - - img { - height: 100%; - width: 100%; - - object-fit: cover; + &.notransition { + transition: none !important; + } } } @@ -146,8 +76,6 @@ opacity: 1; .content-image { - border-radius: var(--md-sys-shape-corner-large); - clip-path: circle(100%); } }