153 lines
4.4 KiB
TypeScript
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>
|
|
)
|
|
} |