说明文档更新
This commit is contained in:
@@ -0,0 +1,299 @@
|
||||
<template>
|
||||
<div v-if="show" class="help-overlay" role="presentation" @click.self="close">
|
||||
<section class="help-dialog" role="dialog" aria-modal="true" aria-labelledby="help-title">
|
||||
<header class="help-head">
|
||||
<div>
|
||||
<h2 id="help-title">使用说明</h2>
|
||||
<p>从创建粒子到保存、导出的快速入门</p>
|
||||
</div>
|
||||
<button class="help-close" aria-label="关闭使用说明" title="关闭 (Esc)" @click="close">✕</button>
|
||||
</header>
|
||||
|
||||
<div class="help-body">
|
||||
<section class="help-section help-start">
|
||||
<h3>快速开始</h3>
|
||||
<ol>
|
||||
<li><b>创建对象:</b>在左侧“场景对象”中用 +粒子 / +碰撞 / +路径 / +Spine 添加场景对象。</li>
|
||||
<li><b>编辑粒子:</b>选中某个粒子系统,依次调整“发射模式 → 发射器形状 → 粒子属性 → 外观与资源 → 修改器”。</li>
|
||||
<li><b>查看效果:</b>底部时间轴可播放、暂停、逐帧或拖动;修改任意参数后会自动重新计算。</li>
|
||||
<li><b>保存与导出:</b>用“保存配置”保留工程;“导出 Spine Json / images 包 / .spine 包”输出成品。</li>
|
||||
</ol>
|
||||
<p class="help-note">每个模块组标题右侧的“重置”可把该组参数恢复默认;系统设置会自动保存在当前浏览器。</p>
|
||||
</section>
|
||||
|
||||
<div class="help-grid">
|
||||
<section class="help-section">
|
||||
<h3>常用操作</h3>
|
||||
<dl class="help-list">
|
||||
<div><dt>小眼睛</dt><dd>单独显示/隐藏对象;隐藏的粒子系统不会被导出。</dd></div>
|
||||
<div><dt>+Copy</dt><dd>完整复制当前选中对象,方便对比不同参数。</dd></div>
|
||||
<div><dt>背景图</dt><dd>上传参考图并调整位置和透明度,只用于画布预览。</dd></div>
|
||||
<div><dt>系统设置</dt><dd>管理界面布局、辅助显示、刻度等,自动存入浏览器。</dd></div>
|
||||
<div><dt>撤销/重做</dt><dd>Ctrl+Z 撤回一步;可达成的步数在系统设置中调整。</dd></div>
|
||||
<div><dt>Spine 骨骼</dt><dd>在层级树搜索并选择骨骼,可用于粒子发射器跟随。</dd></div>
|
||||
</dl>
|
||||
</section>
|
||||
|
||||
<section class="help-section">
|
||||
<h3>快捷键</h3>
|
||||
<div class="shortcut-list">
|
||||
<div><kbd>Ctrl/⌘</kbd><span>+</span><kbd>Z</kbd><em>撤回上一步</em></div>
|
||||
<div><kbd>Ctrl/⌘</kbd><span>+</span><kbd>S</kbd><em>保存配置</em></div>
|
||||
<div><kbd>Q</kbd><em>拖动画布</em></div>
|
||||
<div><kbd>W</kbd><em>位移工具</em></div>
|
||||
<div><kbd>E</kbd><em>旋转工具</em></div>
|
||||
<div><kbd>R</kbd><em>缩放工具</em></div>
|
||||
<div><kbd>D</kbd><em>播放 / 暂停</em></div>
|
||||
<div><kbd>S</kbd><em>回到第一帧</em></div>
|
||||
</div>
|
||||
<p class="help-note">Q / W / E / R 需先点击画布;光标位于输入框时,单键快捷键不会触发。</p>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="help-doc-title">功能模块详解</div>
|
||||
|
||||
<section class="help-section help-module" :class="{ open: openModules[0] }">
|
||||
<button type="button" class="help-module-head" :aria-expanded="openModules[0] ? 'true' : 'false'" @click="openModules[0] = !openModules[0]">
|
||||
<span class="mnum">1</span><span class="mtitle">配置管理</span><span class="caret">{{ openModules[0] ? '▾' : '▸' }}</span>
|
||||
</button>
|
||||
<div v-show="openModules[0]" class="help-module-body">
|
||||
<dl class="help-list">
|
||||
<div><dt>保存配置</dt><dd>把当前全部场景对象和参数保存为工程 JSON 文件(也支持 Ctrl+S)。</dd></div>
|
||||
<div><dt>加载配置</dt><dd>选择本地配置文件,恢复完整工程。</dd></div>
|
||||
<div><dt>预设</dt><dd>从下拉中选择已保存的预设快速套用;点击下拉即可刷新列表。</dd></div>
|
||||
<div><dt>范围</dt><dd>配置只含对象与参数,不含“系统设置”;系统设置单独存于浏览器。</dd></div>
|
||||
</dl>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="help-section help-module" :class="{ open: openModules[1] }">
|
||||
<button type="button" class="help-module-head" :aria-expanded="openModules[1] ? 'true' : 'false'" @click="openModules[1] = !openModules[1]">
|
||||
<span class="mnum">2</span><span class="mtitle">场景对象</span><span class="caret">{{ openModules[1] ? '▾' : '▸' }}</span>
|
||||
</button>
|
||||
<div v-show="openModules[1]" class="help-module-body">
|
||||
<dl class="help-list">
|
||||
<div><dt>粒子</dt><dd>核心对象。可设名称、位置 X/Y、偏移、旋转、缩放 X/Y,以及“随机种子”——相同种子可精确复现同一次效果。</dd></div>
|
||||
<div><dt>碰撞</dt><dd>圆形/椭圆/矩形/多边形/自定义;启用开关、碰撞响应(物理弹跳/暂停/销毁)、弹性与摩擦,还可沿某条路径移动并带进度曲线。</dd></div>
|
||||
<div><dt>路径</dt><dd>贝塞尔路径,可双击新建/删除锚点、拖手柄调曲线;内置圆/方/多边形/星形预设,支持闭合与颜色。</dd></div>
|
||||
<div><dt>Spine</dt><dd>加载 .json+.atlas+.png 预览骨骼动画,可查看/搜索骨骼层级树,用于粒子“发射器跟随”。</dd></div>
|
||||
<div><dt>通用</dt><dd>每个对象都有小眼睛显隐;“+Copy”可以复制当前对象;隐藏的粒子系统不会进入导出。</dd></div>
|
||||
</dl>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="help-section help-module" :class="{ open: openModules[2] }">
|
||||
<button type="button" class="help-module-head" :aria-expanded="openModules[2] ? 'true' : 'false'" @click="openModules[2] = !openModules[2]">
|
||||
<span class="mnum">3</span><span class="mtitle">发射模式</span><span class="caret">{{ openModules[2] ? '▾' : '▸' }}</span>
|
||||
</button>
|
||||
<div v-show="openModules[2]" class="help-module-body">
|
||||
<dl class="help-list">
|
||||
<div><dt>持续</dt><dd>按“每秒发射数量”持续喷射;再分“常规持续”(发射时长)与“循环持续”(三段式:开始循环 / 纯循环 / 结束循环,可自动或自定义帧长,做到无缝衔接)。</dd></div>
|
||||
<div><dt>爆发</dt><dd>一次性发射“单次数量”颗粒子。</dd></div>
|
||||
<div><dt>延迟时间</dt><dd>粒子条左端位置,表示发射开始前的等待时间。</dd></div>
|
||||
<div><dt>注意</dt><dd>循环持续模式不支持骨骼跟随和路径跟随;开关时会把跟随设置恢复默认。</dd></div>
|
||||
</dl>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="help-section help-module" :class="{ open: openModules[3] }">
|
||||
<button type="button" class="help-module-head" :aria-expanded="openModules[3] ? 'true' : 'false'" @click="openModules[3] = !openModules[3]">
|
||||
<span class="mnum">4</span><span class="mtitle">发射器形状</span><span class="caret">{{ openModules[3] ? '▾' : '▸' }}</span>
|
||||
</button>
|
||||
<div v-show="openModules[3]" class="help-module-body">
|
||||
<dl class="help-list">
|
||||
<div><dt>形状</dt><dd>点 / 圆形 / 矩形 / 锥形 / 路径。</dd></div>
|
||||
<div><dt>圆·锥</dt><dd>内半径与外半径,形成环形或锥形发射区;锥形额外有“锥形朝向”和“开口角度”。</dd></div>
|
||||
<div><dt>矩形</dt><dd>“外框 − 内框”形成环带,可分别设置内外宽高。</dd></div>
|
||||
<div><dt>路径</dt><dd>选一条场景路径作为出生线;出生分布可选等距固定或随机。</dd></div>
|
||||
<div><dt>发射角度</dt><dd>固定 / 随机(基准角度 + 随机范围)/ 径向(圆、矩、锥中心向外)/ 垂直于路径 / 沿路径方向。</dd></div>
|
||||
</dl>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="help-section help-module" :class="{ open: openModules[4] }">
|
||||
<button type="button" class="help-module-head" :aria-expanded="openModules[4] ? 'true' : 'false'" @click="openModules[4] = !openModules[4]">
|
||||
<span class="mnum">5</span><span class="mtitle">粒子属性</span><span class="caret">{{ openModules[4] ? '▾' : '▸' }}</span>
|
||||
</button>
|
||||
<div v-show="openModules[4]" class="help-module-body">
|
||||
<dl class="help-list">
|
||||
<div><dt>初始参数</dt><dd>生命周期、速度、缩放(统一或 X/Y 分离)、初始旋转(可跟随发射方向)。每个属性支持固定 / 随机 / 曲线三种取值。</dd></div>
|
||||
<div><dt>生命周期变化</dt><dd>速度倍率、缩放倍率(统一/分离)、旋转速度,均可用“生命周期 → 倍率”曲线控制。</dd></div>
|
||||
<div><dt>曲线含义</dt><dd>横轴为粒子生命周期 0→1,纵轴为倍率或对应数值。</dd></div>
|
||||
</dl>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="help-section help-module" :class="{ open: openModules[5] }">
|
||||
<button type="button" class="help-module-head" :aria-expanded="openModules[5] ? 'true' : 'false'" @click="openModules[5] = !openModules[5]">
|
||||
<span class="mnum">6</span><span class="mtitle">外观与资源</span><span class="caret">{{ openModules[5] ? '▾' : '▸' }}</span>
|
||||
</button>
|
||||
<div v-show="openModules[5]" class="help-module-body">
|
||||
<dl class="help-list">
|
||||
<div><dt>透明度</dt><dd>曲线或固定;曲线模式可选“跟随导出 / 线性 / 贝塞尔”。</dd></div>
|
||||
<div><dt>图片资源</dt><dd>“+”新增,可上传单图或序列帧;多张图片按权重随机。每张可调缩放、轴心、颜色(固定/随机/生命周期渐变)、混合模式(正常/相加/相乘/滤色)、独立透明度(关/固定/曲线)。</dd></div>
|
||||
<div><dt>序列帧</dt><dd>播放方式:单次隐藏 / 单次定格 / 正向循环 / 反向循环,可设每秒帧数。</dd></div>
|
||||
</dl>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="help-section help-module" :class="{ open: openModules[6] }">
|
||||
<button type="button" class="help-module-head" :aria-expanded="openModules[6] ? 'true' : 'false'" @click="openModules[6] = !openModules[6]">
|
||||
<span class="mnum">7</span><span class="mtitle">修改器</span><span class="caret">{{ openModules[6] ? '▾' : '▸' }}</span>
|
||||
</button>
|
||||
<div v-show="openModules[6]" class="help-module-body">
|
||||
<dl class="help-list">
|
||||
<div><dt>移动噪声</dt><dd>强度、波动范围、时间流速,让粒子轨迹产生抖动。</dd></div>
|
||||
<div><dt>重力 / 风力</dt><dd>固定或随机强度、方向,以及生命周期内强度曲线。</dd></div>
|
||||
<div><dt>力场</dt><dd>中心 X/Y、强度(正吸负斥)、半径、衰减(恒定/线性/反比)。</dd></div>
|
||||
<div><dt>吸附</dt><dd>延迟后把粒子吸到指定点,到达范围即死亡;可直线或曲线。</dd></div>
|
||||
<div><dt>拖尾</dt><dd>独立拖尾图片(多资源按权重)、旋转、拖尾骨骼数、拖尾比例;长度/宽度可固定或随机并支持放大;可加生命周期长度曲线与形状曲线;颜色/透明度可跟随粒子、固定或曲线。</dd></div>
|
||||
<div><dt>发射器跟随</dt><dd>跟随某条路径(局部/世界、正/反向、进度曲线),或跟随 Spine 骨骼(选中的骨骼 + 偏移)。</dd></div>
|
||||
<div><dt>碰撞 + 阻尼</dt><dd>选择场景中已启用的碰撞对象参与,并设置速度阻尼。</dd></div>
|
||||
</dl>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="help-section help-module" :class="{ open: openModules[7] }">
|
||||
<button type="button" class="help-module-head" :aria-expanded="openModules[7] ? 'true' : 'false'" @click="openModules[7] = !openModules[7]">
|
||||
<span class="mnum">8</span><span class="mtitle">导出设置</span><span class="caret">{{ openModules[7] ? '▾' : '▸' }}</span>
|
||||
</button>
|
||||
<div v-show="openModules[7]" class="help-module-body">
|
||||
<dl class="help-list">
|
||||
<div><dt>图片路径</dt><dd>写入 Spine 的 images 路径,例如 ./images/。</dd></div>
|
||||
<div><dt>Spine 版本</dt><dd>3.8 / 4.0 / 4.1 / 4.2 / 4.3。</dd></div>
|
||||
<div><dt>关键帧曲线</dt><dd>线性或平滑贝塞尔;出生、死亡、突变仍使用阶跃关键帧。</dd></div>
|
||||
<div><dt>导出 FPS</dt><dd>修改 FPS 会保持动画实际秒数不变;“不写 fps”只省略元数据。</dd></div>
|
||||
<div><dt>其它</dt><dd>整数帧对齐、骨骼对象池、排除无内容动画。</dd></div>
|
||||
<div><dt>导出按钮</dt><dd>“导出 Spine Json”生成骨骼动画文件;“导出 images 包”单独下载图片 ZIP;“导出 .spine 包”需要连接器。</dd></div>
|
||||
</dl>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="help-section help-module help-connector" :class="{ open: openModules[8] }">
|
||||
<button type="button" class="help-module-head" :aria-expanded="openModules[8] ? 'true' : 'false'" @click="openModules[8] = !openModules[8]">
|
||||
<span class="mnum">9</span><span class="mtitle">连接器(Spine 连接器)使用说明</span><span class="caret">{{ openModules[8] ? '▾' : '▸' }}</span>
|
||||
</button>
|
||||
<div v-show="openModules[8]" class="help-module-body">
|
||||
<p class="connector-intro">连接器用于把网页生成的 JSON 和图片,调用你电脑上<b>已安装并激活</b>的 Spine,转换成可编辑的 <b>.spine</b> 工程。</p>
|
||||
<dl class="help-list">
|
||||
<div><dt>前置</dt><dd>电脑已安装并激活 Spine;并已启动桌面版连接器APP。</dd></div>
|
||||
<div><dt>下载</dt><dd>
|
||||
<a class="dl-link" href="/downloads/connector/SpineParticleConnector-windows-x64.exe" download>Windows 版<br><small>SpineParticleConnector-windows-x64.exe</small></a>
|
||||
<a class="dl-link" href="/downloads/connector/SpineParticleConnector-macos-arm64.zip" download>macOS 版<br><small>SpineParticleConnector-macos-arm64.zip</small></a>
|
||||
</dd></div>
|
||||
<div><dt>网页端</dt><dd>导出区状态显示“连接器可用 · Spine 已就绪”后,点击“导出 .spine 包”。</dd></div>
|
||||
<div><dt>首次授权</dt><dd>生产网站首次连接会显示“授权当前网站”;点击后在本机确认页核对完整来源(协议 + 域名 + 端口),再点“允许此网站”。授权一次后本机会保存白名单。本地 127.0.0.1:5173 默认允许。</dd></div>
|
||||
<div><dt>路径设置</dt><dd>连接器自动检测 Spine 安装位置;检测不到时可在桌面窗口手动指定:Windows 选 Spine.com,macOS 选 Spine.app/Contents/MacOS/Spine。</dd></div>
|
||||
<div><dt>下载结果</dt><dd>得到 ZIP 包,内含 .spine 工程和图片目录(如 images/star.png)。</dd></div>
|
||||
<div><dt>版本</dt><dd>连接器按请求与 JSON 内的版本自动匹配 3.8~4.3,使用最新可用补丁。</dd></div>
|
||||
<div><dt>安全</dt><dd>仅监听本机 127.0.0.1:27843;授权与白名单保存在连接器里;文件在临时目录转换后清理,并有大小限制。</dd></div>
|
||||
</dl>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="help-section help-export">
|
||||
<h3>配置与导出有什么区别?</h3>
|
||||
<p><b>保存配置</b>会保存编辑器中的全部对象和参数,之后可以继续修改;<b>导出 Spine Json</b>只导出显示中的粒子系统,并把跟随、碰撞和拖尾结果烘焙为独立动画数据。</p>
|
||||
</section>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onBeforeUnmount, onMounted, ref } from 'vue'
|
||||
|
||||
defineProps<{ show: boolean }>()
|
||||
const emit = defineEmits<{ (event: 'close'): void }>()
|
||||
|
||||
// 功能模块详解:默认全部收起,点击标题栏展开/收起单个模块。
|
||||
const openModules = ref<boolean[]>(Array.from({ length: 9 }, () => false))
|
||||
|
||||
function close() {
|
||||
emit('close')
|
||||
}
|
||||
|
||||
function onKeydown(event: KeyboardEvent) {
|
||||
if (event.key === 'Escape') close()
|
||||
}
|
||||
|
||||
onMounted(() => window.addEventListener('keydown', onKeydown))
|
||||
onBeforeUnmount(() => window.removeEventListener('keydown', onKeydown))
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.help-overlay {
|
||||
position: absolute; inset: 0; z-index: 40; display: flex; align-items: center; justify-content: center; padding: 72px 24px 28px;
|
||||
box-sizing: border-box; background: rgba(5, 8, 15, .72); backdrop-filter: blur(3px);
|
||||
}
|
||||
.help-dialog {
|
||||
width: min(820px, 100%); max-height: 100%; display: flex; flex-direction: column; overflow: hidden;
|
||||
border: 1px solid #3a4864; border-radius: 14px; background: #141a27; color: #b8c3d8;
|
||||
box-shadow: 0 22px 70px rgba(0, 0, 0, .62);
|
||||
}
|
||||
.help-head {
|
||||
display: flex; align-items: flex-start; justify-content: space-between; gap: 18px; padding: 18px 20px 15px;
|
||||
border-bottom: 1px solid #2b354a; background: linear-gradient(135deg, #202942, #181e2d);
|
||||
}
|
||||
.help-head h2 { margin: 0; color: #eef2ff; font-size: 19px; }
|
||||
.help-head p { margin: 5px 0 0; color: #7786a3; font-size: 11px; }
|
||||
.help-close {
|
||||
width: 28px; height: 28px; flex: 0 0 28px; border: 1px solid #43516b; border-radius: 6px;
|
||||
background: #273249; color: #ccd7ed; cursor: pointer;
|
||||
}
|
||||
.help-close:hover { border-color: #7774ff; background: #3b4670; color: #fff; }
|
||||
.help-body { min-height: 0; overflow: auto; padding: 18px 20px 21px; }
|
||||
.help-section { padding: 14px 15px; border: 1px solid #2c3850; border-radius: 10px; background: #181f2e; }
|
||||
.help-section h3 { margin: 0 0 11px; color: #9fb2ff; font-size: 13px; }
|
||||
.help-start ol { margin: 0; padding-left: 21px; color: #aab6cc; font-size: 12px; line-height: 1.75; }
|
||||
.help-start li::marker { color: #7774ff; font-weight: 700; }
|
||||
.help-section b { color: #dce4f7; }
|
||||
.help-grid { display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(250px, .85fr); gap: 12px; margin-top: 12px; }
|
||||
.help-list { display: grid; gap: 0; margin: 0; }
|
||||
.help-list > div { display: grid; grid-template-columns: 78px 1fr; gap: 9px; padding: 7px 0; border-bottom: 1px solid #263146; }
|
||||
.help-list > div:last-child { border-bottom: 0; }
|
||||
.help-list dt { color: #d3dcf0; font-size: 11px; font-weight: 700; }
|
||||
.help-list dd { margin: 0; color: #8795ae; font-size: 11px; line-height: 1.5; }
|
||||
.shortcut-list { display: grid; gap: 7px; }
|
||||
.shortcut-list > div { display: flex; align-items: center; min-height: 25px; gap: 5px; }
|
||||
.shortcut-list kbd {
|
||||
min-width: 24px; box-sizing: border-box; padding: 3px 6px; border: 1px solid #465470; border-bottom-width: 2px;
|
||||
border-radius: 5px; background: #101623; color: #e0e7f6; font: 10px/1.2 ui-monospace, SFMono-Regular, Menlo, monospace; text-align: center;
|
||||
}
|
||||
.shortcut-list span { color: #65728b; font-size: 10px; }
|
||||
.shortcut-list em { margin-left: auto; color: #9ca9c1; font-size: 11px; font-style: normal; }
|
||||
.help-note { margin: 11px 0 0; padding-top: 9px; border-top: 1px solid #2a3549; color: #697791; font-size: 10px; line-height: 1.55; }
|
||||
.help-export { margin-top: 12px; }
|
||||
.help-export p { margin: 0; color: #8997b0; font-size: 11px; line-height: 1.65; }
|
||||
.help-doc-title { margin: 16px 2px 2px; color: #9fb2ff; font-size: 13px; font-weight: 700; letter-spacing: .5px; }
|
||||
.help-module { margin-top: 12px; }
|
||||
.help-module-head {
|
||||
display: flex; align-items: center; gap: 8px; width: 100%; padding: 0; border: 0; background: transparent;
|
||||
color: #9fb2ff; font: inherit; font-size: 13px; font-weight: 700; text-align: left; cursor: pointer;
|
||||
}
|
||||
.help-module-head:hover { color: #fff; }
|
||||
.help-module-head .mtitle { flex: 1; min-width: 0; }
|
||||
.help-module-head .caret { flex: 0 0 auto; color: #7b86a2; font-size: 12px; }
|
||||
.help-module.open .help-module-head { color: #fff; }
|
||||
.help-module.open .help-module-head .caret { color: #9fb2ff; }
|
||||
.help-module .mnum {
|
||||
flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
|
||||
width: 22px; height: 22px; border-radius: 6px;
|
||||
background: linear-gradient(135deg, #4a53b8, #6a5fd0); color: #fff; font-size: 12px; font-weight: 700;
|
||||
}
|
||||
.help-module.help-connector { border-color: #4a4f8a; background: linear-gradient(135deg, #1d2442, #181d2f); }
|
||||
.help-module.help-connector .help-module-head { color: #b8c2ff; }
|
||||
.help-module .connector-intro { margin: 0 0 10px; color: #9aa8c4; font-size: 11px; line-height: 1.6; }
|
||||
.help-module .connector-intro b { color: #dce4f7; }
|
||||
.help-module .dl-link {
|
||||
display: inline-flex; flex-direction: column; align-items: flex-start; gap: 2px; margin: 0 10px 6px 0; padding: 6px 12px;
|
||||
border: 1px solid #5652b5; border-radius: 6px; background: #4540a0; color: #fff; font-size: 12px; font-weight: 700; text-decoration: none;
|
||||
}
|
||||
.help-module .dl-link:hover { border-color: #8982ff; background: #554dc2; }
|
||||
.help-module .dl-link small { color: #cfe0ff; font-weight: 500; font-size: 9px; }
|
||||
.help-module-body { padding-top: 10px; }
|
||||
@media (max-width: 760px) {
|
||||
.help-overlay { padding: 66px 12px 14px; }
|
||||
.help-grid { grid-template-columns: 1fr; }
|
||||
}
|
||||
</style>
|
||||
+2
-110
@@ -119,63 +119,7 @@
|
||||
<div class="sp-cache-note">整个系统设置会自动保存到当前浏览器</div>
|
||||
</div>
|
||||
|
||||
<div v-if="showHelp" class="help-overlay" role="presentation" @click.self="showHelp = false">
|
||||
<section class="help-dialog" role="dialog" aria-modal="true" aria-labelledby="help-title">
|
||||
<header class="help-head">
|
||||
<div>
|
||||
<h2 id="help-title">使用说明</h2>
|
||||
<p>从创建粒子到保存、导出的快速入门</p>
|
||||
</div>
|
||||
<button class="help-close" aria-label="关闭使用说明" title="关闭 (Esc)" @click="showHelp = false">✕</button>
|
||||
</header>
|
||||
|
||||
<div class="help-body">
|
||||
<section class="help-section help-start">
|
||||
<h3>快速开始</h3>
|
||||
<ol>
|
||||
<li><b>创建对象:</b>在左侧“场景对象”中添加粒子、碰撞、路径或 Spine。</li>
|
||||
<li><b>编辑粒子:</b>选中粒子系统,依次调整发射、形状、属性、外观资源和修改器。</li>
|
||||
<li><b>查看效果:</b>使用底部时间轴播放、暂停或拖动到指定帧;修改参数后会自动重新计算。</li>
|
||||
<li><b>保存成果:</b>配置文件用于继续编辑;“导出 Spine Json”支持 Spine 3.8、4.0、4.1、4.2 和 4.3。</li>
|
||||
</ol>
|
||||
</section>
|
||||
|
||||
<div class="help-grid">
|
||||
<section class="help-section">
|
||||
<h3>常用功能</h3>
|
||||
<dl class="help-list">
|
||||
<div><dt>小眼睛</dt><dd>单独显示或隐藏场景对象;隐藏的粒子系统不会导出。</dd></div>
|
||||
<div><dt>+Copy</dt><dd>完整复制当前选中对象,方便对比不同参数效果。</dd></div>
|
||||
<div><dt>背景图</dt><dd>上传参考图并调整位置和透明度,只用于画布预览。</dd></div>
|
||||
<div><dt>系统设置</dt><dd>管理界面与辅助显示,并自动保存在当前浏览器中。</dd></div>
|
||||
<div><dt>配置管理</dt><dd>保存当前项目数据、加载配置,或直接使用预设文件;不包含系统设置。</dd></div>
|
||||
<div><dt>Spine 骨骼</dt><dd>在层级树搜索并选择骨骼,可用于粒子发射器跟随。</dd></div>
|
||||
</dl>
|
||||
</section>
|
||||
|
||||
<section class="help-section">
|
||||
<h3>快捷键</h3>
|
||||
<div class="shortcut-list">
|
||||
<div><kbd>Ctrl/⌘</kbd><span>+</span><kbd>Z</kbd><em>撤回上一步</em></div>
|
||||
<div><kbd>Ctrl/⌘</kbd><span>+</span><kbd>S</kbd><em>保存配置</em></div>
|
||||
<div><kbd>Q</kbd><em>拖动画布</em></div>
|
||||
<div><kbd>W</kbd><em>位移工具</em></div>
|
||||
<div><kbd>E</kbd><em>旋转工具</em></div>
|
||||
<div><kbd>R</kbd><em>缩放工具</em></div>
|
||||
<div><kbd>D</kbd><em>播放 / 暂停</em></div>
|
||||
<div><kbd>S</kbd><em>回到第一帧</em></div>
|
||||
</div>
|
||||
<p class="help-note">Q / W / E / R 需要先点击画布。光标位于输入框时,单键快捷键不会触发。</p>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<section class="help-section help-export">
|
||||
<h3>配置与导出有什么区别?</h3>
|
||||
<p><b>保存配置</b>会保存编辑器中的全部对象和参数,之后可以继续修改;<b>导出 Spine Json</b>只导出显示中的粒子系统,并把跟随、碰撞和拖尾结果烘焙为独立动画数据。</p>
|
||||
</section>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
<HelpDialog :show="showHelp" @close="showHelp = false" />
|
||||
|
||||
<div class="hud" v-if="info">
|
||||
系统: <b class="hud-number hud-system-count">{{ info.systems }}</b> · 粒子(骨骼): <b class="hud-number hud-particle-count">{{ info.particles }}</b> · 根骨骼: <b>root</b>
|
||||
@@ -198,6 +142,7 @@ import { editorHistoryState, installEditorHistory, setUndoLimit, undoLastOperati
|
||||
import { useEditorShortcuts } from '../editor/useEditorShortcuts'
|
||||
import { fileToDataUrl } from '../spine/spineSourceBundle'
|
||||
import { downloadEditorConfig } from '../editor/editorConfig'
|
||||
import HelpDialog from './HelpDialog.vue'
|
||||
|
||||
const store = useParticleStore()
|
||||
const holder = ref<HTMLElement | null>(null)
|
||||
@@ -329,10 +274,6 @@ function openHelp() {
|
||||
showBackgroundMenu.value = false
|
||||
}
|
||||
|
||||
function onHelpKeydown(event: KeyboardEvent) {
|
||||
if (event.key === 'Escape' && showHelp.value) showHelp.value = false
|
||||
}
|
||||
|
||||
function toggleSettings() {
|
||||
showSettings.value = !showSettings.value
|
||||
if (showSettings.value) showBackgroundMenu.value = false
|
||||
@@ -1711,7 +1652,6 @@ function loop() {
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
window.addEventListener('keydown', onHelpKeydown)
|
||||
const el = holder.value!
|
||||
app = new Application({ width: el.clientWidth || 800, height: el.clientHeight || 600, backgroundAlpha: 0, antialias: true })
|
||||
el.appendChild(app.view as unknown as HTMLCanvasElement)
|
||||
@@ -1765,7 +1705,6 @@ onMounted(async () => {
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
window.removeEventListener('keydown', onHelpKeydown)
|
||||
cancelAnimationFrame(raf)
|
||||
spineRuntime?.destroy()
|
||||
spineRuntime = null
|
||||
@@ -1843,53 +1782,6 @@ onUnmounted(() => {
|
||||
}
|
||||
.help-btn:hover, .help-btn.on { border-color: #7774ff; background: #343b63; color: #fff; }
|
||||
.zoom-pct { margin-left: 0; font-variant-numeric: tabular-nums; color: #9aa; min-width: 44px; text-align: center; }
|
||||
.help-overlay {
|
||||
position: absolute; inset: 0; z-index: 40; display: flex; align-items: center; justify-content: center; padding: 72px 24px 28px;
|
||||
box-sizing: border-box; background: rgba(5, 8, 15, .72); backdrop-filter: blur(3px);
|
||||
}
|
||||
.help-dialog {
|
||||
width: min(820px, 100%); max-height: 100%; display: flex; flex-direction: column; overflow: hidden;
|
||||
border: 1px solid #3a4864; border-radius: 14px; background: #141a27; color: #b8c3d8;
|
||||
box-shadow: 0 22px 70px rgba(0, 0, 0, .62);
|
||||
}
|
||||
.help-head {
|
||||
display: flex; align-items: flex-start; justify-content: space-between; gap: 18px; padding: 18px 20px 15px;
|
||||
border-bottom: 1px solid #2b354a; background: linear-gradient(135deg, #202942, #181e2d);
|
||||
}
|
||||
.help-head h2 { margin: 0; color: #eef2ff; font-size: 19px; }
|
||||
.help-head p { margin: 5px 0 0; color: #7786a3; font-size: 11px; }
|
||||
.help-close {
|
||||
width: 28px; height: 28px; flex: 0 0 28px; border: 1px solid #43516b; border-radius: 6px;
|
||||
background: #273249; color: #ccd7ed; cursor: pointer;
|
||||
}
|
||||
.help-close:hover { border-color: #7774ff; background: #3b4670; color: #fff; }
|
||||
.help-body { min-height: 0; overflow: auto; padding: 18px 20px 21px; }
|
||||
.help-section { padding: 14px 15px; border: 1px solid #2c3850; border-radius: 10px; background: #181f2e; }
|
||||
.help-section h3 { margin: 0 0 11px; color: #9fb2ff; font-size: 13px; }
|
||||
.help-start ol { margin: 0; padding-left: 21px; color: #aab6cc; font-size: 12px; line-height: 1.75; }
|
||||
.help-start li::marker { color: #7774ff; font-weight: 700; }
|
||||
.help-section b { color: #dce4f7; }
|
||||
.help-grid { display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(250px, .85fr); gap: 12px; margin-top: 12px; }
|
||||
.help-list { display: grid; gap: 0; margin: 0; }
|
||||
.help-list > div { display: grid; grid-template-columns: 78px 1fr; gap: 9px; padding: 7px 0; border-bottom: 1px solid #263146; }
|
||||
.help-list > div:last-child { border-bottom: 0; }
|
||||
.help-list dt { color: #d3dcf0; font-size: 11px; font-weight: 700; }
|
||||
.help-list dd { margin: 0; color: #8795ae; font-size: 11px; line-height: 1.5; }
|
||||
.shortcut-list { display: grid; gap: 7px; }
|
||||
.shortcut-list > div { display: flex; align-items: center; min-height: 25px; gap: 5px; }
|
||||
.shortcut-list kbd {
|
||||
min-width: 24px; box-sizing: border-box; padding: 3px 6px; border: 1px solid #465470; border-bottom-width: 2px;
|
||||
border-radius: 5px; background: #101623; color: #e0e7f6; font: 10px/1.2 ui-monospace, SFMono-Regular, Menlo, monospace; text-align: center;
|
||||
}
|
||||
.shortcut-list span { color: #65728b; font-size: 10px; }
|
||||
.shortcut-list em { margin-left: auto; color: #9ca9c1; font-size: 11px; font-style: normal; }
|
||||
.help-note { margin: 11px 0 0; padding-top: 9px; border-top: 1px solid #2a3549; color: #697791; font-size: 10px; line-height: 1.55; }
|
||||
.help-export { margin-top: 12px; }
|
||||
.help-export p { margin: 0; color: #8997b0; font-size: 11px; line-height: 1.65; }
|
||||
@media (max-width: 760px) {
|
||||
.help-overlay { padding: 66px 12px 14px; }
|
||||
.help-grid { grid-template-columns: 1fr; }
|
||||
}
|
||||
.hud { position: absolute; bottom: 12px; left: 12px; padding: 8px 12px; background: rgba(20,20,32,0.75); border-radius: 8px; font-size: 12px; color: #a0a8cc; }
|
||||
.hud-number { display: inline-block; box-sizing: border-box; text-align: right; font-variant-numeric: tabular-nums; font-feature-settings: 'tnum' 1; }
|
||||
.hud-system-count { width: 3ch; }
|
||||
|
||||
Reference in New Issue
Block a user