Appearance
图层检测系统全面升级文档
概述
本文档详细记录了Eagle2Ae AE扩展中图层检测系统的全面升级,包括检测按钮功能优化、新增简化弹窗系统、模态对话框实现、文件夹操作功能独立化以及样式紧凑化等重要改进。
最新更新 (v2.3.0):
- ✅ 简化弹窗系统,移除复杂的导出和文件夹操作按钮
- ✅ 恢复模态弹窗形式,提升用户体验
- ✅ 文件夹打开功能独立保存为工具模块
- ✅ 弹窗界面紧凑化优化,减少占用空间
- ✅ 保持核心图层信息显示和悬浮提示功能
1. 检测图层按钮功能升级
1.1 核心功能增强
检测逻辑优化
- 视频文件识别: 扩展了视频文件格式支持,包括
.mp4,.mov,.avi,.mkv,.wmv,.flv,.webm,.mxf,.r3d等 - 图层类型分类: 明确区分图片素材、视频素材、序列帧等不同类型
- 导出原因说明: 为每种图层类型提供准确的导出状态说明
检测结果展示
``javascript // 检测结果数据结构 { exportable: true, reason: "视频素材,将导出第一帧", type: "VideoLayer", sourceInfo: { isVideo: true, fileName: "动画视频.mp4", // 其他源信息... } }
### 1.2 用户界面改进
#### 检测按钮交互
- **即时反馈**: 点击检测按钮后立即显示加载状态
- **进度指示**: 显示检测进度和当前处理的图层
- **结果预览**: 检测完成后自动弹出总结对话框
#### 状态指示器
| 状态 | 图标 | 颜色 | 说明 |
|------|------|------|------|
| 可导出 | ✓ | 绿色 | 图层可以正常导出 |
| 不可导出 | ✗ | 红色 | 图层无法导出(如序列帧) |
| 视频文件 | 🎬 | 蓝色 | 视频素材,将导出第一帧 |
| 纯色图层 | ⬜ | 灰色 | 纯色或文本图层 |
## 2. HTML模态对话框架构 (v2.3.0)
### 2.1 架构变更:从JSX到HTML
为统一真实环境与Demo模式下的视觉体验,总结对话框的实现已从AE原生JSX窗口重构为在CEP面板内部渲染的HTML模态对话框。
- **文件位置**: `Eagle2Ae-Ae/js/ui/summary-dialog.js`
- **适用环境**: After Effects CEP扩展环境。
- **弹窗类型**: HTML/CSS/JS 模态对话框。
- **特性**: 现代深色主题,样式统一,紧凑布局,通过DOM元素动态创建。
- **调用方式**: 在`main.js`中,当`detectLayers()`获取到JSX分析结果后,实例化并调用`SummaryDialog.prototype.show()`方法。
```javascript
// main.js (示意)
async detectLayers() {
// ... 调用 hostscript.jsx 获取 detectionResults
const detectionResults = await this.executeExtendScript(...);
// 调用新的HTML对话框
const dialog = new SummaryDialog();
dialog.show(detectionResults);
}2.2 简化内容结构与全新交互
总结信息区域 (两行式总结 + 悬浮提示)
为了使界面更紧凑,总结信息区域现在默认只显示两行核心信息:
- 可导出图层的分类统计
- 不可导出图层的分类统计
完整的第三行总结信息(包含检测的图层总数、可导出总数、不可导出总数)并未移除,而是作为悬浮提示 (Tooltip) 功能提供。将鼠标悬停在该总结区域上,即可查看完整的统计详情。
显示示例:
▶ 可导出: 文本:2, 形状:1
✖ 不可导出: 设计:3, 视频:6, 纯色:1
(当鼠标悬停时,会浮现提示: "总结: 共检测 13 个图层,3 个可导出,10 个不可导出")这个改动有效地提升了信息密度和界面的整洁度。
图层详情区域(交互重构)
- 无行内按钮: 列表中的每一行都移除了旧版的“导出(▶)”和“打开文件夹(📁)”按钮,界面更干净。
- 纯信息显示: 每行只显示图层状态、分类和名称。
图层分类显示
图层名称前会根据其类型显示一个分类标签,帮助用户快速识别,例如:
[√]【文本】: 可导出的文本图层。[×]【视频】: 不可导出的视频素材。[√]【设计】: 可导出的设计文件 (如.psd)。[√]【合成】: 可导出的预合成。
分类逻辑由 hostscript.jsx 中的 analyzeLayer 函数决定,确保了识别的准确性。
全新的点击交互
现在通过直接点击图层名称的文本来执行操作,具体行为根据图层类型有所不同:
打开文件夹:
- 适用类型: 普通素材文件(如图片、视频、音频等)。
- 操作: 点击这些图层的名称,会调用
jsx/utils/folder-opener.js模块的功能,直接在你的操作系统中打开该素材文件所在的文件夹。
导出图层/合成:
- 适用类型: 设计文件 (如
.psd)、预合成、或普通合成。 - 操作: 点击后会触发单帧导出。对于图层,会渲染该图层;对于合成,则会导出其当前时间点的画面。
- 适用类型: 设计文件 (如
显示详细信息:
- 适用类型: 无法执行上述操作的图层(如纯色、形状图层)或操作失败时。
- 操作: 点击后会弹出一个小窗口,展示该图层的详细信息(与鼠标悬停提示内容相同)。
特殊情况处理
除了基本的分类和交互,检测逻辑还包含对以下特殊情况的处理:
序列帧检测: 系统会自动通过文件名规律(如
file_00001.png)和素材时长来识别图像序列。识别出的图像序列会被标记为不可导出,并提示“序列帧暂不支持导出”。图层蒙版处理: 对带有蒙版(Mask)的图层处理规则如下:
- 对于素材文件图层(如图片、视频),即使有蒙版,通常仍可导出。
- 对于形状或文本图层,一旦添加了蒙版,该图层将变为不可导出。
操作按钮区域
- 确定/关闭: 保留了底部的“确定”和“关闭”按钮,用于关闭对话框。
- 键盘支持: 支持Enter确认,Esc取消。
3. 文件夹操作功能独立化 (v2.3.0)
3.1 独立模块设计
模块文件位置
- 文件路径:
Eagle2Ae-Ae/jsx/utils/folder-opener.js - 模块类型: 独立工具模块
- 依赖关系: 无外部依赖,纯 JSX 实现
- 兼容性: ExtendScript 环境原生支持
核心功能函数
``javascript /**
- 文件夹打开工具函数
- 从 dialog-summary.jsx 中提取的打开文件夹功能 */
// 1. 主要入口函数 function openLayerFolder(layer)
// 2. 直接路径打开 function openFolderByFilePath(filePath)
// 3. URI解码工具 function decodeStr(str)
// 4. JSX原生打开方法 function openFolderWithJSX(folderPath)
### 3.2 功能特性
#### URI解码支持
``javascript
/**
* 解码 URI 编码的字符串的函数
* 参考7zhnegli3.jsx脚本中的编解码功能
* @param {string} str - 需要解码的字符串
* @returns {string} 解码后的字符串,失败时返回原字符串
*/
function decodeStr(str) {
try {
return decodeURIComponent(str);
} catch(e) {
return str;
}
}中文路径支持
- 编码处理: 自动检测和处理URI编码问题
- 路径验证: 检查解码后是否包含乱码字符
- 错误提示: 提供详细的解决方案指导
JSX原生实现
``javascript /**
- 使用JSX原生Folder对象打开文件夹
- 参考7zhnegli3.jsx脚本中的outputFolder.execute()方法
- @param {string} folderPath - 文件夹路径
- @returns {boolean} 是否成功打开 */ function openFolderWithJSX(folderPath) { try { var targetFolder = new Folder(folderPath); if (!targetFolder.exists) { return false; } return targetFolder.execute(); } catch (error) { return false; } }
### 3.3 调用方式
#### 引入模块// 在需要使用文件夹功能的脚本中引入 #include "utils/folder-opener.js"
// 或者使用相对路径 #include "jsx/utils/folder-opener.js"
#### 使用示例// 1. 通过图层对象打开文件夹 var layer = { name: "图片素材.jpg", tooltipInfo: { originalPath: "C:/Projects/Images/图片素材.jpg" } }; openLayerFolder(layer);
// 2. 直接通过文件路径打开 openFolderByFilePath("C:/Projects/Images/图片素材.jpg");
// 3. 只需URI解码 var decodedPath = decodeStr("%E5%9B%BE%E7%89%87%E7%B4%A0%E6%9D%90");
### 3.4 错误处理
#### 路径检测机制// 检查解码后的路径是否仍包含编码问题 if (decodedPath.indexOf('?') !== -1) { alert('❌ 路径编码错误\n\n解决方法:\n' + '1. 重命名文件,避免特殊字符\n' + '2. 检查系统区域和语言设置\n' + '3. 将文件移动到简单路径下'); return; }
#### 备用方案
- **Explorer.exe调用**: JSX方法失败时的备用方案
- **手动路径显示**: 自动打开失败时显示路径供用户手动操作
- **详细日志**: 记录所有操作步骤和错误信息
## 4. 紧凑化布局优化 (v2.3.0)
### 4.1 尺寸优化策略
#### 整体尺寸减小// 原始尺寸 vs 紧凑尺寸 const sizeComparison = { dialog: { width: { before: 450, after: 380, reduction: '70px (-15.6%)' }, height: { before: 350, after: 280, reduction: '70px (-20%)' } }, layerDetails: { height: { before: 180, after: 120, reduction: '60px (-33.3%)' } }, buttons: { width: { before: 80, after: 70, reduction: '10px (-12.5%)' }, height: { before: 25, after: 22, reduction: '3px (-12%)' } } };
#### 间距优化// 间距调整对比 const spacingOptimization = { dialog: { spacing: { before: 8, after: 5 }, margins: { before: 12, after: 8 } }, summaryPanel: { spacing: { before: 3, after: 2 }, margins: { before: 8, after: 6 } }, layerDetails: { spacing: { before: 2, after: 1 }, margins: { before: 8, after: 6 } }, buttonGroup: { spacing: { before: 10, after: 8 } } };
### 4.2 内容区域优化
#### 文本宽度调整// 文本区域宽度优化 const textWidthOptimization = { summaryText: { before: 420, after: 360, reduction: '60px' }, layerText: { before: 420, after: 330, reduction: '90px' }, layerRow: { before: 400, after: 340, reduction: '60px' } };
#### 布局结构简化// 紧凑布局实现 function addLayerRowWithButtons(parent, layer, canExport) { var layerRow = parent.add('group'); layerRow.orientation = 'row'; layerRow.alignChildren = 'left'; layerRow.spacing = 3; // 减少从 5 layerRow.preferredSize.width = 340; // 减少从 400
var layerText = formatLayerText(layer, canExport);
var layerLabel = layerRow.add('statictext', undefined, layerText);
layerLabel.preferredSize.width = 330; // 紧凑版宽度
// 移除所有按钮功能,简化界面
addLayerTooltip(layerLabel, layer, canExport);
}
### 4.3 视觉效果对比
#### 占用空间减少原始版本: 450px × 350px = 157,500 像素 紧凑版本: 380px × 280px = 106,400 像素 空间减少: 51,100 像素 (-32.4%)
#### 用户体验提升
- **更少遮挡**: 弹窗对AE界面的遮挡更少
- **更快浏览**: 紧凑的布局使信息更集中
- **更优整体**: 整体视觉体验更加精致
### 4.4 响应式考量
#### 小屏幕适配// 小屏幕环境下的进一步紧凑化 if (screenWidth < 1366) { dialog.preferredSize.width = 320; // 进一步减小 dialog.preferredSize.height = 240; }
#### 高DPI支持// 高DPI环境下的尺寸调整 if (screenDPI > 144) { const scaleFactor = screenDPI / 96; dialog.preferredSize.width *= scaleFactor; dialog.preferredSize.height *= scaleFactor; }
## 5. 简化功能架构 (v2.3.0)
### 5.1 功能精简策略
#### 移除的复杂功能
- **导出图层按钮**: 移除了复杂的单图层导出功能
- **文件夹操作按钮**: 移除了直接的文件夹打开按钮
- **扩展功能按钮**: 移除了预留的扩展功能
- **非模态窗口**: 移除了复杂的非模态窗口实现
#### 保留的核心功能
- **信息显示**: 保持完整的图层信息展示
- **悬浮提示**: 保留图层详情的悬浮提示功能
- **统计总结**: 保持三行总结信息显示
- **模态交互**: 恢复简洁的模态对话框体验
### 5.2 代码简化成果
#### 代码行数减少// 代码优化统计 const codeOptimization = { originalLines: 1592, currentLines: 679, reduction: 913, percentage: '-57.3%' };
// 移除的主要函数 const removedFunctions = [ 'isDesignFile', // 设计文件判断 'isMaterialFile', // 素材文件判断
'addExportButton', // 导出按钮 'addOpenFolderButton', // 文件夹按钮 'exportSingleLayer', // 单图层导出 'createExportFolder', // 导出文件夹创建 'validateOutputFile', // 输出文件验证 // ... 等等约20个复杂函数 ];
#### 性能提升
- **加载速度**: 代码减少约57%,加载更快
- **内存占用**: 移除复杂逻辑,内存使用更少
- **响应速度**: 简化界面,用户交互更流畅
## 6. 技术实现细节
### 6.1 检测流程优化
#### 异步检测处理// 异步图层检测实现 async function detectLayersAsync() { try { showLoadingIndicator('正在检测图层...');
const script = 'analyzeAllLayers();';
const result = await executeExtendScript(script);
const layerData = JSON.parse(result);
// 显示检测结果
showDetectionSummaryDialog(layerData);
} catch (error) {
console.error('[图层检测] 检测失败:', error);
showErrorDialog('图层检测失败,请重试');
} finally {
hideLoadingIndicator();
}
}
#### 错误处理机制// 检测错误处理 function handleDetectionError(error) { const errorMessages = { 'NO_PROJECT': '请先打开一个AE项目', 'NO_COMPOSITION': '请选择一个合成', 'NO_LAYERS': '当前合成中没有图层', 'SCRIPT_ERROR': 'ExtendScript执行错误' };
const message = errorMessages[error.code] || '检测过程中发生未知错误';
showErrorDialog(message);
}
### 6.2 性能优化策略
#### 懒加载实现// Demo组件懒加载 class DemoModeManager { async loadComponent(componentName) { if (!this.components[componentName]) { const module = await import(./demo-${componentName}.js); this.components[componentName] = new module.default(); } return this.components[componentName]; } }
#### 内存管理// 弹窗资源清理 function cleanupDialog(dialog) { // 移除事件监听器 dialog.removeEventListener('click', handleDialogClick); dialog.removeEventListener('keydown', handleDialogKeydown);
// 从DOM中移除
if (dialog.parentNode) {
dialog.parentNode.removeChild(dialog);
}
// 清理引用
dialog = null;
}
## 7. 测试和验证
### 7.1 功能测试清单
#### 检测功能测试
- [ ] 图片文件正确识别为可导出
- [ ] 视频文件正确识别并标注"将导出第一帧"
- [ ] 序列帧正确识别为不可导出
- [ ] 纯色图层正确识别
- [ ] 文本图层正确识别
- [ ] 混合图层类型正确分类
#### 弹窗功能测试
- [ ] CEP环境下JSX弹窗正常显示
- [ ] Demo模式下JavaScript弹窗正常显示
- [ ] 弹窗内容数据准确显示
- [ ] 按钮交互功能正常
- [ ] 键盘快捷键支持
- [ ] 弹窗关闭功能正常
#### Demo模式测试
- [ ] Web环境自动启用Demo模式
- [ ] CEP环境彩蛋触发功能
- [ ] 虚拟数据正确生成
- [ ] 网络请求正确拦截
- [ ] 样式与CEP环境一致
### 7.2 兼容性测试
#### 浏览器兼容性
- [ ] Chrome 80+
- [ ] Firefox 75+
- [ ] Safari 13+
- [ ] Edge 80+
#### AE版本兼容性
- [ ] After Effects CC 2018
- [ ] After Effects CC 2019
- [ ] After Effects CC 2020
- [ ] After Effects 2021
- [ ] After Effects 2022+
### 7.3 性能测试
#### 检测性能
- 小项目(<10图层):< 1秒
- 中项目(10-50图层):< 3秒
- 大项目(50+图层):< 10秒
#### 弹窗性能
- 弹窗显示延迟:< 200ms
- 内容渲染时间:< 500ms
- 内存占用:< 10MB
## 8. 故障排除指南
### 8.1 常见问题解决
#### 检测按钮无响应
**症状**: 点击检测按钮后无任何反应
**可能原因**:
1. ExtendScript脚本加载失败
2. AE项目未打开或无合成
3. CSInterface通信异常
**解决方案**:// 诊断脚本 function diagnoseDetectionIssue() { // 检查CSInterface if (typeof csInterface === 'undefined') { console.error('CSInterface未初始化'); return; }
// 检查AE连接
csInterface.evalScript('app.project.name', (result) => {
if (!result) {
console.error('无法获取AE项目信息');
}
});
}
#### Demo模式弹窗样式异常
**症状**: Demo模式下弹窗样式与CEP环境不一致
**解决方案**:
1. 检查CSS样式是否正确加载
2. 验证颜色值和字体设置
3. 确认布局结构完整性
#### 虚拟数据显示错误
**症状**: Demo模式下显示的数据不正确或格式异常
**解决方案**:
1. 检查demo-config.json配置文件
2. 验证数据生成逻辑
3. 确认统计计算准确性
### 8.2 调试工具和方法
#### 调试模式启用// 启用详细调试日志 window.DEBUG_MODE = true; window.DEMO_DEBUG = true;
// 查看Demo模式状态 console.log('Demo模式状态:', window.demoMode?.state);
// 查看拦截统计 console.log('拦截统计:', window.demoMode?.networkInterceptor?.getStats());
#### 性能监控// 检测性能监控 function monitorDetectionPerformance() { const startTime = performance.now();
detectLayersAsync().then(() => {
const endTime = performance.now();
console.log(`检测耗时: ${endTime - startTime}ms`);
});
}
## 9. 未来发展规划
### 9.1 功能扩展计划
#### 检测功能增强
- [ ] 支持更多图层类型检测
- [ ] 添加图层依赖关系分析
- [ ] 实现批量操作建议
- [ ] 增加导出质量预估
#### 弹窗系统优化
- [ ] 支持自定义弹窗主题
- [ ] 添加弹窗动画效果
- [ ] 实现弹窗内容搜索
- [ ] 支持弹窗内容导出
#### Demo模式完善
- [ ] 增加更多演示场景
- [ ] 支持自定义虚拟数据
- [ ] 添加交互式教程
- [ ] 实现演示录制功能
### 9.2 技术架构优化
#### 模块化重构
- 将检测逻辑抽象为独立模块
- 实现弹窗系统的插件化架构
- 优化Demo模式的组件结构
#### 性能优化
- 实现检测结果缓存机制
- 优化大项目的检测性能
- 减少内存占用和提升响应速度
## 10. 版本历史
### v2.3.0 (当前版本) - 简化与紧凑化版本
- ✅ **简化弹窗系统**: 移除复杂的导出和文件夹操作按钮
- ✅ **恢复模态弹窗**: 从非模态改回模态形式,提升用户体验
- ✅ **文件夹功能独立化**: 保存到 `folder-opener.js` 独立模块
- ✅ **紧凑化布局**: 弹窗尺寸从450×350减少到380×280
- ✅ **代码简化**: 移除~57%代码,从1592行减少到679行
- ✅ **性能优化**: 加载速度和响应性能显著提升
- ✅ **保持核心功能**: 图层信息显示和悬浮提示功能完整保留
### v2.2.0 (上一版本)
- ✅ 新增图层检测总结弹窗功能
- ✅ 实现Demo模式虚拟弹窗系统
- ✅ 优化弹窗样式与CEP环境一致性
- ✅ 修复文件名后缀重复问题
- ✅ 增强视频文件检测逻辑
### v2.1.2
- ✅ 扩展视频文件格式支持
- ✅ 优化图层类型检测逻辑
- ✅ 修复视频文件导出第一帧问题
### v2.1.0
- ✅ 基础图层检测功能
- ✅ 简单的检测结果显示
- ✅ 基本的错误处理机制
---
**文档维护**: Eagle2Ae开发团队
**最后更新**: 2025-01-12
**版本**: v2.3.0 - 简化与紧凑化版本
**状态**: 已发布