feat: 实现左右对比效果,原图和效果图各占一半

- 重新设计图片对比区域,实现左右分屏布局
- 原图展示在左半边,效果图展示在右半边,各占50%宽度
- 添加中央分割线和圆形交互手柄,带有左右箭头图标
- 标签位置调整到图片底部中央,使用毛玻璃效果
- 统一图片高度180px,确保视觉平衡和完美对比
- 保持圆角设计和阴影效果,提升视觉体验
- 更新设计预览文档,记录左右对比的实现细节
This commit is contained in:
杨明明 2025-09-03 17:30:32 +08:00
parent 68dc675e84
commit e37e7334cd
3 changed files with 83 additions and 54 deletions

View File

@ -1,8 +1,8 @@
# Home页面瀑布流设计预览 # Home页面瀑布流设计预览 - 左右对比版本
## 设计概述 ## 设计概述
我已经成功美化了home页面实现了瀑布流布局来展示模板数据的对比效果。以下是主要的设计改进: 我已经成功美化了home页面实现了瀑布流布局和左右对比效果来展示模板数据。以下是主要的设计改进:
## 🎨 设计特色 ## 🎨 设计特色
@ -11,11 +11,12 @@
- **响应式设计**在更大屏幕上自动调整为3列 - **响应式设计**在更大屏幕上自动调整为3列
- **自适应高度**:每个卡片根据内容自动调整高度 - **自适应高度**:每个卡片根据内容自动调整高度
### 2. 图片对比效果 ### 2. 左右对比效果 ⭐ **最新更新**
- **原图 → 效果图**:清晰展示处理前后的对比 - **左右分屏**原图展示左半边效果图展示右半边各占50%宽度
- **视觉箭头**:使用箭头图标突出转换过程 - **视觉分割线**:中间添加优雅的白色分割线,带有圆形交互手柄
- **标签标识**:原图和效果图都有清晰的标签标识 - **标签标识**:底部居中显示标签,原图蓝色,效果图绿色
- **圆角设计**:所有图片都采用圆角设计,更加现代 - **毛玻璃效果**标签使用backdrop-filter实现现代毛玻璃效果
- **完美对比**统一高度180px确保视觉平衡和对比效果
### 3. 卡片设计 ### 3. 卡片设计
- **渐变背景**:图片区域使用渐变背景增加层次感 - **渐变背景**:图片区域使用渐变背景增加层次感
@ -37,10 +38,10 @@ Home页面
│ └── 副标题:"选择模板,一键生成精美效果" │ └── 副标题:"选择模板,一键生成精美效果"
└── 瀑布流网格 └── 瀑布流网格
└── 模板卡片 × 6 └── 模板卡片 × 6
├── 图片对比区域 ├── 左右对比区域 ⭐ **新设计**
│ ├── 原图(带"原图"标签) │ ├── 左半边:原图(底部蓝色"原图"标签)
│ ├── 箭头指示 │ ├── 中央分割线:白色线条 + 圆形手柄(⟷图标)
│ └── 效果图(带"效果"标签) │ └── 右半边:效果图(底部绿色"效果"标签)
└── 信息区域 └── 信息区域
├── 模板名称 ├── 模板名称
├── 功能描述 ├── 功能描述

View File

@ -20,32 +20,39 @@
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.15); box-shadow: 0 8px 30px rgba(0, 0, 0, 0.15);
} }
/* 图片对比区域 */ /* 左右对比区域 */
.image-comparison { .image-comparison {
position: relative; position: relative;
padding: 16px; padding: 16px;
background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%); background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
} }
.image-container { .split-container {
position: relative; position: relative;
display: flex;
border-radius: 12px; border-radius: 12px;
overflow: hidden; overflow: hidden;
margin-bottom: 12px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
height: 180px;
} }
.input-container { .image-half {
margin-bottom: 8px; position: relative;
flex: 1;
overflow: hidden;
} }
.output-container { .left-half {
margin-bottom: 0; border-right: 1px solid rgba(255, 255, 255, 0.3);
}
.right-half {
border-left: 1px solid rgba(255, 255, 255, 0.3);
} }
.comparison-image { .comparison-image {
width: 100%; width: 100%;
height: 120px; height: 100%;
object-fit: cover; object-fit: cover;
display: block; display: block;
background: #f5f5f5; background: #f5f5f5;
@ -58,12 +65,14 @@
.image-label { .image-label {
position: absolute; position: absolute;
top: 8px; bottom: 8px;
left: 8px; left: 50%;
padding: 4px 8px; transform: translateX(-50%);
border-radius: 12px; padding: 4px 12px;
border-radius: 16px;
backdrop-filter: blur(10px); backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
white-space: nowrap;
} }
.input-label { .input-label {
@ -76,16 +85,31 @@
.label-text { .label-text {
color: #fff; color: #fff;
font-size: 11px; font-size: 12px;
font-weight: 600; font-weight: 600;
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3); text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
} }
.comparison-arrow { /* 分割线和拖拽手柄 */
.split-line {
position: absolute;
left: 50%;
top: 16px;
bottom: 16px;
width: 2px;
background: linear-gradient(to bottom,
rgba(255, 255, 255, 0.8) 0%,
rgba(255, 255, 255, 0.9) 50%,
rgba(255, 255, 255, 0.8) 100%);
transform: translateX(-50%);
z-index: 3;
}
.split-handle {
position: absolute; position: absolute;
right: 16px;
top: 50%; top: 50%;
transform: translateY(-50%); left: 50%;
transform: translate(-50%, -50%);
width: 32px; width: 32px;
height: 32px; height: 32px;
background: rgba(255, 255, 255, 0.95); background: rgba(255, 255, 255, 0.95);
@ -93,12 +117,12 @@
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); box-shadow: 0 2px 12px rgba(0, 0, 0, 0.15);
z-index: 2; border: 2px solid rgba(0, 122, 255, 0.2);
} }
.arrow-icon { .split-icon {
font-size: 16px; font-size: 14px;
color: #007AFF; color: #007AFF;
font-weight: bold; font-weight: bold;
} }

View File

@ -14,33 +14,37 @@ export default function TemplateCard({ template, onClick }: TemplateCardProps) {
return ( return (
<View className='template-card' onClick={handleClick}> <View className='template-card' onClick={handleClick}>
{/* 图片对比区域 */} {/* 左右对比区域 */}
<View className='image-comparison'> <View className='image-comparison'>
<View className='image-container input-container'> <View className='split-container'>
<Image <View className='image-half left-half'>
className='comparison-image' <Image
src={template.input} className='comparison-image'
mode='aspectFill' src={template.input}
lazyLoad mode='aspectFill'
/> lazyLoad
<View className='image-label input-label'> />
<Text className='label-text'></Text> <View className='image-label input-label'>
<Text className='label-text'></Text>
</View>
</View>
<View className='image-half right-half'>
<Image
className='comparison-image'
src={template.output}
mode='aspectFill'
lazyLoad
/>
<View className='image-label output-label'>
<Text className='label-text'></Text>
</View>
</View> </View>
</View> </View>
<View className='comparison-arrow'> <View className='split-line'>
<Text className='arrow-icon'></Text> <View className='split-handle'>
</View> <Text className='split-icon'></Text>
<View className='image-container output-container'>
<Image
className='comparison-image'
src={template.output}
mode='aspectFill'
lazyLoad
/>
<View className='image-label output-label'>
<Text className='label-text'></Text>
</View> </View>
</View> </View>
</View> </View>