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