@ray-js/ipc-player-integration 0.0.49 → 0.0.50-beta.0
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/lib/ctx/ctx.composition.js +6 -1
- package/lib/ctx/ctx.js +11 -1
- package/lib/features/initPlayerWidgets/index.d.ts +8 -0
- package/lib/features/initPlayerWidgets/index.js +13 -0
- package/lib/i18n/index.d.ts +8 -0
- package/lib/i18n/strings.d.ts +4 -0
- package/lib/i18n/strings.js +4 -0
- package/lib/interface.d.ts +9 -1
- package/lib/ui/bottomLeftContent.js +23 -8
- package/lib/ui/constant.d.ts +10 -0
- package/lib/ui/constant.js +12 -1
- package/lib/ui/ui.js +78 -4
- package/lib/ui/ui.less +15 -0
- package/lib/utils/content/dpCode.d.ts +1 -0
- package/lib/utils/content/dpCode.js +5 -1
- package/lib/utils/storage/index.d.ts +2 -2
- package/lib/widgets/index.d.ts +1 -0
- package/lib/widgets/index.js +2 -1
- package/lib/widgets/realTimeMagnification/realTimeMagnification.js +18 -1
- package/lib/widgets/toggleVerticalFull/toggleVerticalFull.less +1 -1
- package/lib/widgets/zoomTurntable/constants.d.ts +92 -0
- package/lib/widgets/zoomTurntable/constants.js +148 -0
- package/lib/widgets/zoomTurntable/entryAnchor.d.ts +7 -0
- package/lib/widgets/zoomTurntable/entryAnchor.js +7 -0
- package/lib/widgets/zoomTurntable/index.d.ts +8 -0
- package/lib/widgets/zoomTurntable/index.js +8 -0
- package/lib/widgets/zoomTurntable/lensModel.d.ts +53 -0
- package/lib/widgets/zoomTurntable/lensModel.js +137 -0
- package/lib/widgets/zoomTurntable/lensModel.test.d.ts +1 -0
- package/lib/widgets/zoomTurntable/lensModel.test.js +336 -0
- package/lib/widgets/zoomTurntable/lensSkill.d.ts +89 -0
- package/lib/widgets/zoomTurntable/lensSkill.js +332 -0
- package/lib/widgets/zoomTurntable/measureVisible.d.ts +22 -0
- package/lib/widgets/zoomTurntable/measureVisible.js +76 -0
- package/lib/widgets/zoomTurntable/turntable/index.d.ts +10 -0
- package/lib/widgets/zoomTurntable/turntable/index.js +76 -0
- package/lib/widgets/zoomTurntable/turntable/index.less +11 -0
- package/lib/widgets/zoomTurntable/turntable/rjs/index.js +242 -0
- package/lib/widgets/zoomTurntable/turntable/rjs/index.json +3 -0
- package/lib/widgets/zoomTurntable/turntable/rjs/index.rjs +691 -0
- package/lib/widgets/zoomTurntable/turntable/rjs/index.tyml +7 -0
- package/lib/widgets/zoomTurntable/turntable/type.d.ts +95 -0
- package/lib/widgets/zoomTurntable/turntable/type.js +1 -0
- package/lib/widgets/zoomTurntable/useLensZoom.d.ts +37 -0
- package/lib/widgets/zoomTurntable/useLensZoom.js +418 -0
- package/lib/widgets/zoomTurntable/zoomTurntableDock.d.ts +17 -0
- package/lib/widgets/zoomTurntable/zoomTurntableDock.js +228 -0
- package/lib/widgets/zoomTurntable/zoomTurntableDock.less +11 -0
- package/lib/widgets/zoomTurntable/zoomTurntableEntry.d.ts +21 -0
- package/lib/widgets/zoomTurntable/zoomTurntableEntry.js +253 -0
- package/lib/widgets/zoomTurntable/zoomTurntableEntry.less +51 -0
- package/lib/widgets/zoomTurntable/zoomTurntableTip.d.ts +16 -0
- package/lib/widgets/zoomTurntable/zoomTurntableTip.js +76 -0
- package/lib/widgets/zoomTurntable/zoomTurntableTip.less +56 -0
- package/package.json +3 -3
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
|
|
2
|
+
import "core-js/modules/esnext.iterator.constructor.js";
|
|
3
|
+
import "core-js/modules/esnext.iterator.filter.js";
|
|
4
|
+
import "core-js/modules/esnext.iterator.map.js";
|
|
5
|
+
import { DEFAULT_MATCH_TOLERANCE, D_MAX, D_MIN, buildMarks, buildTickValues, deltaOf, indexOfLensId, matchLens, maxScaleMultiple, toDisplayZoom, toleranceOf, toScaleMultiple, zoomBounds } from './lensModel';
|
|
6
|
+
import { isZoomSkillValid, lensCount, parseZoomSkill } from './lensSkill';
|
|
7
|
+
|
|
8
|
+
/** 双目定焦:短焦 1.0x / 临界 3.0x / 长焦 3.0x / 手势上限 6.0x */
|
|
9
|
+
const DOUBLE = {
|
|
10
|
+
cnt: 2,
|
|
11
|
+
thresholds: [1.0, 3.0, 6.0],
|
|
12
|
+
lenses: [{
|
|
13
|
+
id: 0,
|
|
14
|
+
type: 1,
|
|
15
|
+
step: 0.1,
|
|
16
|
+
basicRatio: 1.0
|
|
17
|
+
}, {
|
|
18
|
+
id: 1,
|
|
19
|
+
type: 1,
|
|
20
|
+
step: 0.1,
|
|
21
|
+
basicRatio: 3.0
|
|
22
|
+
}]
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
/** 三目定焦 */
|
|
26
|
+
const TRIPLE = {
|
|
27
|
+
cnt: 3,
|
|
28
|
+
thresholds: [1.0, 3.0, 6.0, 12.0],
|
|
29
|
+
lenses: [{
|
|
30
|
+
id: 0,
|
|
31
|
+
type: 1,
|
|
32
|
+
step: 0.1,
|
|
33
|
+
basicRatio: 1.0
|
|
34
|
+
}, {
|
|
35
|
+
id: 1,
|
|
36
|
+
type: 1,
|
|
37
|
+
step: 0.1,
|
|
38
|
+
basicRatio: 3.0
|
|
39
|
+
}, {
|
|
40
|
+
id: 2,
|
|
41
|
+
type: 1,
|
|
42
|
+
step: 0.1,
|
|
43
|
+
basicRatio: 6.0
|
|
44
|
+
}]
|
|
45
|
+
};
|
|
46
|
+
describe('lensSkill 校验', () => {
|
|
47
|
+
it('cnt 为镜头数依据,缺失时回落 lenses.length', () => {
|
|
48
|
+
expect(lensCount(DOUBLE)).toBe(2);
|
|
49
|
+
expect(lensCount(_objectSpread(_objectSpread({}, DOUBLE), {}, {
|
|
50
|
+
cnt: undefined
|
|
51
|
+
}))).toBe(2);
|
|
52
|
+
expect(lensCount(null)).toBe(0);
|
|
53
|
+
expect(lensCount({
|
|
54
|
+
cnt: 2,
|
|
55
|
+
thresholds: [],
|
|
56
|
+
lenses: []
|
|
57
|
+
})).toBe(0);
|
|
58
|
+
});
|
|
59
|
+
it('合法数据通过校验', () => {
|
|
60
|
+
expect(isZoomSkillValid(DOUBLE)).toBe(true);
|
|
61
|
+
expect(isZoomSkillValid(TRIPLE)).toBe(true);
|
|
62
|
+
});
|
|
63
|
+
it('畸形数据一律判不可用(不做部分降级)', () => {
|
|
64
|
+
// thresholds 长度不等于 cnt + 1
|
|
65
|
+
expect(isZoomSkillValid(_objectSpread(_objectSpread({}, DOUBLE), {}, {
|
|
66
|
+
thresholds: [1, 3]
|
|
67
|
+
}))).toBe(false);
|
|
68
|
+
// thresholds 非升序
|
|
69
|
+
expect(isZoomSkillValid(_objectSpread(_objectSpread({}, DOUBLE), {}, {
|
|
70
|
+
thresholds: [1, 6, 3]
|
|
71
|
+
}))).toBe(false);
|
|
72
|
+
// 单镜头(门控在 useLensZoom 里,这里只验校验函数本身仍认为数据合法)
|
|
73
|
+
expect(isZoomSkillValid({
|
|
74
|
+
cnt: 1,
|
|
75
|
+
thresholds: [1, 6],
|
|
76
|
+
lenses: [{
|
|
77
|
+
id: 0,
|
|
78
|
+
type: 1,
|
|
79
|
+
basicRatio: 1
|
|
80
|
+
}]
|
|
81
|
+
})).toBe(true);
|
|
82
|
+
expect(isZoomSkillValid(null)).toBe(false);
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
describe('ipc_multi_zoom 上报值解析', () => {
|
|
86
|
+
/** 协议参考上报值 */
|
|
87
|
+
|
|
88
|
+
it('解析上报 string,cnt 即镜头数', () => {
|
|
89
|
+
const skill = parseZoomSkill('{"cnt":2,"thresholds":[1,3,6],"lenses":[{"id":0,"type":0,"step":0.1,"basicRatio":1},{"id":1,"type":1,"step":0.1,"basicRatio":3}]}');
|
|
90
|
+
expect(lensCount(skill)).toBe(2);
|
|
91
|
+
expect(isZoomSkillValid(skill)).toBe(true);
|
|
92
|
+
expect(skill.lenses[1]).toEqual({
|
|
93
|
+
id: 1,
|
|
94
|
+
type: 1,
|
|
95
|
+
step: 0.1,
|
|
96
|
+
basicRatio: 3
|
|
97
|
+
});
|
|
98
|
+
expect(zoomBounds(skill)).toEqual([1, 6]);
|
|
99
|
+
});
|
|
100
|
+
it('对象值直接透传(调试注入 mockZoomSkill)', () => {
|
|
101
|
+
expect(parseZoomSkill(DOUBLE)).toBe(DOUBLE);
|
|
102
|
+
});
|
|
103
|
+
it('空值 / 畸形 JSON 返回 null,不抛错', () => {
|
|
104
|
+
expect(parseZoomSkill(undefined)).toBeNull();
|
|
105
|
+
expect(parseZoomSkill('')).toBeNull();
|
|
106
|
+
expect(parseZoomSkill('not json')).toBeNull();
|
|
107
|
+
expect(parseZoomSkill(2)).toBeNull();
|
|
108
|
+
});
|
|
109
|
+
it('单镜头设备(cnt = 1)不具备多镜头能力', () => {
|
|
110
|
+
const single = parseZoomSkill('{"cnt":1,"thresholds":[1,3],"lenses":[{"id":0,"type":0,"step":0.1,"basicRatio":1}]}');
|
|
111
|
+
expect(lensCount(single)).toBe(1);
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
describe('双层缩放换算', () => {
|
|
115
|
+
it('Δ 由 thresholds 区间跨度推导', () => {
|
|
116
|
+
// d ∈ [1, 4],lens0: (3-1)/(4-1) ≈ 0.667 lens1: (6-3)/(4-1) = 1.0
|
|
117
|
+
expect(deltaOf(DOUBLE, 0)).toBeCloseTo(2 / 3);
|
|
118
|
+
expect(deltaOf(DOUBLE, 1)).toBeCloseTo(1.0);
|
|
119
|
+
});
|
|
120
|
+
it('长焦区间 [3,6] 上 d 与画面倍率 1:1 递增', () => {
|
|
121
|
+
// 协议参考值:3 为 1 倍、4 为 2 倍、5 为 3 倍、6 为 4 倍
|
|
122
|
+
expect(toDisplayZoom(DOUBLE, 1, 1.0)).toBeCloseTo(3.0);
|
|
123
|
+
expect(toDisplayZoom(DOUBLE, 1, 2.0)).toBeCloseTo(4.0);
|
|
124
|
+
expect(toDisplayZoom(DOUBLE, 1, 3.0)).toBeCloseTo(5.0);
|
|
125
|
+
expect(toDisplayZoom(DOUBLE, 1, 4.0)).toBeCloseTo(6.0);
|
|
126
|
+
});
|
|
127
|
+
it('回读:同一个 d 在不同镜头上换算出不同画面倍率', () => {
|
|
128
|
+
// d=2.0 在短焦是画面 1.67x,在长焦是画面 4.0x —— 直接显示 d 就是错的
|
|
129
|
+
expect(toDisplayZoom(DOUBLE, 0, 2.0)).toBeCloseTo(1 + 2 / 3);
|
|
130
|
+
expect(toDisplayZoom(DOUBLE, 1, 2.0)).toBeCloseTo(4.0);
|
|
131
|
+
});
|
|
132
|
+
it('回读:d 边界对应镜头区间端点', () => {
|
|
133
|
+
expect(toDisplayZoom(DOUBLE, 0, D_MIN)).toBeCloseTo(1.0);
|
|
134
|
+
expect(toDisplayZoom(DOUBLE, 0, D_MAX)).toBeCloseTo(3.0);
|
|
135
|
+
expect(toDisplayZoom(DOUBLE, 1, D_MIN)).toBeCloseTo(3.0);
|
|
136
|
+
expect(toDisplayZoom(DOUBLE, 1, D_MAX)).toBeCloseTo(6.0);
|
|
137
|
+
});
|
|
138
|
+
it('回读:d 超出 [1,4] 被夹住,不溢出区间', () => {
|
|
139
|
+
expect(toDisplayZoom(DOUBLE, 0, 0.2)).toBeCloseTo(1.0);
|
|
140
|
+
expect(toDisplayZoom(DOUBLE, 0, 99)).toBeCloseTo(3.0);
|
|
141
|
+
});
|
|
142
|
+
it('往返自洽:toScaleMultiple(toDisplayZoom(d)) === d', () => {
|
|
143
|
+
[0, 1].forEach(index => {
|
|
144
|
+
[1.0, 1.5, 2.0, 2.7, 3.0, 4.0].forEach(d => {
|
|
145
|
+
const curM = toDisplayZoom(DOUBLE, index, d);
|
|
146
|
+
expect(toScaleMultiple(DOUBLE, index, curM)).toBeCloseTo(d, 5);
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
it('往返自洽:toDisplayZoom(toScaleMultiple(curM)) === curM', () => {
|
|
151
|
+
[1.0, 1.8, 2.9, 3.0].forEach(curM => {
|
|
152
|
+
expect(toDisplayZoom(DOUBLE, 0, toScaleMultiple(DOUBLE, 0, curM))).toBeCloseTo(curM, 5);
|
|
153
|
+
});
|
|
154
|
+
[3.0, 4.5, 5.2, 6.0].forEach(curM => {
|
|
155
|
+
expect(toDisplayZoom(DOUBLE, 1, toScaleMultiple(DOUBLE, 1, curM))).toBeCloseTo(curM, 5);
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
it('增减法而非乘法:长焦顶格是 3+3=6,不是 3×4=12', () => {
|
|
159
|
+
expect(toDisplayZoom(DOUBLE, 1, D_MAX)).toBeCloseTo(6.0);
|
|
160
|
+
expect(toDisplayZoom(DOUBLE, 1, D_MAX)).not.toBeCloseTo(12.0);
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
describe('镜头匹配', () => {
|
|
164
|
+
it('区间内正常命中', () => {
|
|
165
|
+
expect(matchLens(DOUBLE, 1.0)).toBe(0);
|
|
166
|
+
expect(matchLens(DOUBLE, 2.5)).toBe(0);
|
|
167
|
+
expect(matchLens(DOUBLE, 4.0)).toBe(1);
|
|
168
|
+
expect(matchLens(DOUBLE, 6.0)).toBe(1);
|
|
169
|
+
});
|
|
170
|
+
it('临界点归大镜头,避免横跳', () => {
|
|
171
|
+
// 3.0 同时落在 lens0 [1,3] 与 lens1 [3,6],取 basicRatio 大者
|
|
172
|
+
expect(matchLens(DOUBLE, 3.0)).toBe(1);
|
|
173
|
+
});
|
|
174
|
+
it('容差取镜头 step(0.1):2.9 起进长焦,2.8 仍在短焦', () => {
|
|
175
|
+
expect(matchLens(DOUBLE, 2.9)).toBe(1); // 2.9 在 lens1 的 [2.9, 6.1] 容差内 → 归大镜头
|
|
176
|
+
expect(matchLens(DOUBLE, 2.8)).toBe(0); // 超出 lens1 容差下界 → 短焦
|
|
177
|
+
expect(matchLens(DOUBLE, 3.1)).toBe(1);
|
|
178
|
+
});
|
|
179
|
+
it('容差随各镜头 step 变化,未声明 step 时用缺省 0.1', () => {
|
|
180
|
+
const coarse = {
|
|
181
|
+
cnt: 2,
|
|
182
|
+
thresholds: [1.0, 3.0, 6.0],
|
|
183
|
+
lenses: [{
|
|
184
|
+
id: 0,
|
|
185
|
+
type: 1,
|
|
186
|
+
step: 0.1,
|
|
187
|
+
basicRatio: 1.0
|
|
188
|
+
}, {
|
|
189
|
+
id: 1,
|
|
190
|
+
type: 1,
|
|
191
|
+
step: 0.5,
|
|
192
|
+
basicRatio: 3.0
|
|
193
|
+
} // 长焦步进更粗
|
|
194
|
+
]
|
|
195
|
+
};
|
|
196
|
+
expect(toleranceOf(coarse, 1)).toBe(0.5);
|
|
197
|
+
expect(matchLens(coarse, 2.6)).toBe(1); // 落在 lens1 的 [2.5, 6.5] 内
|
|
198
|
+
expect(matchLens(coarse, 2.4)).toBe(0);
|
|
199
|
+
const noStep = {
|
|
200
|
+
cnt: 2,
|
|
201
|
+
thresholds: [1.0, 3.0, 6.0],
|
|
202
|
+
lenses: [{
|
|
203
|
+
id: 0,
|
|
204
|
+
type: 1,
|
|
205
|
+
basicRatio: 1.0
|
|
206
|
+
}, {
|
|
207
|
+
id: 1,
|
|
208
|
+
type: 1,
|
|
209
|
+
basicRatio: 3.0
|
|
210
|
+
}]
|
|
211
|
+
};
|
|
212
|
+
expect(toleranceOf(noStep, 1)).toBe(DEFAULT_MATCH_TOLERANCE);
|
|
213
|
+
expect(matchLens(noStep, 2.9)).toBe(1);
|
|
214
|
+
expect(matchLens(noStep, 2.8)).toBe(0);
|
|
215
|
+
});
|
|
216
|
+
it('三目:跨两次临界点', () => {
|
|
217
|
+
expect(matchLens(TRIPLE, 1.5)).toBe(0);
|
|
218
|
+
expect(matchLens(TRIPLE, 4.0)).toBe(1);
|
|
219
|
+
expect(matchLens(TRIPLE, 9.0)).toBe(2);
|
|
220
|
+
expect(matchLens(TRIPLE, 6.0)).toBe(2); // 临界归大
|
|
221
|
+
});
|
|
222
|
+
it('镜头 id 反查下标', () => {
|
|
223
|
+
expect(indexOfLensId(DOUBLE, 1)).toBe(1);
|
|
224
|
+
expect(indexOfLensId(DOUBLE, 99)).toBe(0); // 找不到回落 0
|
|
225
|
+
});
|
|
226
|
+
});
|
|
227
|
+
describe('次刻度按各镜头 step 分段生成', () => {
|
|
228
|
+
/** 分段 step 不同:短焦 step 0.1、长焦 step 0.3 */
|
|
229
|
+
const MIXED_STEP = {
|
|
230
|
+
cnt: 2,
|
|
231
|
+
thresholds: [1.0, 3.0, 6.0],
|
|
232
|
+
lenses: [{
|
|
233
|
+
id: 0,
|
|
234
|
+
type: 1,
|
|
235
|
+
step: 0.1,
|
|
236
|
+
basicRatio: 1.0
|
|
237
|
+
}, {
|
|
238
|
+
id: 1,
|
|
239
|
+
type: 1,
|
|
240
|
+
step: 0.3,
|
|
241
|
+
basicRatio: 3.0
|
|
242
|
+
}]
|
|
243
|
+
};
|
|
244
|
+
it('双目:[1,3] 每 0.1 一格,[3,6] 每 0.3 一格', () => {
|
|
245
|
+
const ticks = buildTickValues(MIXED_STEP);
|
|
246
|
+
expect(ticks.filter(value => value <= 3)).toEqual([1, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 2.8, 2.9, 3]);
|
|
247
|
+
expect(ticks.filter(value => value >= 3)).toEqual([3, 3.3, 3.6, 3.9, 4.2, 4.5, 4.8, 5.1, 5.4, 5.7, 6]);
|
|
248
|
+
});
|
|
249
|
+
it('刻度升序、无重复、不越过上限', () => {
|
|
250
|
+
const ticks = buildTickValues(MIXED_STEP);
|
|
251
|
+
expect(ticks).toEqual([...ticks].sort((a, b) => a - b));
|
|
252
|
+
expect(new Set(ticks).size).toBe(ticks.length);
|
|
253
|
+
expect(Math.max(...ticks)).toBeCloseTo(6);
|
|
254
|
+
});
|
|
255
|
+
it('临界点只出现一次(相邻区间共用端点)', () => {
|
|
256
|
+
expect(buildTickValues(MIXED_STEP).filter(value => value === 3)).toHaveLength(1);
|
|
257
|
+
});
|
|
258
|
+
it('三目:三段各按自己的 step', () => {
|
|
259
|
+
expect(buildTickValues({
|
|
260
|
+
cnt: 3,
|
|
261
|
+
thresholds: [1, 3, 6, 12],
|
|
262
|
+
lenses: [{
|
|
263
|
+
id: 0,
|
|
264
|
+
type: 1,
|
|
265
|
+
step: 0.5,
|
|
266
|
+
basicRatio: 1
|
|
267
|
+
}, {
|
|
268
|
+
id: 1,
|
|
269
|
+
type: 1,
|
|
270
|
+
step: 1,
|
|
271
|
+
basicRatio: 3
|
|
272
|
+
}, {
|
|
273
|
+
id: 2,
|
|
274
|
+
type: 1,
|
|
275
|
+
step: 2,
|
|
276
|
+
basicRatio: 6
|
|
277
|
+
}]
|
|
278
|
+
})).toEqual([1, 1.5, 2, 2.5, 3, 4, 5, 6, 8, 10, 12]);
|
|
279
|
+
});
|
|
280
|
+
it('step 缺失时该段用缺省 0.1', () => {
|
|
281
|
+
expect(buildTickValues({
|
|
282
|
+
cnt: 1,
|
|
283
|
+
thresholds: [1, 1.5],
|
|
284
|
+
lenses: [{
|
|
285
|
+
id: 0,
|
|
286
|
+
type: 1,
|
|
287
|
+
basicRatio: 1
|
|
288
|
+
}]
|
|
289
|
+
})).toEqual([1, 1.1, 1.2, 1.3, 1.4, 1.5]);
|
|
290
|
+
});
|
|
291
|
+
});
|
|
292
|
+
describe('手势缩放上限按镜头换算', () => {
|
|
293
|
+
it('取该镜头区间上限对应的 d,受 D_MAX 约束', () => {
|
|
294
|
+
expect(maxScaleMultiple(DOUBLE, 0)).toBeCloseTo(D_MAX);
|
|
295
|
+
expect(maxScaleMultiple(DOUBLE, 1)).toBeCloseTo(D_MAX);
|
|
296
|
+
expect(maxScaleMultiple(TRIPLE, 2)).toBeCloseTo(D_MAX);
|
|
297
|
+
});
|
|
298
|
+
it('换算结果落在镜头区间上限上(回代 toDisplayZoom 自洽)', () => {
|
|
299
|
+
expect(toDisplayZoom(DOUBLE, 0, maxScaleMultiple(DOUBLE, 0))).toBeCloseTo(3.0);
|
|
300
|
+
expect(toDisplayZoom(DOUBLE, 1, maxScaleMultiple(DOUBLE, 1))).toBeCloseTo(6.0);
|
|
301
|
+
});
|
|
302
|
+
});
|
|
303
|
+
describe('转盘区间与刻度', () => {
|
|
304
|
+
it('区间取 thresholds 首尾(不使用 maxZoomSettings)', () => {
|
|
305
|
+
expect(zoomBounds(DOUBLE)).toEqual([1.0, 6.0]);
|
|
306
|
+
expect(zoomBounds(TRIPLE)).toEqual([1.0, 12.0]);
|
|
307
|
+
});
|
|
308
|
+
it('主刻度 = 各镜头光学倍数 + 上限,去重升序', () => {
|
|
309
|
+
expect(buildMarks(DOUBLE)).toEqual([{
|
|
310
|
+
value: 1,
|
|
311
|
+
label: '1'
|
|
312
|
+
}, {
|
|
313
|
+
value: 3,
|
|
314
|
+
label: '3'
|
|
315
|
+
}, {
|
|
316
|
+
value: 6,
|
|
317
|
+
label: '6'
|
|
318
|
+
}]);
|
|
319
|
+
expect(buildMarks(TRIPLE).map(mark => mark.value)).toEqual([1, 3, 6, 12]);
|
|
320
|
+
});
|
|
321
|
+
it('非整数倍率保留一位小数', () => {
|
|
322
|
+
expect(buildMarks({
|
|
323
|
+
cnt: 2,
|
|
324
|
+
thresholds: [1.0, 2.5, 5.0],
|
|
325
|
+
lenses: [{
|
|
326
|
+
id: 0,
|
|
327
|
+
type: 1,
|
|
328
|
+
basicRatio: 1.0
|
|
329
|
+
}, {
|
|
330
|
+
id: 1,
|
|
331
|
+
type: 1,
|
|
332
|
+
basicRatio: 2.5
|
|
333
|
+
}]
|
|
334
|
+
}).map(mark => mark.label)).toEqual(['1', '2.5', '5']);
|
|
335
|
+
});
|
|
336
|
+
});
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 镜头能力解析与镜头切换下发。协议相关的不确定性都收敛在本文件。
|
|
3
|
+
*
|
|
4
|
+
* 协议来源:《面板小程序 V1.6.0_零散优化+多目变焦》§4
|
|
5
|
+
*
|
|
6
|
+
* 能力取自 ipc_multi_zoom DP 的 string 值,cnt <= 1 不出现转盘入口:
|
|
7
|
+
* {"cnt":2,"thresholds":[1,3,6],"lenses":[{"id":0,"type":0,"step":0.1,"basicRatio":1},…]}
|
|
8
|
+
* 切镜头走 ty.ipc.switchChannel({ deviceId, channel }),channel 即上报的子镜头 id。
|
|
9
|
+
* 出流后用 ty.ipc.queryCurrentChannel 回读当前镜头;
|
|
10
|
+
* 设备侧 / 其他端切镜头由 ty.ipc.onChannelChange 事件通知。
|
|
11
|
+
*/
|
|
12
|
+
export type Lens = {
|
|
13
|
+
/** 镜头 ID;切镜头时作为 ty.ipc.switchChannel 的 channel 下发 */
|
|
14
|
+
id: number;
|
|
15
|
+
/** 0 球机(PTZ) · 1 枪机(Bullet) */
|
|
16
|
+
type: 0 | 1;
|
|
17
|
+
/** 镜头固定光学倍数(定焦);按钮显示 + 双层 base + 下发目标倍数 */
|
|
18
|
+
basicRatio: number;
|
|
19
|
+
/** 步进精度 */
|
|
20
|
+
step?: number;
|
|
21
|
+
};
|
|
22
|
+
export type ZoomSkill = {
|
|
23
|
+
/** 镜头数量(= 按钮数),协议保证与 lenses.length 一致;统一经 lensCount() 取用 */
|
|
24
|
+
cnt?: number;
|
|
25
|
+
/** [起始, 切换点…, 手势放大上限],长度 = cnt + 1,升序 */
|
|
26
|
+
thresholds: number[];
|
|
27
|
+
/** 镜头数组,按 basicRatio 升序 */
|
|
28
|
+
lenses: Lens[];
|
|
29
|
+
};
|
|
30
|
+
export type CurrentLensState = {
|
|
31
|
+
/** 对应 Lens.id */
|
|
32
|
+
lens_id: number;
|
|
33
|
+
/** 当前本地数字缩放 d;宿主不回该字段时按 1.0 处理 */
|
|
34
|
+
multiple: number;
|
|
35
|
+
};
|
|
36
|
+
/** channelChange 事件载荷 */
|
|
37
|
+
export type ChannelChangeEvent = {
|
|
38
|
+
/** 设备 id;宿主未带该字段时不做设备过滤 */
|
|
39
|
+
deviceId?: string;
|
|
40
|
+
/** 切换后的镜头通道,对应 Lens.id */
|
|
41
|
+
channel: number;
|
|
42
|
+
};
|
|
43
|
+
/** 能力 DP:其 string 值即镜头能力描述,解析出的 cnt > 1 才显示入口 */
|
|
44
|
+
export { MULTI_ZOOM as MULTI_ZOOM_DP_CODE } from '../../utils/content/dpCode';
|
|
45
|
+
/** MOCK 数据:与协议参考上报值一致的双目定焦(短焦 1.0x / 临界 3.0x / 上限 6.0x) */
|
|
46
|
+
export declare const MOCK_ZOOM_SKILL: ZoomSkill;
|
|
47
|
+
/**
|
|
48
|
+
* 镜头数量。以 cnt 为判定字段;
|
|
49
|
+
* 固件漏填时回落到 lenses.length,两者不一致时告警(协议保证一致)。
|
|
50
|
+
*/
|
|
51
|
+
export declare const lensCount: (skill?: ZoomSkill | null) => number;
|
|
52
|
+
/** 校验数据自洽性。半套数据画出的刻度是错的,比不显示更糟,故不做部分降级 */
|
|
53
|
+
export declare const isZoomSkillValid: (skill?: ZoomSkill | null) => boolean;
|
|
54
|
+
/**
|
|
55
|
+
* 解析 ipc_multi_zoom DP 上报的 string 值为镜头能力。
|
|
56
|
+
* @param value DP 值;调试注入的对象(mockZoomSkill)直接透传,两条来源共用同一校验链路
|
|
57
|
+
*/
|
|
58
|
+
export declare const parseZoomSkill: (value?: unknown) => ZoomSkill | null;
|
|
59
|
+
/**
|
|
60
|
+
* 切换物理镜头。channel 取上报的子镜头 id 而非数组下标 —— 固件可上报非连续 id。
|
|
61
|
+
* 返回 false(不支持 / 失败)时由 useLensZoom 回滚读数,无回调另有 SWITCH_LENS_TIMEOUT 兜底。
|
|
62
|
+
*/
|
|
63
|
+
export declare const switchLens: (devId: string, lens: Lens) => Promise<boolean>;
|
|
64
|
+
/** 打印播放器实例上的方法名;方法名对不上时用来确认实例究竟提供了什么 */
|
|
65
|
+
export declare const dumpPlayerApis: (IPCPlayerInstance: any, keyword?: string) => void;
|
|
66
|
+
/**
|
|
67
|
+
* 开关全景小窗(小窗画面为当前镜头的全景)。
|
|
68
|
+
*
|
|
69
|
+
* 画面停在镜头光学正倍数上时不需要小窗,在镜头区间内数字放大后才需要。
|
|
70
|
+
* 调用方(useLensZoom)已按 devId 做过去重,这里只管下发,不判重。
|
|
71
|
+
*/
|
|
72
|
+
export declare const showSmallMonitor: (IPCPlayerInstance: any, show: boolean) => void;
|
|
73
|
+
/**
|
|
74
|
+
* 查询当前镜头与本地缩放,用于出流后 / 重连后同步。
|
|
75
|
+
* 返回 null(不支持 / 失败 / 超时)时调用方保持现状,不重置镜头。
|
|
76
|
+
*/
|
|
77
|
+
export declare const queryCurrentLens: (devId: string) => Promise<CurrentLensState | null>;
|
|
78
|
+
/**
|
|
79
|
+
* 宿主是否支持镜头切换事件。
|
|
80
|
+
* 切镜头的收尾(画面归 1 倍 + 刷读数)以该事件为准,不支持时只能退回「switchChannel 成功即收尾」。
|
|
81
|
+
*/
|
|
82
|
+
export declare const isChannelChangeSupported: () => boolean;
|
|
83
|
+
/**
|
|
84
|
+
* 打印 ty.ipc 上与 channel 相关的方法名(顺原型链收集,方法可能挂在原型上)。
|
|
85
|
+
* 真机上「事件为什么不来」第一步就是确认宿主到底提供了哪个名字。
|
|
86
|
+
*/
|
|
87
|
+
export declare const dumpChannelApis: () => void;
|
|
88
|
+
/** 订阅镜头切换事件(自己下发 / 设备侧 / 其他端切镜头都会上报),返回取消订阅函数 */
|
|
89
|
+
export declare const subscribeChannelChange: (devId: string, handler: (e: ChannelChangeEvent) => void) => (() => void);
|