forked from natuka/web.puabadge.com
修改:优化点云过渡效果
This commit is contained in:
1 parent
704f6a30e0
commit
e6ff4756df
2 files changed
+51
-45
No files matched your search
@@ -48,7 +48,7 @@ const TIMING = {
|
||||
SUBJECT_OUTLINE_MS: 1600,
|
||||
/** 灰色人物抠图停留 5s 后再上色 */
|
||||
SUBJECT_GRAY_MS: 5000,
|
||||
/** 人物点云最短停留(彩色段);结果 ready 可提前打断 */
|
||||
/** 彩色人物点云最短停留后再切效果图点云 */
|
||||
SUBJECT_HOLD_MS: 1200,
|
||||
RESULT_TRANSITION_MS: 1200,
|
||||
/** 效果图灰色点云 */
|
||||
|
||||
@@ -60,6 +60,7 @@ function createStateMachine(hooks) {
|
||||
subjectReady = false
|
||||
subjectFailed = false
|
||||
subjectEntered = false
|
||||
resultReadyAt = 0
|
||||
enter(PHASE.LOGO_POINT_CLOUD)
|
||||
}
|
||||
|
||||
@@ -110,10 +111,11 @@ function createStateMachine(hooks) {
|
||||
if (phase !== PHASE.IMAGE_COLOR_POINT_CLOUD && phase !== PHASE.RESULT_PRELOADING) {
|
||||
return false
|
||||
}
|
||||
// 等效果图点云采样完成后再进 mask 人物段,避免真机提前切空缓冲黑屏
|
||||
if (resultPreloadStatus !== 'ready') return false
|
||||
// 原图彩色点云需先完整展示
|
||||
if (Date.now() - phaseStartedAt < TIMING.IMAGE_COLOR_MS && phase === PHASE.IMAGE_COLOR_POINT_CLOUD) {
|
||||
// 原图彩色点云需先完整展示,再进 mask 人物段(不因效果图就绪而跳过)
|
||||
if (
|
||||
phase === PHASE.IMAGE_COLOR_POINT_CLOUD &&
|
||||
Date.now() - phaseStartedAt < TIMING.IMAGE_COLOR_MS
|
||||
) {
|
||||
return false
|
||||
}
|
||||
subjectEntered = true
|
||||
@@ -123,22 +125,28 @@ function createStateMachine(hooks) {
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* 切到效果图点云。人物段未走完时禁止跳转:
|
||||
* - subjectReady:必须播完 SUBJECT_* 到彩色人物点云后才可切
|
||||
* - subjectFailed:可从原图彩/预加载直接切效果图
|
||||
*/
|
||||
function tryStartResultTransition() {
|
||||
if (!colorWaitReached) return false
|
||||
if (resultPreloadStatus !== 'ready') return false
|
||||
if (
|
||||
phase !== PHASE.IMAGE_COLOR_POINT_CLOUD &&
|
||||
phase !== PHASE.RESULT_PRELOADING &&
|
||||
phase !== PHASE.SUBJECT_DETECTING &&
|
||||
phase !== PHASE.SUBJECT_OUTLINE &&
|
||||
phase !== PHASE.SUBJECT_CLOUD_GRAY &&
|
||||
phase !== PHASE.SUBJECT_CLOUD_COLORIZE &&
|
||||
phase !== PHASE.SUBJECT_CLOUD_COLOR &&
|
||||
phase !== PHASE.SUBJECT_POINT_CLOUD
|
||||
) {
|
||||
|
||||
const inSubjectColor =
|
||||
phase === PHASE.SUBJECT_CLOUD_COLOR || phase === PHASE.SUBJECT_POINT_CLOUD
|
||||
const canSkipSubject =
|
||||
subjectFailed &&
|
||||
(phase === PHASE.IMAGE_COLOR_POINT_CLOUD || phase === PHASE.RESULT_PRELOADING)
|
||||
|
||||
if (inSubjectColor) {
|
||||
// 彩色人物点云至少停留 SUBJECT_HOLD_MS
|
||||
if (Date.now() - phaseStartedAt < TIMING.SUBJECT_HOLD_MS) return false
|
||||
} else if (!canSkipSubject) {
|
||||
return false
|
||||
}
|
||||
// 效果图阶段清零人物进度,保证 RESULT_* 观感不变
|
||||
|
||||
subjectProgress = 0
|
||||
outlineProgress = 0
|
||||
reveal = 0
|
||||
@@ -215,8 +223,7 @@ function createStateMachine(hooks) {
|
||||
colorProgress = 1
|
||||
colorWaitReached = true
|
||||
enter(PHASE.IMAGE_COLOR_POINT_CLOUD)
|
||||
// 不立刻进人物:先展示原图彩色点云 IMAGE_COLOR_MS
|
||||
tryStartResultTransition()
|
||||
// 先展示原图彩色点云;人物段由 IMAGE_COLOR_MS 结束后再进
|
||||
}
|
||||
return getUniforms()
|
||||
}
|
||||
@@ -232,38 +239,40 @@ function createStateMachine(hooks) {
|
||||
subjectProgress = 0
|
||||
outlineProgress = 0
|
||||
if (!morphing) assembly = 1
|
||||
if (
|
||||
resultPreloadStatus === 'loading' &&
|
||||
phase === PHASE.IMAGE_COLOR_POINT_CLOUD &&
|
||||
|
||||
const colorHoldDone =
|
||||
phase === PHASE.RESULT_PRELOADING ||
|
||||
Date.now() - phaseStartedAt >= TIMING.IMAGE_COLOR_MS
|
||||
) {
|
||||
// 彩色原图已展示够再标预加载;人物段优先于 RESULT_PRELOADING 文案
|
||||
}
|
||||
// 效果图点云就绪后再进 mask 人物段;识别失败或超时则直接切效果图点云
|
||||
if (resultPreloadStatus === 'ready') {
|
||||
|
||||
if (colorHoldDone) {
|
||||
// 优先进 mask 人物点云,绝不因效果图已就绪而跳过
|
||||
const entered = tryEnterSubject()
|
||||
const subjectWaitedOut =
|
||||
!subjectReady &&
|
||||
!subjectFailed &&
|
||||
resultReadyAt &&
|
||||
Date.now() - resultReadyAt > 12000
|
||||
if (!entered && (subjectFailed || subjectWaitedOut)) {
|
||||
if (!entered) {
|
||||
// mask 尚未就绪:继续等;超时或失败才直切效果图
|
||||
const waitMs =
|
||||
phase === PHASE.RESULT_PRELOADING
|
||||
? 12000
|
||||
: TIMING.IMAGE_COLOR_MS + 12000
|
||||
const subjectWaitedOut =
|
||||
!subjectReady &&
|
||||
!subjectFailed &&
|
||||
Date.now() - phaseStartedAt > waitMs
|
||||
if (subjectWaitedOut) subjectFailed = true
|
||||
tryStartResultTransition()
|
||||
if (subjectFailed) {
|
||||
tryStartResultTransition()
|
||||
} else if (
|
||||
phase === PHASE.IMAGE_COLOR_POINT_CLOUD &&
|
||||
(resultPreloadStatus === 'loading' || resultPreloadStatus === 'idle')
|
||||
) {
|
||||
enter(PHASE.RESULT_PRELOADING)
|
||||
}
|
||||
}
|
||||
} else if (
|
||||
phase === PHASE.IMAGE_COLOR_POINT_CLOUD &&
|
||||
Date.now() - phaseStartedAt >= TIMING.IMAGE_COLOR_MS &&
|
||||
(resultPreloadStatus === 'loading' || resultPreloadStatus === 'idle')
|
||||
) {
|
||||
enter(PHASE.RESULT_PRELOADING)
|
||||
}
|
||||
return getUniforms()
|
||||
}
|
||||
|
||||
// —— 人物粗轮廓段(效果图前):彩原图 → 灰抠图 → 约10s → 彩抠图 ——
|
||||
// —— 人物粗轮廓段:检测 → 轮廓 → 灰抠图 → 上色 → 彩抠图(不可中途跳到效果图)——
|
||||
if (phase === PHASE.SUBJECT_DETECTING) {
|
||||
// Buffer 已就绪:短过渡进 OUTLINE,不固定空等满 SUBJECT_DETECT_MS
|
||||
const detectDur = subjectReady
|
||||
? Math.min(TIMING.SUBJECT_DETECT_MS, 420)
|
||||
: TIMING.SUBJECT_DETECT_MS
|
||||
@@ -275,7 +284,6 @@ function createStateMachine(hooks) {
|
||||
if (!morphing) assembly = 1
|
||||
subjectProgress = smootherstep(t) * 0.75
|
||||
outlineProgress = smootherstep(Math.max(0, (t - 0.2) / 0.8)) * 0.5
|
||||
if (tryStartResultTransition()) return getUniforms()
|
||||
if (!morphing && t >= 1) {
|
||||
colorProgress = 0
|
||||
enter(PHASE.SUBJECT_OUTLINE)
|
||||
@@ -292,7 +300,6 @@ function createStateMachine(hooks) {
|
||||
const t = Math.min(1, elapsed / TIMING.SUBJECT_OUTLINE_MS)
|
||||
subjectProgress = 0.7 + smootherstep(t) * 0.3
|
||||
outlineProgress = 0.45 + smootherstep(t) * 0.55
|
||||
if (tryStartResultTransition()) return getUniforms()
|
||||
if (!morphing && t >= 1) {
|
||||
enter(PHASE.SUBJECT_CLOUD_GRAY)
|
||||
}
|
||||
@@ -307,7 +314,6 @@ function createStateMachine(hooks) {
|
||||
if (!morphing) assembly = 1
|
||||
subjectProgress = 1
|
||||
outlineProgress = Math.max(0.35, 1 - Math.min(1, elapsed / 2400) * 0.55)
|
||||
if (tryStartResultTransition()) return getUniforms()
|
||||
if (!morphing && elapsed >= TIMING.SUBJECT_GRAY_MS) {
|
||||
enter(PHASE.SUBJECT_CLOUD_COLORIZE)
|
||||
}
|
||||
@@ -323,7 +329,6 @@ function createStateMachine(hooks) {
|
||||
if (!morphing) assembly = 1
|
||||
subjectProgress = 1
|
||||
outlineProgress = 0.35
|
||||
if (tryStartResultTransition()) return getUniforms()
|
||||
if (t >= 1) {
|
||||
colorProgress = 1
|
||||
enter(PHASE.SUBJECT_CLOUD_COLOR)
|
||||
@@ -342,6 +347,7 @@ function createStateMachine(hooks) {
|
||||
if (!morphing) assembly = 1
|
||||
subjectProgress = 1
|
||||
outlineProgress = 0.3
|
||||
// 人物彩色点云播完(且效果图就绪)后再切效果图点云
|
||||
tryStartResultTransition()
|
||||
return getUniforms()
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user