768 investor 财务数据 滑动效果

This commit is contained in:
张 元山 2025-03-14 18:01:49 +08:00
parent af90a49f35
commit e8c74caab7

View File

@ -112,11 +112,30 @@
委托书
</div>
</div>
<div class="w-2/3 font-normal text-[#9F9F9F]">
<div
class="bg-[#C6ACFF] color-[#fff] ma-[6px] px-[25px] py-[30px] font-semibold"
class="w-2/3 font-normal text-[#9F9F9F] year-content-animation"
ref="yearContent"
@mouseenter="pauseYearInterval"
@mouseleave="resumeYearInterval"
@touchstart="handleTouchStart"
@touchend="handleTouchEnd"
@touchmove="handleTouchMove"
@mousedown="handleMouseDown"
@mouseup="handleMouseUp"
@mousemove="handleMouseMove"
>
<div>2023</div>
<div
class="color-[#fff] ma-[6px] px-[25px] py-[30px] font-semibold"
:class="
state.activeYear === 2021
? 'bg-[#6520FA]'
: state.activeYear === 2022
? 'bg-[#8B59F7]'
: 'bg-[#C6ACFF]'
"
>
<div v-if="!isAnimating">{{ state.activeYear }}</div>
<div v-else>&nbsp;</div>
</div>
<div
class="bg-[#F8F9FF] ma-[6px] px-[25px] py-[30px] flex justify-between"
@ -151,13 +170,13 @@
<div>Q4</div>
</div>
<div class="bg-[#F8F9FF] ma-[6px] px-[25px] py-[30px]">
<div>2023</div>
<div>{{ state.activeYear }}</div>
</div>
<div class="bg-[#F8F9FF] ma-[6px] px-[25px] py-[30px]">
<div>2023</div>
<div>{{ state.activeYear }}</div>
</div>
<div class="bg-[#F8F9FF] ma-[6px] px-[25px] py-[30px]">
<div>2023</div>
<div>{{ state.activeYear }}</div>
</div>
</div>
</div>
@ -399,8 +418,233 @@ const state = reactive({
link: "",
},
],
activeYear: 2023,
});
//
const yearContent = ref(null);
//
const isAnimating = ref(false);
//
const slideDirection = ref("left"); //
//
const currentYearIndex = ref(0);
const yearArray = [2021, 2022, 2023];
//
const isPaused = ref(false);
const touchStartX = ref(0);
const mouseStartX = ref(0);
const isMouseDown = ref(false);
let interval = null;
let pauseTimeout = null;
//
const animateYearChange = (direction, targetYear) => {
if (!yearContent.value) return;
//
isAnimating.value = true;
const tl = gsap.timeline();
if (direction === "left") {
//
tl.to(yearContent.value, {
opacity: 0,
x: -50,
duration: 0.3,
ease: "power2.inOut",
})
.set(yearContent.value, {
x: 50,
})
.add(() => {
//
state.activeYear = targetYear;
})
.to(yearContent.value, {
opacity: 1,
x: 0,
duration: 0.3,
ease: "power2.out",
onComplete: () => {
//
isAnimating.value = false;
},
});
} else {
//
tl.to(yearContent.value, {
opacity: 0,
x: 50,
duration: 0.3,
ease: "power2.inOut",
})
.set(yearContent.value, {
x: -50,
})
.add(() => {
//
state.activeYear = targetYear;
})
.to(yearContent.value, {
opacity: 1,
x: 0,
duration: 0.3,
ease: "power2.out",
onComplete: () => {
//
isAnimating.value = false;
},
});
}
};
//
const startYearInterval = () => {
if (interval) clearInterval(interval);
interval = setInterval(() => {
if (!isPaused.value) {
nextYear();
}
}, 3000);
};
//
const nextYear = () => {
slideDirection.value = "left"; //
const nextIndex = (currentYearIndex.value + 1) % yearArray.length;
const nextYearValue = yearArray[nextIndex];
// activeYear
animateYearChange("left", nextYearValue);
//
currentYearIndex.value = nextIndex;
};
//
const prevYear = () => {
slideDirection.value = "right"; //
const prevIndex =
(currentYearIndex.value - 1 + yearArray.length) % yearArray.length;
const prevYearValue = yearArray[prevIndex];
// activeYear
animateYearChange("right", prevYearValue);
//
currentYearIndex.value = prevIndex;
};
//
const pauseYearInterval = () => {
isPaused.value = true;
};
//
const resumeYearInterval = () => {
isPaused.value = false;
};
//
const pauseForDuration = (duration = 3000) => {
pauseYearInterval();
//
if (pauseTimeout) {
clearTimeout(pauseTimeout);
}
//
pauseTimeout = setTimeout(() => {
resumeYearInterval();
}, duration);
};
//
const handleTouchStart = (event) => {
pauseYearInterval();
touchStartX.value = event.touches[0].clientX;
};
//
const handleTouchEnd = () => {
//
// resumeYearInterval();
};
//
const handleTouchMove = (event) => {
if (touchStartX.value === 0) return;
const touchEndX = event.touches[0].clientX;
const diffX = touchEndX - touchStartX.value;
//
if (Math.abs(diffX) > 50) {
if (diffX < 0) {
//
slideDirection.value = "left";
nextYear();
} else {
//
slideDirection.value = "right";
prevYear();
}
touchStartX.value = 0; //
//
pauseForDuration();
}
};
//
const handleMouseDown = (event) => {
isMouseDown.value = true;
mouseStartX.value = event.clientX;
pauseYearInterval();
};
//
const handleMouseUp = () => {
isMouseDown.value = false;
//
// resumeYearInterval();
};
//
const handleMouseMove = (event) => {
if (!isMouseDown.value || mouseStartX.value === 0) return;
const mouseEndX = event.clientX;
const diffX = mouseEndX - mouseStartX.value;
//
if (Math.abs(diffX) > 50) {
if (diffX < 0) {
//
slideDirection.value = "left";
nextYear();
} else {
//
slideDirection.value = "right";
prevYear();
}
mouseStartX.value = 0; //
//
pauseForDuration();
}
};
//
startYearInterval();
const carouselTrack = ref(null);
let carouselAnimation = null; // GSAP
@ -477,6 +721,12 @@ onUnmounted(() => {
if (carouselAnimation) {
carouselAnimation.kill();
}
if (interval) {
clearInterval(interval);
}
if (pauseTimeout) {
clearTimeout(pauseTimeout);
}
});
import { useRouter } from "vue-router";
@ -655,4 +905,10 @@ const handleLink = (url) => {
border-radius: 20px 0 0 20px;
}
}
//
.year-content-animation {
position: relative;
will-change: transform, opacity;
}
</style>