1
0
mirror of https://github.com/sendevia/website.git synced 2026-03-06 15:42:34 +08:00

feat(MaterialCard): replace swipe interaction with hover-based image reveal

This commit is contained in:
2025-12-10 15:33:35 +08:00
parent 61b4e918a1
commit ecd2385e79
2 changed files with 24 additions and 62 deletions

View File

@@ -20,34 +20,6 @@ const props = withDefaults(defineProps<Props>(), {
variant: "feed",
impression: () => [],
});
const isSwapped = ref(false);
let touchStartX = 0;
// 是否有多张图片
const hasMultipleImages = () => props.impression && props.impression.length >= 2;
// 处理开始触摸
const handleTouchStart = (e: TouchEvent) => {
if (!hasMultipleImages()) return;
touchStartX = e.touches[0].clientX;
};
// 处理结束触摸
const handleTouchEnd = (e: TouchEvent) => {
if (!hasMultipleImages()) return;
const touchEndX = e.changedTouches[0].clientX;
const diff = touchStartX - touchEndX;
// 滑动距离超过 50px 视为有效
if (Math.abs(diff) > 50) {
if (diff > 0) {
isSwapped.value = true;
} else {
isSwapped.value = false;
}
}
};
</script>
<template>
@@ -61,13 +33,7 @@ const handleTouchEnd = (e: TouchEvent) => {
</div>
</div>
<div
v-if="props.impression && props.impression.length > 0"
class="image-container"
:class="{ swapped: isSwapped }"
@touchstart.passive="handleTouchStart"
@touchend.passive="handleTouchEnd"
>
<div v-if="props.impression && props.impression.length > 0" class="image-container">
<img
v-for="(imgUrl, index) in props.impression.slice(0, 2)"
:key="index"

View File

@@ -63,48 +63,44 @@
.image-container {
display: grid;
grid-template-columns: 100%;
gap: 6px;
transition: grid-template-columns var(--md-sys-motion-spring-fast-spatial-duration)
var(--md-sys-motion-spring-fast-spatial);
position: relative;
height: 200px;
&:has(img:nth-child(2)) {
grid-template-columns: calc(90% - 6px) 10%;
img:nth-child(1) {
opacity: 1;
z-index: 0;
}
img:nth-child(2) {
opacity: 0;
z-index: 1;
}
}
&.swapped,
&:hover {
&:has(img:nth-child(2)) {
grid-template-columns: 10% calc(90% - 6px);
img:nth-child(2) {
opacity: 1;
}
}
}
img {
height: 200px;
position: absolute;
top: 0px;
height: inherit;
width: 100%;
border-radius: var(--md-sys-shape-corner-extra-large);
object-fit: cover;
transition: border-radius var(--md-sys-motion-spring-fast-spatial-duration)
var(--md-sys-motion-spring-fast-spatial);
&:nth-child(1) {
border-radius: var(--md-sys-shape-corner-extra-large);
}
&:nth-child(2) {
border-radius: var(--md-sys-shape-corner-medium);
}
}
&.swapped:hover {
img:nth-child(1) {
border-radius: var(--md-sys-shape-corner-medium);
}
img:nth-child(2) {
border-radius: var(--md-sys-shape-corner-extra-large);
}
transition: opacity var(--md-sys-motion-spring-default-effect-duration)
var(--md-sys-motion-spring-default-effect);
}
}
}