@ray-js/ipc-player-integration 0.0.50-beta.0 → 0.0.50-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -11
- package/lib/ctx/ctx.composition.js +5 -5
- package/lib/features/initPlayerWidgets/index.d.ts +0 -3
- package/lib/features/initPlayerWidgets/index.js +1 -2
- package/lib/hooks/useBattery/index.js +7 -1
- package/lib/iconfont/iconfont.css +127 -7
- package/lib/iconfont/iconfont.js +10 -10
- package/lib/iconfont/iconfont.json +233 -23
- package/lib/iconfont/iconfont.ttf +0 -0
- package/lib/iconfont/iconfont.woff +0 -0
- package/lib/iconfont/iconfont.woff2 +0 -0
- package/lib/interface.d.ts +1 -1
- package/lib/interface.js +1 -1
- package/lib/ports.output.d.ts +13 -0
- package/lib/ports.output.js +13 -0
- package/lib/ui/bottomLeftContent.js +141 -27
- package/lib/ui/bottomRightContent.d.ts +6 -1
- package/lib/ui/bottomRightContent.js +43 -5
- package/lib/ui/ui.js +58 -4
- package/lib/ui/ui.less +17 -0
- package/lib/widgets/battery/battery.js +11 -3
- package/lib/widgets/battery/battery.less +11 -0
- package/lib/widgets/battery/batteryFull.js +11 -3
- package/lib/widgets/zoomTurntable/constants.d.ts +44 -12
- package/lib/widgets/zoomTurntable/constants.js +61 -17
- package/lib/widgets/zoomTurntable/lensModel.test.js +1 -1
- package/lib/widgets/zoomTurntable/lensSkill.d.ts +1 -1
- package/lib/widgets/zoomTurntable/lensSkill.js +1 -1
- package/lib/widgets/zoomTurntable/turntable/index.js +4 -1
- package/lib/widgets/zoomTurntable/turntable/rjs/index.rjs +138 -9
- package/lib/widgets/zoomTurntable/turntable/rjs/index.tyml +1 -0
- package/lib/widgets/zoomTurntable/useLensZoom.d.ts +3 -4
- package/lib/widgets/zoomTurntable/useLensZoom.js +94 -12
- package/lib/widgets/zoomTurntable/zoomTurntableDock.js +76 -4
- package/lib/widgets/zoomTurntable/zoomTurntableEntry.d.ts +0 -3
- package/lib/widgets/zoomTurntable/zoomTurntableEntry.js +20 -5
- package/lib/widgets/zoomTurntable/zoomTurntableEntry.less +11 -1
- package/package.json +2 -2
|
@@ -5,8 +5,16 @@ import { PlayState } from '../../interface';
|
|
|
5
5
|
import { useDpState } from '../../hooks/useDpState';
|
|
6
6
|
import { setScaleMultipleEvent, zoomLevelChange } from '../../ui/constant';
|
|
7
7
|
import { MOCK_ZOOM_SKILL, MULTI_ZOOM_DP_CODE, dumpChannelApis, isChannelChangeSupported, isZoomSkillValid, lensCount, parseZoomSkill, queryCurrentLens, showSmallMonitor, subscribeChannelChange, switchLens } from './lensSkill';
|
|
8
|
-
import { DEFAULT_STEP, D_MIN, buildMarks, buildTickValues, indexOfLensId, matchLens, maxScaleMultiple, toDisplayZoom, toScaleMultiple, zoomBounds } from './lensModel';
|
|
9
|
-
import { CHANNEL_SETTLE_TIMEOUT, D_MATCH_EPS, GESTURE_SWITCH_DEBOUNCE, SWITCH_LENS_TIMEOUT, zoomTurntableLensChange, zoomTurntableZoomChange } from './constants';
|
|
8
|
+
import { DEFAULT_STEP, D_MIN, buildMarks, buildTickValues, indexOfLensId, lensRange, matchLens, maxScaleMultiple, toDisplayZoom, toScaleMultiple, zoomBounds } from './lensModel';
|
|
9
|
+
import { CHANNEL_SETTLE_TIMEOUT, D_MATCH_EPS, GESTURE_SWITCH_DEBOUNCE, SWITCH_LENS_TIMEOUT, ZOOM_PREVIEW_THROTTLE, zoomTurntableLensChange, zoomTurntableSwitching, zoomTurntableZoomChange } from './constants';
|
|
10
|
+
/**
|
|
11
|
+
* 内部调试开关:置 true 时用 MOCK_ZOOM_SKILL 顶替 ipc_multi_zoom 的上报值。
|
|
12
|
+
*
|
|
13
|
+
* 只在没有该 DP 的设备上自测转盘时临时打开,**提交前必须回到 false**。
|
|
14
|
+
* 不做成 props:mock 是组件内部的调试手段,不该出现在对外 API 上。
|
|
15
|
+
*/
|
|
16
|
+
const USE_MOCK_ZOOM_SKILL = false;
|
|
17
|
+
|
|
10
18
|
/**
|
|
11
19
|
* 最近一次的本地数字缩放 d,按 devId 记录。
|
|
12
20
|
* 放模块级:Dock 动态挂载/卸载,组件内 ref 存不住,但它只是派生中间量,不值得占一个 atom。
|
|
@@ -57,7 +65,6 @@ export const useLensZoom = options => {
|
|
|
57
65
|
devId,
|
|
58
66
|
event,
|
|
59
67
|
showZoomTurntable = false,
|
|
60
|
-
mockZoomSkill,
|
|
61
68
|
skipLoad = false,
|
|
62
69
|
setZoomSkill,
|
|
63
70
|
setZoomLensIndex,
|
|
@@ -82,24 +89,48 @@ export const useLensZoom = options => {
|
|
|
82
89
|
|
|
83
90
|
/** 画面绝对倍率;挂载时按已记录的 d 恢复读数 */
|
|
84
91
|
const [curM, setCurM] = useState(() => zoomSkill ? toDisplayZoom(zoomSkill, zoomLensIndex, getLastD(devId)) : D_MIN);
|
|
92
|
+
/**
|
|
93
|
+
* 正在切往的目标镜头下标(-1 表示没有切换进行中)。
|
|
94
|
+
* 切换真空期里镜头下标还没动,倍率 tab 要靠它把高亮提前落到目标镜头,
|
|
95
|
+
* 免得原镜头的 tab 上冒出目标镜头的数值。
|
|
96
|
+
*/
|
|
97
|
+
const [switchingIndex, setSwitchingIndex] = useState(-1);
|
|
85
98
|
/** 拖动中:屏蔽回读,避免指针被拽回 */
|
|
86
99
|
const draggingRef = useRef(false);
|
|
87
100
|
/** 手势缩放跨临界点判定的 trailing 防抖 */
|
|
88
101
|
const gestureTimerRef = useRef();
|
|
102
|
+
/** 拖动中连续下发的节流时间戳 */
|
|
103
|
+
const previewAtRef = useRef(0);
|
|
89
104
|
const lensIndexRef = useRef(zoomLensIndex);
|
|
90
105
|
lensIndexRef.current = zoomLensIndex;
|
|
91
106
|
const skillRef = useRef(zoomSkill);
|
|
92
107
|
skillRef.current = zoomSkill;
|
|
93
108
|
|
|
109
|
+
/** 标记 / 清除「切换进行中」,并广播给其它 hook 实例 */
|
|
110
|
+
const markSwitching = useMemoizedFn(index => {
|
|
111
|
+
setSwitchingIndex(index);
|
|
112
|
+
event.emit(zoomTurntableSwitching, {
|
|
113
|
+
index
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
useEffect(() => {
|
|
117
|
+
const onSwitching = _ref => {
|
|
118
|
+
let {
|
|
119
|
+
index
|
|
120
|
+
} = _ref;
|
|
121
|
+
return setSwitchingIndex(index);
|
|
122
|
+
};
|
|
123
|
+
event.on(zoomTurntableSwitching, onSwitching);
|
|
124
|
+
return () => {
|
|
125
|
+
event.off(zoomTurntableSwitching, onSwitching);
|
|
126
|
+
};
|
|
127
|
+
}, [event]);
|
|
128
|
+
|
|
94
129
|
// ---------------- 能力加载 ----------------
|
|
95
130
|
useEffect(() => {
|
|
96
131
|
if (skipLoad || !devId || !showZoomTurntable) return undefined;
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
if (mockZoomSkill) {
|
|
100
|
-
console.log('[zoomTurntable] mock 模式:跳过 ipc_multi_zoom DP 解析');
|
|
101
|
-
}
|
|
102
|
-
const raw = mockZoomSkill === true ? MOCK_ZOOM_SKILL : mockZoomSkill || multiZoomDpValue;
|
|
132
|
+
const raw = multiZoomDpValue;
|
|
133
|
+
console.log('[zoomTurntable] ipc_multi_zoom 上报值', JSON.stringify(raw !== null && raw !== void 0 ? raw : null));
|
|
103
134
|
const skill = parseZoomSkill(raw);
|
|
104
135
|
if (!isZoomSkillValid(skill)) {
|
|
105
136
|
// DP 未上报 / 值畸形 / 单镜头设备:能力不可用,入口不出现
|
|
@@ -108,7 +139,7 @@ export const useLensZoom = options => {
|
|
|
108
139
|
}
|
|
109
140
|
setZoomSkill(skill);
|
|
110
141
|
return undefined;
|
|
111
|
-
}, [devId, showZoomTurntable,
|
|
142
|
+
}, [devId, showZoomTurntable, multiZoomDpValue, skipLoad]);
|
|
112
143
|
|
|
113
144
|
/** 多镜头能力就绪:ipc_multi_zoom 解析出的 cnt > 1(单镜头设备不出现) */
|
|
114
145
|
const multiLensReady = showZoomTurntable && lensCount(zoomSkill) > 1;
|
|
@@ -178,9 +209,37 @@ export const useLensZoom = options => {
|
|
|
178
209
|
}, [devId, multiLensReady, playState, skipLoad, syncToLens, syncSmallMonitorByD]);
|
|
179
210
|
|
|
180
211
|
// ---------------- 下发:curM → 切镜头 + d ----------------
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* 拖动过程中的连续下发:画面跟着转盘实时变倍,松手才落地的话中间是"死"的。
|
|
215
|
+
*
|
|
216
|
+
* 只在当前镜头区间内下发本地数字缩放 d,超出区间的部分夹到边界 ——
|
|
217
|
+
* 跨镜头要 switchChannel,逐帧下发扛不住,留给松手后的 applyZoom。
|
|
218
|
+
*/
|
|
219
|
+
const previewZoom = useMemoizedFn(targetM => {
|
|
220
|
+
const skill = skillRef.current;
|
|
221
|
+
if (!skill) return;
|
|
222
|
+
const now = Date.now();
|
|
223
|
+
if (now - previewAtRef.current < ZOOM_PREVIEW_THROTTLE) return;
|
|
224
|
+
previewAtRef.current = now;
|
|
225
|
+
const index = lensIndexRef.current;
|
|
226
|
+
const [lo, hi] = lensRange(skill, index);
|
|
227
|
+
const clamped = Math.min(hi, Math.max(lo, targetM));
|
|
228
|
+
const d = toScaleMultiple(skill, index, clamped);
|
|
229
|
+
setLastD(devId, d);
|
|
230
|
+
// immediate:连续拖动时属性本来就在变,不需要 ui.tsx 那套"先对齐再设目标"的中间态,
|
|
231
|
+
// 走对齐反而会插入一帧 actual 值,画面看起来会抖
|
|
232
|
+
event.emit(setScaleMultipleEvent, {
|
|
233
|
+
value: d,
|
|
234
|
+
immediate: true
|
|
235
|
+
});
|
|
236
|
+
// 小窗按下发值切换,内部按 devId 去重,只在跨过 d=1 时真正调一次
|
|
237
|
+
syncSmallMonitorByD(d);
|
|
238
|
+
});
|
|
181
239
|
const beginDrag = useMemoizedFn(value => {
|
|
182
240
|
draggingRef.current = true;
|
|
183
241
|
setCurM(value);
|
|
242
|
+
previewZoom(value);
|
|
184
243
|
});
|
|
185
244
|
|
|
186
245
|
/**
|
|
@@ -195,6 +254,7 @@ export const useLensZoom = options => {
|
|
|
195
254
|
console.log('[scaleMultiple] zoomTurntable emit setScaleMultipleEvent', D_MIN, `lensIndex=${index}`, `lastD=${getLastD(devId)}`);
|
|
196
255
|
event.emit(setScaleMultipleEvent, D_MIN);
|
|
197
256
|
syncToLens(index, D_MIN);
|
|
257
|
+
markSwitching(-1);
|
|
198
258
|
// 切镜头即回到该镜头的光学正倍数,小窗关掉(onChannelChange / 超时兜底都会走到这里)
|
|
199
259
|
applySmallMonitor(false);
|
|
200
260
|
event.emit(zoomTurntableLensChange, {
|
|
@@ -233,6 +293,9 @@ export const useLensZoom = options => {
|
|
|
233
293
|
// 切物理镜头:从下发到 channelChange 回来这段屏蔽回读
|
|
234
294
|
console.log('[zoomTurntable] 切换镜头', `${prevIndex} -> ${nextIndex}`, `channel=${skill.lenses[nextIndex].id}`, `targetM=${targetM.toFixed(2)}`);
|
|
235
295
|
takePendingSwitch(devId); // 上一次没结算完的直接作废,以最新这次为准
|
|
296
|
+
// 高亮先落到目标镜头:这段真空期里 lensIndex 还是原镜头,
|
|
297
|
+
// 不提前挪的话原 tab 会显示目标镜头的读数,看起来就是数值跳变
|
|
298
|
+
markSwitching(nextIndex);
|
|
236
299
|
switchSeq += 1;
|
|
237
300
|
const seq = switchSeq;
|
|
238
301
|
/** 读数退回「当前镜头 + 已记录的 d」;切没切成不确定时才用 */
|
|
@@ -244,6 +307,7 @@ export const useLensZoom = options => {
|
|
|
244
307
|
index: nextIndex,
|
|
245
308
|
timer: setTimeout(() => {
|
|
246
309
|
pendingSwitchStore.delete(devId);
|
|
310
|
+
markSwitching(-1);
|
|
247
311
|
rollback();
|
|
248
312
|
console.warn('[zoomTurntable] switchChannel 无回调,读数已回滚', `${prevIndex} -> ${nextIndex}`, `${SWITCH_LENS_TIMEOUT}ms`);
|
|
249
313
|
}, SWITCH_LENS_TIMEOUT)
|
|
@@ -254,6 +318,7 @@ export const useLensZoom = options => {
|
|
|
254
318
|
|
|
255
319
|
if (!ok) {
|
|
256
320
|
takePendingSwitch(devId);
|
|
321
|
+
markSwitching(-1);
|
|
257
322
|
console.warn('[zoomTurntable] 切换镜头失败,读数已回滚', `${prevIndex} -> ${nextIndex}`);
|
|
258
323
|
setCurM(toDisplayZoom(skill, prevIndex, getLastD(devId)));
|
|
259
324
|
return;
|
|
@@ -307,10 +372,10 @@ export const useLensZoom = options => {
|
|
|
307
372
|
* 切镜头的统一收尾入口:自己下发的(switchChannel)与外部来源(设备侧 / 其他端)都走这里。
|
|
308
373
|
* 自己下发的那次不在 switchChannel 回调里收尾,就是为了等这条事件 —— 设备真的切过去了再动画面。
|
|
309
374
|
*/
|
|
310
|
-
const onChannelChange = useMemoizedFn(
|
|
375
|
+
const onChannelChange = useMemoizedFn(_ref2 => {
|
|
311
376
|
let {
|
|
312
377
|
channel
|
|
313
|
-
} =
|
|
378
|
+
} = _ref2;
|
|
314
379
|
const skill = skillRef.current;
|
|
315
380
|
if (!skill) {
|
|
316
381
|
console.warn('[zoomTurntable] 收到 channelChange 但镜头能力未就绪,已忽略', channel);
|
|
@@ -380,6 +445,21 @@ export const useLensZoom = options => {
|
|
|
380
445
|
d,
|
|
381
446
|
lensIndex: lensIndexRef.current
|
|
382
447
|
});
|
|
448
|
+
|
|
449
|
+
// 画面已经顶到当前镜头区间的上界(也就是下一个镜头的光学倍数,如 1x 镜头放到 3.0):
|
|
450
|
+
// 这个边界值在归属上属于下一个镜头,必须立刻切过去。
|
|
451
|
+
// 走 trailing 防抖的话,那 500ms 里 tab 会挂着「下一镜头的值」显示在当前镜头上。
|
|
452
|
+
const [, upperBound] = lensRange(skill, lensIndexRef.current);
|
|
453
|
+
const nextIndex = matchLens(skill, next);
|
|
454
|
+
if (nextIndex !== lensIndexRef.current && next >= upperBound - D_MATCH_EPS) {
|
|
455
|
+
if (gestureTimerRef.current) {
|
|
456
|
+
clearTimeout(gestureTimerRef.current);
|
|
457
|
+
gestureTimerRef.current = undefined;
|
|
458
|
+
}
|
|
459
|
+
console.log('[zoomTurntable] 触到镜头区间上界,立即切换', `curM=${next.toFixed(2)}`, `${lensIndexRef.current} -> ${nextIndex}`);
|
|
460
|
+
applyToLens(nextIndex, next);
|
|
461
|
+
return;
|
|
462
|
+
}
|
|
383
463
|
scheduleGestureLensSwitch(next);
|
|
384
464
|
});
|
|
385
465
|
useEffect(() => {
|
|
@@ -402,6 +482,8 @@ export const useLensZoom = options => {
|
|
|
402
482
|
/** 镜头列表(按 value 升序),用于渲染倍率 tab */
|
|
403
483
|
lenses: (_zoomSkill$lenses$sli = zoomSkill === null || zoomSkill === void 0 || (_zoomSkill$lenses = zoomSkill.lenses) === null || _zoomSkill$lenses === void 0 ? void 0 : _zoomSkill$lenses.slice(0, lensCount(zoomSkill))) !== null && _zoomSkill$lenses$sli !== void 0 ? _zoomSkill$lenses$sli : [],
|
|
404
484
|
lensIndex: zoomLensIndex,
|
|
485
|
+
/** 正在切往的目标镜头下标;-1 表示没有切换进行中 */
|
|
486
|
+
switchingIndex,
|
|
405
487
|
/** 画面绝对倍率 */
|
|
406
488
|
curM,
|
|
407
489
|
min,
|
|
@@ -12,7 +12,7 @@ import { PlayState } from '../../interface';
|
|
|
12
12
|
import { pauseTimeToHideAllComponent, playerTap } from '../../ui/constant';
|
|
13
13
|
import { useLensZoom } from './useLensZoom';
|
|
14
14
|
import ZoomTurntable from './turntable';
|
|
15
|
-
import { CROP_RATIO_BOTTOM, CROP_RATIO_RIGHT, RELAYOUT_DELAYS, STYLE_OPTIONS_BOTTOM, STYLE_OPTIONS_RIGHT, VIBRATE_THROTTLE, zoomTurntableClose } from './constants';
|
|
15
|
+
import { CROP_RATIO_BOTTOM, CROP_RATIO_RIGHT, RELAYOUT_DELAYS, ZOOM_CANVAS_OVERSHOOT_BOTTOM, STYLE_OPTIONS_BOTTOM, STYLE_OPTIONS_RIGHT, VIBRATE_THROTTLE, zoomTurntableClose } from './constants';
|
|
16
16
|
import './zoomTurntableDock.less';
|
|
17
17
|
/**
|
|
18
18
|
* 当前页面 id,ty.nativeDisabled 需要它定位要禁用手势分发的页面。
|
|
@@ -40,6 +40,7 @@ const getPageId = () => {
|
|
|
40
40
|
* 定位与层级由承载的 CoverView 通过 absolutePosition 提供。
|
|
41
41
|
*/
|
|
42
42
|
export const ZoomTurntableDock = props => {
|
|
43
|
+
var _initialValueRef$curr;
|
|
43
44
|
const {
|
|
44
45
|
event,
|
|
45
46
|
className
|
|
@@ -73,6 +74,27 @@ export const ZoomTurntableDock = props => {
|
|
|
73
74
|
/** 上次震动时间与上次震动对应的倍率,用于节流与跨刻度判定 */
|
|
74
75
|
const lastVibrateAtRef = useRef(0);
|
|
75
76
|
const lastVibrateValueRef = useRef(curM);
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* 转盘起始值:只在打开转盘 / 重建画布时取一次,之后不再跟随 curM 回写。
|
|
80
|
+
*
|
|
81
|
+
* curM 会因为切镜头收尾、画面回读而变,受控回写会在拖动中把指针拽走 ——
|
|
82
|
+
* 转盘自己维护值、只在落位时把结果下发出去,手感才连续。
|
|
83
|
+
*
|
|
84
|
+
* 取值时机要等镜头能力就绪:能力没就绪时 curM 只是 D_MIN 占位,
|
|
85
|
+
* 拿它当起点会让转盘停在错误刻度(非受控之后没有回写能纠正了)。
|
|
86
|
+
*/
|
|
87
|
+
const initialValueRef = useRef(null);
|
|
88
|
+
const lastRemountRef = useRef(remountKey);
|
|
89
|
+
if (lastRemountRef.current !== remountKey) {
|
|
90
|
+
lastRemountRef.current = remountKey;
|
|
91
|
+
initialValueRef.current = null;
|
|
92
|
+
}
|
|
93
|
+
if (initialValueRef.current == null && multiLensReady && curM > 0) {
|
|
94
|
+
initialValueRef.current = curM;
|
|
95
|
+
}
|
|
96
|
+
// 兜底夹到 [min, max]:起点绝不能落在倍率域之外(曾出现过 0.0X)
|
|
97
|
+
const initialValue = Math.min(max, Math.max(min, (_initialValueRef$curr = initialValueRef.current) !== null && _initialValueRef$curr !== void 0 ? _initialValueRef$curr : min));
|
|
76
98
|
const requestClose = useMemoizedFn(() => {
|
|
77
99
|
event.emit(zoomTurntableClose);
|
|
78
100
|
});
|
|
@@ -111,6 +133,41 @@ export const ZoomTurntableDock = props => {
|
|
|
111
133
|
};
|
|
112
134
|
}, []);
|
|
113
135
|
|
|
136
|
+
// 诊断:把浮层与 canvas 的真实布局打出来,核对可拖区域到底覆盖到哪。
|
|
137
|
+
// 期望(竖屏 HIT_PADDING_Y=56):dock 高 296、canvas 高 288,canvas 顶距 dock 顶约 8px。
|
|
138
|
+
// 若 canvas 实际高度远小于 288,说明 rjs 的 canvasWidth/Height 没随 styleOptions 更新,
|
|
139
|
+
// 上半部分自然收不到 touch,会直接落到播放器上。
|
|
140
|
+
useEffect(() => {
|
|
141
|
+
const timer = setTimeout(() => {
|
|
142
|
+
const query = ty.createSelectorQuery();
|
|
143
|
+
query.select('.ipc-player-plugin-zoom-turntable-dock').boundingClientRect();
|
|
144
|
+
query.select('.ipc-zoom-turntable-canvas').boundingClientRect();
|
|
145
|
+
query.selectViewport().boundingClientRect();
|
|
146
|
+
query.exec(res => {
|
|
147
|
+
const dock = res === null || res === void 0 ? void 0 : res[0];
|
|
148
|
+
const canvas = res === null || res === void 0 ? void 0 : res[1];
|
|
149
|
+
const viewport = res === null || res === void 0 ? void 0 : res[2];
|
|
150
|
+
console.log('[zoomTurntable] 浮层布局诊断', JSON.stringify({
|
|
151
|
+
dock: dock && {
|
|
152
|
+
top: dock.top,
|
|
153
|
+
left: dock.left,
|
|
154
|
+
w: dock.width,
|
|
155
|
+
h: dock.height
|
|
156
|
+
},
|
|
157
|
+
canvas: canvas && {
|
|
158
|
+
top: canvas.top,
|
|
159
|
+
left: canvas.left,
|
|
160
|
+
w: canvas.width,
|
|
161
|
+
h: canvas.height
|
|
162
|
+
},
|
|
163
|
+
canvas顶距dock顶: dock && canvas ? canvas.top - dock.top : null,
|
|
164
|
+
viewportH: viewport === null || viewport === void 0 ? void 0 : viewport.height
|
|
165
|
+
}));
|
|
166
|
+
});
|
|
167
|
+
}, 300);
|
|
168
|
+
return () => clearTimeout(timer);
|
|
169
|
+
}, [remountKey]);
|
|
170
|
+
|
|
114
171
|
// 点击播放器 → 收起转盘。
|
|
115
172
|
// ui.tsx 的 handPlayerTap 会在此时把其余控件重新显示出来(componentHideState → false)
|
|
116
173
|
// 并 emit(playerTap),所以这里只需负责关掉转盘。
|
|
@@ -193,6 +250,20 @@ export const ZoomTurntableDock = props => {
|
|
|
193
250
|
alignItems: 'center',
|
|
194
251
|
justifyContent: 'flex-end'
|
|
195
252
|
}), [isRight]);
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* canvas 的承载层。竖屏用负 margin 让 canvas 底边探出播放器底边,
|
|
256
|
+
* 浮层本身则贴底不下沉 —— 这样 canvas 顶部(刻度线那一带)才不会被 CoverView 裁掉,
|
|
257
|
+
* 而绘制内容的视觉位置与探出效果都和原来一致。
|
|
258
|
+
*/
|
|
259
|
+
const canvasHolderStyle = useMemo(() => isRight ? {
|
|
260
|
+
display: 'flex',
|
|
261
|
+
justifyContent: 'center'
|
|
262
|
+
} : {
|
|
263
|
+
display: 'flex',
|
|
264
|
+
justifyContent: 'center',
|
|
265
|
+
marginBottom: `-${ZOOM_CANVAS_OVERSHOOT_BOTTOM}px`
|
|
266
|
+
}, [isRight]);
|
|
196
267
|
if (!multiLensReady || playState !== PlayState.PLAYING) {
|
|
197
268
|
return null;
|
|
198
269
|
}
|
|
@@ -205,10 +276,11 @@ export const ZoomTurntableDock = props => {
|
|
|
205
276
|
'ipc-player-plugin-zoom-turntable-dock-right': isRight
|
|
206
277
|
}),
|
|
207
278
|
style: turntableStyle
|
|
279
|
+
}, /*#__PURE__*/React.createElement(View, {
|
|
280
|
+
style: canvasHolderStyle
|
|
208
281
|
}, /*#__PURE__*/React.createElement(ZoomTurntable, {
|
|
209
282
|
key: `${isRight ? 'right' : 'bottom'}-${remountKey}`,
|
|
210
|
-
|
|
211
|
-
defaultValue: curM,
|
|
283
|
+
defaultValue: initialValue,
|
|
212
284
|
min: min,
|
|
213
285
|
max: max,
|
|
214
286
|
step: step,
|
|
@@ -224,5 +296,5 @@ export const ZoomTurntableDock = props => {
|
|
|
224
296
|
onChangeEnd: handleChangeEnd,
|
|
225
297
|
onTouchStart: handleTouchStart,
|
|
226
298
|
onTouchEnd: handleTouchEnd
|
|
227
|
-
}));
|
|
299
|
+
})));
|
|
228
300
|
};
|
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { ComponentConfigProps } from '../../interface';
|
|
3
|
-
import { ZoomSkill } from './lensSkill';
|
|
4
3
|
import './zoomTurntableEntry.less';
|
|
5
4
|
type Props = ComponentConfigProps & {
|
|
6
5
|
className?: string;
|
|
7
6
|
/** 业务侧的功能开关;实际是否渲染仍由 ipc_multi_zoom 解析出的 cnt 决定 */
|
|
8
7
|
showZoomTurntable?: boolean;
|
|
9
|
-
/** 调试用:直接注入镜头能力,跳过 ipc_multi_zoom DP 解析 */
|
|
10
|
-
mockZoomSkill?: ZoomSkill | boolean;
|
|
11
8
|
/** 长按判定时长,默认 500ms */
|
|
12
9
|
longPressDuration?: number;
|
|
13
10
|
/** 关闭圈选引导 */
|
|
@@ -49,9 +49,16 @@ export const ZoomTurntableEntry = props => {
|
|
|
49
49
|
multiLensReady,
|
|
50
50
|
lenses,
|
|
51
51
|
lensIndex,
|
|
52
|
+
switchingIndex,
|
|
52
53
|
curM,
|
|
53
54
|
switchToLens
|
|
54
55
|
} = useLensZoom(props);
|
|
56
|
+
|
|
57
|
+
// 切换真空期(下发成功 ~ channelChange / 超时收尾)里镜头下标还没动,
|
|
58
|
+
// 高亮提前落到目标镜头,且各 tab 一律显示自己的光学倍数:
|
|
59
|
+
// 否则原镜头的 tab 上会先冒出目标镜头的读数,收尾后再跳回去。
|
|
60
|
+
const isLensSwitching = switchingIndex >= 0;
|
|
61
|
+
const activeIndex = isLensSwitching ? switchingIndex : lensIndex;
|
|
55
62
|
const [dockVisible, setDockVisible] = useState(false);
|
|
56
63
|
const timerRef = useRef();
|
|
57
64
|
const startRef = useRef();
|
|
@@ -61,6 +68,9 @@ export const ZoomTurntableEntry = props => {
|
|
|
61
68
|
const cancelledRef = useRef(false);
|
|
62
69
|
const dockVisibleRef = useRef(false);
|
|
63
70
|
const tipCheckedRef = useRef(false);
|
|
71
|
+
/** onTouchEnd 是稳定引用,用 ref 取最新的高亮下标 */
|
|
72
|
+
const activeIndexRef = useRef(activeIndex);
|
|
73
|
+
activeIndexRef.current = activeIndex;
|
|
64
74
|
const clearTimer = () => {
|
|
65
75
|
if (timerRef.current) {
|
|
66
76
|
clearTimeout(timerRef.current);
|
|
@@ -211,13 +221,17 @@ export const ZoomTurntableEntry = props => {
|
|
|
211
221
|
clearTimer();
|
|
212
222
|
// firedRef:长按已出转盘,不再当作点击处理
|
|
213
223
|
if (!firedRef.current && !cancelledRef.current) {
|
|
214
|
-
|
|
224
|
+
// 与 activeIndex 比:正在切往的那个 tab 再点一次不该重复下发
|
|
225
|
+
if (index !== activeIndexRef.current) {
|
|
215
226
|
event.emit(widgetClick, {
|
|
216
227
|
widgetId: widgetLabs.ZOOM_TURNTABLE
|
|
217
228
|
});
|
|
218
229
|
switchToLens(index);
|
|
219
230
|
}
|
|
220
|
-
|
|
231
|
+
// 点过 tab 之后不重启自动隐藏倒计时(onTouchStart 已 pause,这里保持暂停):
|
|
232
|
+
// 切镜头真正生效要等 channelChange / 超时收尾,5s 倒计时会在切换过程中把工具条藏掉,
|
|
233
|
+
// 用户看不到读数落位。收起交给用户点播放器(ui.tsx handPlayerTap 直接置隐藏,
|
|
234
|
+
// 不依赖倒计时,暂停状态下照常生效)。
|
|
221
235
|
}
|
|
222
236
|
});
|
|
223
237
|
if (playState !== PlayState.PLAYING || !multiLensReady) {
|
|
@@ -230,9 +244,10 @@ export const ZoomTurntableEntry = props => {
|
|
|
230
244
|
'ipc-player-plugin-zoom-turntable-tabs-full': screenType === 'full'
|
|
231
245
|
})
|
|
232
246
|
}, lenses.map((lens, index) => {
|
|
233
|
-
const active = index ===
|
|
234
|
-
// 当前镜头实时显示画面绝对倍率(手势放大时 1.0X → 2.5X
|
|
235
|
-
|
|
247
|
+
const active = index === activeIndex;
|
|
248
|
+
// 当前镜头实时显示画面绝对倍率(手势放大时 1.0X → 2.5X),其余显示各自光学倍数;
|
|
249
|
+
// 切换进行中则一律显示光学倍数 —— 此时 curM 已指向目标值,挂谁身上都是跳变
|
|
250
|
+
const text = `${(active && !isLensSwitching ? curM : lens.basicRatio).toFixed(1)}X`;
|
|
236
251
|
return /*#__PURE__*/React.createElement(View, {
|
|
237
252
|
key: lens.id,
|
|
238
253
|
className: clsx('ipc-player-plugin-zoom-turntable-tab', {
|
|
@@ -27,18 +27,28 @@
|
|
|
27
27
|
align-items: center;
|
|
28
28
|
padding: calc(4px * var(--ipc-player-size-scale, 1)) calc(5px * var(--ipc-player-size-scale, 1));
|
|
29
29
|
background-color: rgba(255, 255, 255, 0.3);
|
|
30
|
+
// 读数每帧都在变(4.1X → 4.8X),比例字体下 1 比 8 窄,胶囊宽度会跟着抖,
|
|
31
|
+
// 还会连带触发左下角工具条的重测。min-width 撑住 "N.NX" 的最宽排布,
|
|
32
|
+
// 加上 box-sizing 让 padding 计入,宽度就不再随数字变化。
|
|
33
|
+
// 超过 4 字符(10.0X)时自然撑开,那是跨十倍才发生一次的变化。
|
|
34
|
+
box-sizing: border-box;
|
|
35
|
+
min-width: calc(38px * var(--ipc-player-size-scale, 1));
|
|
30
36
|
|
|
31
37
|
.ipc-player-plugin-zoom-turntable-tab-text {
|
|
32
38
|
color: var(--iconColor);
|
|
33
39
|
font-weight: 600;
|
|
34
40
|
font-size: calc(12px * var(--ipc-player-size-scale, 1));
|
|
41
|
+
// 等宽数字:让 0-9 占同样的字身宽,从根上消掉逐帧抖动(渲染层支持时生效)
|
|
42
|
+
font-variant-numeric: tabular-nums;
|
|
43
|
+
font-feature-settings: 'tnum';
|
|
35
44
|
}
|
|
36
45
|
}
|
|
37
46
|
|
|
38
|
-
// 横屏:左右 padding 放宽,同 RealTimeMagnification 的 full
|
|
47
|
+
// 横屏:左右 padding 放宽,同 RealTimeMagnification 的 full 态;min-width 同步加宽
|
|
39
48
|
.ipc-player-plugin-zoom-turntable-tab-full {
|
|
40
49
|
padding-left: calc(8px * var(--ipc-player-size-scale, 1));
|
|
41
50
|
padding-right: calc(8px * var(--ipc-player-size-scale, 1));
|
|
51
|
+
min-width: calc(44px * var(--ipc-player-size-scale, 1));
|
|
42
52
|
}
|
|
43
53
|
|
|
44
54
|
// 选中态:白底黑字(须在基础态之后定义,同优先级下后者生效)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ray-js/ipc-player-integration",
|
|
3
|
-
"version": "0.0.50-beta.
|
|
3
|
+
"version": "0.0.50-beta.2",
|
|
4
4
|
"description": "IPC 融合播放器",
|
|
5
5
|
"main": "lib/index",
|
|
6
6
|
"files": [
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
"@commitlint/cli": "^7.2.1",
|
|
49
49
|
"@commitlint/config-conventional": "^9.0.1",
|
|
50
50
|
"@ray-js/cli": "^1.7.61",
|
|
51
|
-
"@ray-js/ray": "1.7.83
|
|
51
|
+
"@ray-js/ray": "^1.7.83",
|
|
52
52
|
"@testing-library/react-hooks": "^8.0.1",
|
|
53
53
|
"@types/jest": "^29.5.14",
|
|
54
54
|
"ahooks": "^3.8.4",
|