bw-mini-app/src/components/TemplateCard/index.tsx

153 lines
4.4 KiB
TypeScript

import { View, Text, Image } from '@tarojs/components'
import { useState, useRef } from 'react'
import Taro from '@tarojs/taro'
import { Template } from '../../store/types'
import './index.css'
interface TemplateCardProps {
template: Template
onClick: (template: Template) => void
}
export default function TemplateCard({ template, onClick }: TemplateCardProps) {
const [splitPosition, setSplitPosition] = useState(50) // 分割线位置百分比
const [isDragging, setIsDragging] = useState(false)
const [containerInfo, setContainerInfo] = useState<any>(null)
const containerRef = useRef<any>(null)
const handleClick = () => {
if (!isDragging) {
onClick(template)
}
}
// 获取容器信息
const getContainerInfo = () => {
return new Promise((resolve) => {
const query = Taro.createSelectorQuery()
query.select('.merged-image-container').boundingClientRect((rect) => {
if (rect) {
setContainerInfo(rect)
resolve(rect)
}
}).exec()
})
}
// 处理触摸开始
const handleTouchStart = async (e: any) => {
e.stopPropagation()
setIsDragging(true)
// 获取容器信息用于后续计算
await getContainerInfo()
}
// 处理触摸移动
const handleTouchMove = (e: any) => {
if (!isDragging || !containerInfo) return
e.stopPropagation()
const touch = e.touches[0]
if (!touch) return
// 计算触摸点相对于容器的位置
const touchX = touch.clientX - containerInfo.left
const percentage = Math.max(10, Math.min(90, (touchX / containerInfo.width) * 100))
setSplitPosition(percentage)
}
// 处理触摸结束
const handleTouchEnd = (e: any) => {
e.stopPropagation()
setTimeout(() => setIsDragging(false), 100) // 延迟重置,避免触发点击
}
return (
<View className='template-card' onClick={handleClick}>
{/* 合成对比图片区域 */}
<View className='image-comparison'>
<View
className='merged-image-container'
ref={containerRef}
onTouchMove={handleTouchMove}
onTouchEnd={handleTouchEnd}
>
{/* 左半部分 - 原图的左半部分 */}
<View
className='image-half left-half'
style={{ width: `${splitPosition}%` }}
>
<Image
className='comparison-image left-image'
src={template.input}
mode='aspectFill'
lazyLoad
/>
</View>
{/* 右半部分 - 效果图的右半部分 */}
<View
className='image-half right-half'
style={{ width: `${100 - splitPosition}%` }}
>
<Image
className='comparison-image right-image'
src={template.output}
mode='aspectFill'
lazyLoad
/>
</View>
{/* 可拖拽的分割线 */}
<View
className='split-line'
style={{ left: `${splitPosition}%` }}
onTouchStart={handleTouchStart}
onTouchMove={handleTouchMove}
onTouchEnd={handleTouchEnd}
>
<View className='split-handle'>
<Text className='split-icon'></Text>
</View>
</View>
{/* 动态标签 */}
<View className='image-labels'>
<View
className='label-left input-label'
style={{ width: `${splitPosition}%` }}
>
<Text className='label-text'></Text>
</View>
<View
className='label-right output-label'
style={{ width: `${100 - splitPosition}%` }}
>
<Text className='label-text'></Text>
</View>
</View>
</View>
</View>
{/* 模板信息 */}
<View className='template-info'>
<Text className='template-name'>{template.name}</Text>
<Text className='template-desc'>{template.description}</Text>
<View className='template-meta'>
<View className='tags-container'>
{template.tags.map((tag, index) => (
<Text key={index} className='template-tag'>
{tag}
</Text>
))}
</View>
<View className='credit-cost'>
<Text className='cost-text'>{template.creditCost}</Text>
</View>
</View>
</View>
</View>
)
}