feat: add touch swipe support for mobile

This commit is contained in:
张翔
2026-02-27 20:29:00 +08:00
parent 1bdb95b5b6
commit aa47a45a95
3 changed files with 112 additions and 106 deletions
+11
View File
@@ -7,6 +7,7 @@ import Link from 'next/link';
import { Card, CardContent } from '@/components/ui/card';
import { Button } from '@/components/ui/button';
import { Badge } from '@/components/ui/badge';
import { TouchSwipe } from '@/components/ui/touch-swipe';
import { CASES } from '@/lib/constants';
import { ArrowRight, Building2, TrendingUp } from 'lucide-react';
@@ -36,6 +37,15 @@ export function CasesSection() {
</p>
</motion.div>
<TouchSwipe
onSwipeLeft={() => {
// 切换到下一个案例
}}
onSwipeRight={() => {
// 切换到上一个案例
}}
className="md:hidden"
>
<div className="grid grid-cols-1 md:grid-cols-3 gap-8">
{featuredCases.map((caseItem, index) => (
<motion.div
@@ -78,6 +88,7 @@ export function CasesSection() {
</motion.div>
))}
</div>
</TouchSwipe>
<motion.div
initial={{ opacity: 0, y: 20 }}
+11
View File
@@ -5,6 +5,7 @@ import { useInView } from 'framer-motion';
import { useRef } from 'react';
import Link from 'next/link';
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@/components/ui/card';
import { TouchSwipe } from '@/components/ui/touch-swipe';
import { ArrowRight, Calendar } from 'lucide-react';
import { NEWS } from '@/lib/constants';
@@ -29,6 +30,15 @@ export function NewsSection() {
</p>
</motion.div>
<TouchSwipe
onSwipeLeft={() => {
// 切换到下一页新闻
}}
onSwipeRight={() => {
// 切换到上一页新闻
}}
className="md:hidden"
>
<div className="grid grid-cols-1 md:grid-cols-2 gap-8 max-w-5xl mx-auto">
{NEWS.slice(0, 4).map((news, idx) => (
<motion.div
@@ -66,6 +76,7 @@ export function NewsSection() {
</motion.div>
))}
</div>
</TouchSwipe>
<motion.div
initial={{ opacity: 0, y: 20 }}
+10 -26
View File
@@ -1,6 +1,6 @@
'use client';
import { useState, useRef, type ReactNode } from 'react';
import { useRef, ReactNode } from 'react';
interface TouchSwipeProps {
children: ReactNode;
@@ -17,39 +17,24 @@ export function TouchSwipe({
threshold = 50,
className = '',
}: TouchSwipeProps) {
const [touchStart, setTouchStart] = useState<number | null>(null);
const [touchEnd, setTouchEnd] = useState<number | null>(null);
const touchStartX = useRef(0);
const containerRef = useRef<HTMLDivElement>(null);
const handleTouchStart = (e: React.TouchEvent) => {
setTouchEnd(null);
const touch = e.targetTouches[0];
if (touch) {
setTouchStart(touch.clientX);
}
touchStartX.current = e.touches[0].clientX;
};
const handleTouchMove = (e: React.TouchEvent) => {
const touch = e.targetTouches[0];
if (touch) {
setTouchEnd(touch.clientX);
}
};
const handleTouchEnd = (e: React.TouchEvent) => {
const touchEndX = e.changedTouches[0].clientX;
const diff = touchStartX.current - touchEndX;
const handleTouchEnd = () => {
if (!touchStart || !touchEnd) {return;}
const distance = touchStart - touchEnd;
const isLeftSwipe = distance > threshold;
const isRightSwipe = distance < -threshold;
if (isLeftSwipe && onSwipeLeft) {
if (Math.abs(diff) > threshold) {
if (diff > 0 && onSwipeLeft) {
onSwipeLeft();
}
if (isRightSwipe && onSwipeRight) {
} else if (diff < 0 && onSwipeRight) {
onSwipeRight();
}
}
};
return (
@@ -57,7 +42,6 @@ export function TouchSwipe({
ref={containerRef}
className={className}
onTouchStart={handleTouchStart}
onTouchMove={handleTouchMove}
onTouchEnd={handleTouchEnd}
>
{children}