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:
@@ -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"
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user