Skip to content

Commit e4a9010

Browse files
committed
update: enhance auto-play functionality in ImageMatrix component and adjust media query for responsive design
1 parent 0d11fc4 commit e4a9010

3 files changed

Lines changed: 107 additions & 23 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ coverage
2828
*.sw?
2929
yarn.lock
3030
public/dataset/*.zip
31+
public/dataset_backup
3132
public/dataset/*/images/dwpose
3233
public/dataset/*/images/edited
3334
public/dataset/*/images/garments

src/components/sections/ComparisonResults.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -655,7 +655,7 @@ onBeforeUnmount(() => document.removeEventListener('click', onDocClick))
655655
}
656656
}
657657
658-
@media (max-width: 400px) {
658+
@media (max-width: 500px) {
659659
.cr-gt-col {
660660
--cr-cell-width: 90px;
661661
}

src/components/sections/ImageMatrix.vue

Lines changed: 105 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -42,19 +42,28 @@ const AUTO_PLAY_INTERVAL = 10000
4242
let autoPlayTimer: number | undefined
4343
// 用于驱动自动翻页进度条动画重启
4444
const progressSeed = ref(0)
45+
/** 是否开启自动播放(默认开启) */
46+
const autoPlayEnabled = ref(true)
4547
4648
const resetAutoPlay = () => {
4749
if (typeof window === 'undefined') return
4850
if (autoPlayTimer !== undefined) {
4951
window.clearInterval(autoPlayTimer)
52+
autoPlayTimer = undefined
53+
}
54+
if (autoPlayEnabled.value) {
55+
autoPlayTimer = window.setInterval(() => {
56+
goToNextPage()
57+
}, AUTO_PLAY_INTERVAL)
5058
}
51-
autoPlayTimer = window.setInterval(() => {
52-
goToNextPage()
53-
}, AUTO_PLAY_INTERVAL)
54-
// 重启进度条动画
5559
progressSeed.value++
5660
}
5761
62+
const toggleAutoPlay = () => {
63+
autoPlayEnabled.value = !autoPlayEnabled.value
64+
resetAutoPlay()
65+
}
66+
5867
onMounted(() => {
5968
calcCols()
6069
if (typeof window !== 'undefined') {
@@ -120,7 +129,9 @@ const goToNextPage = () => {
120129
type DisplayItem = {
121130
id: string
122131
mainSrc: string
132+
mainSrcPng: string
123133
mainThumbSrc: string
134+
mainThumbSrcPng: string
124135
overlaySrc: string
125136
overlayThumbSrc: string
126137
skeletonSrc: string
@@ -161,13 +172,18 @@ const displayItems = computed<DisplayItem[]>(() => {
161172
const id = ids[indexInPage]
162173
if (id) {
163174
const mainSrc = `${baseUrl}dataset/${id}/images/look/${id}.jpg`
175+
const mainSrcPng = `${baseUrl}dataset/${id}/images/look/${id}.png`
176+
const mainThumbSrc = `${baseUrl}thumbnail/${id}/images/look/${id}.jpg`
177+
const mainThumbSrcPng = `${baseUrl}thumbnail/${id}/images/look/${id}.png`
164178
const overlaySrc = `${baseUrl}dataset/${id}/images/segment/color_segmentation.png`
165179
const skeletonSrc = `${baseUrl}dataset/${id}/images/dwpose/${id}.png`
166180
167181
items.push({
168182
id,
169183
mainSrc,
170-
mainThumbSrc: mainSrc.replace(`${baseUrl}dataset/`, `${baseUrl}thumbnail/`),
184+
mainSrcPng,
185+
mainThumbSrc,
186+
mainThumbSrcPng,
171187
overlaySrc,
172188
overlayThumbSrc: overlaySrc.replace(`${baseUrl}dataset/`, `${baseUrl}thumbnail/`),
173189
skeletonSrc,
@@ -178,39 +194,42 @@ const displayItems = computed<DisplayItem[]>(() => {
178194
}
179195
180196
// 没有显式指定 id 的格子统一使用 loading 占位图
197+
const loading = `${baseUrl}dataset/loading.jpg`
181198
items.push({
182199
id: `placeholder-${currentPage.value}-${i}`,
183-
mainSrc: `${baseUrl}dataset/loading.jpg`,
184-
mainThumbSrc: `${baseUrl}dataset/loading.jpg`,
185-
overlaySrc: `${baseUrl}dataset/loading.jpg`,
186-
overlayThumbSrc: `${baseUrl}dataset/loading.jpg`,
187-
skeletonSrc: `${baseUrl}dataset/loading.jpg`,
188-
skeletonThumbSrc: `${baseUrl}dataset/loading.jpg`,
200+
mainSrc: loading,
201+
mainSrcPng: loading,
202+
mainThumbSrc: loading,
203+
mainThumbSrcPng: loading,
204+
overlaySrc: loading,
205+
overlayThumbSrc: loading,
206+
skeletonSrc: loading,
207+
skeletonThumbSrc: loading,
189208
})
190209
}
191210
192211
return items
193212
})
194213
195-
// 矩阵图优先用缩略图(省流),404 再回退原图;look 还有 jpgpng 回退
214+
// look 图回退顺序:thumbnail jpg → thumbnail png → dataset jpg → dataset png
196215
const lookUrlCache = ref<Record<string, string>>({})
197216
const overlayUrlCache = ref<Record<string, string>>({})
198217
const skeletonUrlCache = ref<Record<string, string>>({})
199218
219+
const LOOK_FALLBACK_ORDER = (item: DisplayItem) =>
220+
[item.mainThumbSrc, item.mainThumbSrcPng, item.mainSrc, item.mainSrcPng] as const
221+
200222
function getMainLookSrc(item: DisplayItem): string {
201-
return lookUrlCache.value[item.id] ?? item.mainThumbSrc ?? item.mainSrc
223+
return lookUrlCache.value[item.id] ?? item.mainThumbSrc
202224
}
203225
204226
function onLookImageError(item: DisplayItem) {
205227
if (item.id.startsWith('placeholder-')) return
206-
const tried = lookUrlCache.value[item.id] ?? item.mainThumbSrc ?? item.mainSrc
207-
if (tried === item.mainThumbSrc) {
208-
lookUrlCache.value = { ...lookUrlCache.value, [item.id]: item.mainSrc }
209-
} else if (tried.endsWith('.jpg')) {
210-
lookUrlCache.value = {
211-
...lookUrlCache.value,
212-
[item.id]: `${baseUrl}dataset/${item.id}/images/look/${item.id}.png`,
213-
}
228+
const order = LOOK_FALLBACK_ORDER(item)
229+
const tried = lookUrlCache.value[item.id] ?? item.mainThumbSrc
230+
const idx = order.indexOf(tried)
231+
if (idx >= 0 && idx < order.length - 1) {
232+
lookUrlCache.value = { ...lookUrlCache.value, [item.id]: order[idx + 1] }
214233
}
215234
}
216235
@@ -364,7 +383,7 @@ const closeDetail = () => {
364383
:key="progressSeed"
365384
:style="{
366385
animationDuration: AUTO_PLAY_INTERVAL + 'ms',
367-
animationPlayState: isDetailVisible ? 'paused' : 'running',
386+
animationPlayState: isDetailVisible || !autoPlayEnabled ? 'paused' : 'running',
368387
}"
369388
></div>
370389
</div>
@@ -389,6 +408,13 @@ const closeDetail = () => {
389408
>
390409
391410
</button>
411+
<span class="auto-play-wrap">
412+
<span class="auto-play-label">Auto-play</span>
413+
<label class="auto-play-switch" :title="autoPlayEnabled ? 'Disable auto-play' : 'Enable auto-play'">
414+
<input type="checkbox" :checked="autoPlayEnabled" @change="toggleAutoPlay" />
415+
<span class="auto-play-slider"></span>
416+
</label>
417+
</span>
392418
</div>
393419

394420
<OutfitDetailModal
@@ -564,6 +590,63 @@ const closeDetail = () => {
564590
transform: none;
565591
}
566592
593+
/* 自动播放:文字 + 开关 */
594+
.auto-play-wrap {
595+
display: inline-flex;
596+
align-items: center;
597+
gap: 8px;
598+
font-size: 12px;
599+
color: #666666;
600+
}
601+
602+
.auto-play-label {
603+
user-select: none;
604+
}
605+
606+
.auto-play-switch {
607+
position: relative;
608+
display: inline-block;
609+
width: 40px;
610+
height: 22px;
611+
flex-shrink: 0;
612+
cursor: pointer;
613+
}
614+
615+
.auto-play-switch input {
616+
opacity: 0;
617+
width: 0;
618+
height: 0;
619+
}
620+
621+
.auto-play-slider {
622+
position: absolute;
623+
inset: 0;
624+
border-radius: 22px;
625+
background: #d0d0d0;
626+
transition: background 0.25s ease;
627+
}
628+
629+
.auto-play-slider::before {
630+
content: '';
631+
position: absolute;
632+
width: 18px;
633+
height: 18px;
634+
left: 2px;
635+
top: 2px;
636+
border-radius: 50%;
637+
background: #ffffff;
638+
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
639+
transition: transform 0.25s ease;
640+
}
641+
642+
.auto-play-switch input:checked + .auto-play-slider {
643+
background: #409eff;
644+
}
645+
646+
.auto-play-switch input:checked + .auto-play-slider::before {
647+
transform: translateX(18px);
648+
}
649+
567650
.nav-btn:hover {
568651
background: #e0e0e0;
569652
}

0 commit comments

Comments
 (0)