gis-view-webgl2 0.1.11 → 0.1.13
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 +0 -24
- package/dist/gis-view.css +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +524 -33
- package/dist/index.js +1 -1
- package/docs/AI/345/257/271/350/257/235/346/261/207/346/200/273.md +156 -8
- package/docs/GisView.md +6 -6
- package/docs/ai/06-/344/274/232/350/257/235/347/264/242/345/274/225/344/270/216/345/244/215/346/237/245/346/226/271/346/263/225.md +157 -7
- package/docs/demos/BackgroundDemo.vue +600 -0
- package/docs/demos/ChannelDemo.vue +145 -3
- package/docs/demos/StyleDemo.vue +280 -69
- package/docs/demos/api-index.js +35 -19
- package/docs/demos/demos.js +26 -18
- package/docs/demos/gis-view-demo/demo.css +76 -0
- package/docs/demos/gis-view-demo/panels/StylePanels.vue +24 -8
- package/docs/demos/gis-view-demo/panels/ViewPanels.vue +33 -3
- package/docs/demos/gis-view-demo/useGisViewDemo.js +236 -22
- package/docs/format/02-/350/212/202/347/202/271/344/270/216/347/272/277/350/267/257.md +1 -1
- package/docs/format/03-/346/213/220/347/202/271/350/243/205/351/245/260/344/270/216/346/240/267/345/274/217.md +3 -3
- package/docs/from0/06-/344/273/216/346/225/260/346/215/256/345/210/260/345/256/236/344/276/213-/350/247/243/346/236/220/345/261/202.md +13 -11
- package/docs/from0/15-/351/231/204/345/275/225-/345/270/270/351/207/217/351/200/237/346/237/245/344/270/216/350/270/251/345/235/221/346/270/205/345/215/225.md +1 -1
- package/docs/index.html +2 -2
- package/docs/internals/10-/350/247/204/345/210/231/346/235/241/344/273/266/344/270/216/347/212/266/346/200/201/346/240/267/345/274/217.md +3 -3
- package/docs/internals/13-/351/271/260/347/234/274/345/233/276.md +1 -1
- package/docs/internals/14-/350/203/214/346/231/257/345/261/202.md +1 -0
- package/docs/internals/15-03-/351/200/220/350/275/256/350/256/260/345/275/225-/346/200/247/350/203/275/344/270/216/344/277/256/345/244/215-/344/270/213.md +199 -0
- package/docs/internals/17-/350/260/203/350/257/225/344/270/216/346/211/251/345/261/225/345/273/272/350/256/256.md +1 -1
- package/docs/internals/18-/346/200/247/350/203/275/345/256/236/346/265/213/344/270/216WebGPU/350/257/204/344/274/260.md +32 -0
- package/docs/manual/02-/345/235/220/346/240/207/344/270/216/346/225/260/346/215/256.md +1 -1
- package/docs/manual/03-/351/205/215/347/275/256/351/241/271.md +217 -26
- package/docs/manual/07-/346/214/207/351/222/210/344/270/216/350/246/201/347/264/240/347/274/226/350/276/221.md +2 -2
- package/docs/manual/08-/351/200/211/344/270/255/344/270/216/346/213/220/347/202/271.md +37 -4
- package/docs/manual/09-/351/200/232/351/201/223/344/270/216/345/244/232/345/233/236/347/272/277.md +58 -1
- package/docs/manual/11-/346/240/267/345/274/217/344/270/216/350/247/204/345/210/231.md +59 -8
- package/docs/manual/12-/346/240/207/347/255/276/344/270/216/350/243/205/351/245/260.md +1 -1
- package/docs/manual/13-/345/212/250/346/225/210/344/270/216/345/233/276/345/205/203.md +220 -2
- package/docs/manual/14-/350/247/206/345/233/276/344/270/216/347/255/233/351/200/211.md +77 -16
- package/docs/manual/15-/345/257/274/345/207/272/344/270/216/351/233/206/346/210/220.md +30 -17
- package/docs/manual/16-/345/256/236/344/276/213/346/226/271/346/263/225/346/200/273/350/241/250.md +11 -4
- package/docs/manual/17-/345/217/202/346/225/260/351/200/237/346/237/245.md +17 -8
- package/docs/manual/18-/351/200/220/346/226/271/346/263/225/347/244/272/344/276/213.md +128 -4
- package/docs/manual/19-/350/257/273/346/225/260/344/270/216/346/213/226/346/213/275/351/242/204/350/247/210.md +2 -2
- package/docs/manual/20-/346/200/247/350/203/275/344/270/216/345/244/247/346/225/260/346/215/256.md +13 -1
- package/docs/manual/21-/350/257/264/346/230/216/344/270/216/345/270/270/350/247/201/351/227/256/351/242/230.md +4 -1
- package/docs/steps/index.html +1 -1
- package/docs/steps/selftest-demo.html +2 -2
- package/docs/steps/selftest-demos.html +626 -11
- package/docs/steps/selftest-docs.html +8 -4
- package/docs/steps/selftest-features.html +1428 -2
- package/docs/steps/selftest-perf.html +296 -25
- package/docs/steps/selftest-scale.html +61 -3
- package/docs/steps/selftest-select.html +303 -1
- package/docs/steps/step-06-style.js +3 -2
- package/package.json +2 -2
|
@@ -91,8 +91,8 @@
|
|
|
91
91
|
// 1. 外壳:默认综合示例,页签齐全
|
|
92
92
|
const loaded = await canvasReady()
|
|
93
93
|
check('演示外壳把默认演示(综合示例)挂起来了', Boolean(loaded), loaded ? 'canvas 就绪' : '没等到 canvas')
|
|
94
|
-
check('页签列出全部演示(
|
|
95
|
-
check('页头的演示数量直接跟随注册表(
|
|
94
|
+
check('页签列出全部演示(23 个:22 个功能 + 综合)', tabs().length === 23, `${tabs().length} 个页签:${tabs().map(tab => tab.textContent.trim()).join(' / ')}`)
|
|
95
|
+
check('页头的演示数量直接跟随注册表(23 个)', (document.querySelector('.page-header__count')?.textContent ?? '').includes('23 个'), document.querySelector('.page-header__count')?.textContent?.trim() ?? '没有页头计数')
|
|
96
96
|
check('默认页签是综合示例', (document.querySelector('.demo-shell__tab--active')?.textContent ?? '').includes('综合'), document.querySelector('.demo-shell__tab--active')?.textContent?.trim() ?? '')
|
|
97
97
|
check('默认页签写进地址栏(刷新还停在同一个演示)', location.search.includes('demo=full'), location.search)
|
|
98
98
|
check('综合示例的面板照旧在(拆分没有动它)', document.querySelectorAll('.demo-panel-buttons button').length >= 6, `${document.querySelectorAll('.demo-panel-buttons button').length} 个面板按钮`)
|
|
@@ -122,7 +122,7 @@
|
|
|
122
122
|
const afterBack = document.querySelector('.demo-shell__tab--active')?.textContent.trim() ?? ''
|
|
123
123
|
check('键盘 [ 往回翻(基础视图回到综合示例)', afterBack.includes('综合'), afterBack)
|
|
124
124
|
const eyebrow = document.querySelector('.demo-shell__eyebrow')?.textContent.trim() ?? ''
|
|
125
|
-
check('当前演示显示分组与序号(综合 ·
|
|
125
|
+
check('当前演示显示分组与序号(综合 · 23 / 23)', eyebrow.includes('综合') && eyebrow.includes('23 / 23'), eyebrow)
|
|
126
126
|
document.querySelector('[data-demo=demo-next]')?.click()
|
|
127
127
|
await wait(60)
|
|
128
128
|
const afterStepNext = document.querySelector('.demo-shell__tab--active')?.textContent.trim() ?? ''
|
|
@@ -238,8 +238,9 @@
|
|
|
238
238
|
aa.destroy()
|
|
239
239
|
aaHost.remove()
|
|
240
240
|
// 2. 每个功能演示都切一遍:画布起得来、说明与读数有东西
|
|
241
|
-
const demoSpecs = [
|
|
242
|
-
{ tab: '基础视图', id: 'basic' },
|
|
241
|
+
const demoSpecs = [
|
|
242
|
+
{ tab: '基础视图', id: 'basic' },
|
|
243
|
+
{ tab: '背景与网架', id: 'background' },
|
|
243
244
|
{ tab: '标签交互', id: 'labels' },
|
|
244
245
|
{ tab: '鹰眼图配置', id: 'minimap' },
|
|
245
246
|
{ tab: '样式与规则', id: 'style' },
|
|
@@ -260,14 +261,85 @@
|
|
|
260
261
|
]
|
|
261
262
|
for (const spec of demoSpecs) {
|
|
262
263
|
const clicked = await clickTab(spec.tab)
|
|
263
|
-
const ready = clicked ? await canvasReady() : null
|
|
264
|
-
const panel = document.querySelector('.dv-demo .dv-panel')
|
|
265
|
-
const active = document.querySelector('.demo-shell__tab--active')?.textContent.trim() ?? ''
|
|
264
|
+
const ready = clicked ? await canvasReady() : null
|
|
265
|
+
const panel = document.querySelector('.dv-demo .dv-panel')
|
|
266
|
+
const active = document.querySelector('.demo-shell__tab--active')?.textContent.trim() ?? ''
|
|
266
267
|
check(`切到「${spec.tab}」:画布与读数面板都起来了`, Boolean(ready) && Boolean(panel) && active === spec.tab, `${ready ? 'canvas 就绪' : '没有 canvas'} / ${panel ? `${panel.querySelectorAll('.dv-group').length} 组读数` : '没有面板'} / 当前页签 ${active}`)
|
|
267
268
|
await wait(260)
|
|
268
269
|
check(`「${spec.tab}」把演示 id 写进地址栏(?demo=${spec.id})`, location.search.includes(`demo=${spec.id}`), location.search)
|
|
269
270
|
}
|
|
270
271
|
|
|
272
|
+
// 2.0.0 样式与规则:单 / 多要素补丁、交互状态样式与详情查询都能从面板跑通
|
|
273
|
+
if (await clickTab('样式与规则')) {
|
|
274
|
+
const ready = await canvasReady()
|
|
275
|
+
const demo = await until(() => [...document.querySelectorAll('.dv-demo')].find(node => node.textContent.includes('单个 / 多个要素样式')), 8000)
|
|
276
|
+
const setup = demo?.__vueParentComponent?.setupState
|
|
277
|
+
const view = await until(() => setup?.view, 8000)
|
|
278
|
+
const click = key => document.querySelector(`[data-demo="${key}"]`)?.click()
|
|
279
|
+
const text = key => document.querySelector(`[data-demo="${key}"]`)?.textContent.trim() ?? ''
|
|
280
|
+
const pointTarget = document.querySelector('[data-demo="style-point-target"]')
|
|
281
|
+
const lineTarget = document.querySelector('[data-demo="style-line-target"]')
|
|
282
|
+
if (ready && view && pointTarget && lineTarget) {
|
|
283
|
+
await until(() => view.listPoints().length > 0 && view.listLines().length > 0, 5000)
|
|
284
|
+
const pointId = pointTarget.value
|
|
285
|
+
const lineId = lineTarget.value
|
|
286
|
+
click('style-update-point')
|
|
287
|
+
await wait(120)
|
|
288
|
+
const singlePoint = view.getData().points.find(point => String(point.id) === String(pointId))
|
|
289
|
+
check('样式与规则 demo:updatePoint 改单个节点的颜色、尺寸与图标',
|
|
290
|
+
singlePoint?.color === '#f97316' && singlePoint?.size === 18 && singlePoint?.symbol?.type === 'square' && text('style-edit-readout').includes('updatePoint'),
|
|
291
|
+
JSON.stringify({ point: singlePoint, readout: text('style-edit-readout') }))
|
|
292
|
+
|
|
293
|
+
click('style-patch-points')
|
|
294
|
+
await wait(120)
|
|
295
|
+
const batchPoints = view.getData().points.slice(0, 3)
|
|
296
|
+
check('样式与规则 demo:patchPoints 一次改多个节点',
|
|
297
|
+
batchPoints.every(point => point.color === '#22c55e' && point.size === 15) && text('style-edit-readout').includes('patchPoints'),
|
|
298
|
+
JSON.stringify({ colors: batchPoints.map(point => point.color), readout: text('style-edit-readout') }))
|
|
299
|
+
|
|
300
|
+
click('style-update-line')
|
|
301
|
+
await wait(120)
|
|
302
|
+
const singleLine = view.getData().lines.find(line => String(line.id) === String(lineId))
|
|
303
|
+
check('样式与规则 demo:updateLine 改单条线路的颜色、线宽与线型',
|
|
304
|
+
singleLine?.color === '#ec4899' && singleLine?.width === 4 && singleLine?.lineType === 'dashed' && text('style-edit-readout').includes('updateLine'),
|
|
305
|
+
JSON.stringify({ line: singleLine, readout: text('style-edit-readout') }))
|
|
306
|
+
|
|
307
|
+
click('style-patch-lines')
|
|
308
|
+
await wait(120)
|
|
309
|
+
const batchLines = view.getData().lines.slice(0, 3)
|
|
310
|
+
check('样式与规则 demo:patchLines 一次改多条线路',
|
|
311
|
+
batchLines.every(line => line.color === '#14b8a6' && line.width === 2.8 && line.lineType === 'dotted') && text('style-edit-readout').includes('patchLines'),
|
|
312
|
+
JSON.stringify({ colors: batchLines.map(line => line.color), readout: text('style-edit-readout') }))
|
|
313
|
+
|
|
314
|
+
const options = view.getOptions()
|
|
315
|
+
click('style-query')
|
|
316
|
+
await wait(80)
|
|
317
|
+
const detail = text('style-detail-readout')
|
|
318
|
+
check('样式与规则 demo:单条 / 多条节点、线路与通道详情都有读数',
|
|
319
|
+
detail.includes(`节点单查:${pointId}`) && detail.includes('节点批量:3 条') && detail.includes(`线路单查:${lineId}`) && detail.includes('线路批量:3 条') && detail.includes('通道单查:channel-a') && detail.includes('getChannels() 3 条'),
|
|
320
|
+
detail)
|
|
321
|
+
check('样式与规则 demo:单选 / 多选 / 框选 / 级联状态样式都写进 options',
|
|
322
|
+
options.pointSelectStyle?.color === '#ffd166' && options.pointMultiSelectStyle?.color === '#f97316' && options.pointBoxSelectStyle?.color === '#22d3ee' && options.lineSelectStyle?.color === '#ffd166' && options.lineMultiSelectStyle?.color === '#f97316' && options.cascadeHighlight?.pointStyle?.color === '#22d3ee',
|
|
323
|
+
JSON.stringify({ pointSelect: options.pointSelectStyle, pointMulti: options.pointMultiSelectStyle, pointBox: options.pointBoxSelectStyle, lineSelect: options.lineSelectStyle, lineMulti: options.lineMultiSelectStyle, cascade: options.cascadeHighlight }))
|
|
324
|
+
|
|
325
|
+
click('style-select-box')
|
|
326
|
+
await wait(100)
|
|
327
|
+
check('样式与规则 demo:框选按钮通过 selectInBox 真的形成框选', view.getSelectionData().pointCount > 0, JSON.stringify(view.getSelectionInfo()))
|
|
328
|
+
|
|
329
|
+
click('style-reset')
|
|
330
|
+
await wait(120)
|
|
331
|
+
check('样式与规则 demo:恢复原始数据清掉单 / 多要素补丁',
|
|
332
|
+
view.getData().points[0]?.color === undefined && view.getData().lines[0]?.color === undefined && view.getSelectionData().count === 0,
|
|
333
|
+
JSON.stringify({ point: view.getData().points[0], line: view.getData().lines[0], selection: view.getSelectionInfo() }))
|
|
334
|
+
}
|
|
335
|
+
else {
|
|
336
|
+
check('样式与规则 demo:画布、实例与下拉控件齐全', false, `${ready ? 'canvas 就绪' : 'canvas 未就绪'} / view=${Boolean(view)} / point=${Boolean(pointTarget)} / line=${Boolean(lineTarget)}`)
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
else {
|
|
340
|
+
check('样式与规则 demo:页签在', false, '没找到「样式与规则」页签')
|
|
341
|
+
}
|
|
342
|
+
|
|
271
343
|
// 2.0.1 基础视图:比例读写与空闲检测都能从面板操作并回读
|
|
272
344
|
if (await clickTab('基础视图')) {
|
|
273
345
|
const ready = await canvasReady()
|
|
@@ -354,6 +426,394 @@
|
|
|
354
426
|
check('基础视图:页签在', false, '没找到「基础视图」页签')
|
|
355
427
|
}
|
|
356
428
|
|
|
429
|
+
// 2.0.2 背景与网架:先有网架再加背景,四角拖动、隐藏 / 透明度与 GeoJSON 目标范围
|
|
430
|
+
if (await clickTab('背景与网架')) {
|
|
431
|
+
const ready = await canvasReady()
|
|
432
|
+
await wait(350)
|
|
433
|
+
const demo = await until(() => [...document.querySelectorAll('.dv-demo')].find(node => node.querySelector('[data-demo=background-add-image]')), 8000)
|
|
434
|
+
const setup = demo?.__vueParentComponent?.setupState
|
|
435
|
+
const view = await until(() => setup?.view, 8000)
|
|
436
|
+
const canvas = demo?.querySelector('canvas.gis-view__canvas') ?? demo?.querySelector('canvas')
|
|
437
|
+
const click = key => document.querySelector(`[data-demo=${key}]`)?.click()
|
|
438
|
+
const text = key => document.querySelector(`[data-demo=${key}]`)?.textContent.trim() ?? ''
|
|
439
|
+
const addImage = document.querySelector('[data-demo=background-add-image]')
|
|
440
|
+
const addGeo = document.querySelector('[data-demo=background-add-geojson]')
|
|
441
|
+
const networkToggle = document.querySelector('[data-demo=background-toggle-network]')
|
|
442
|
+
const networkRange = document.querySelector('[data-demo=background-network-opacity]')
|
|
443
|
+
const rotationToggle = document.querySelector('[data-demo=background-rotation-enabled]')
|
|
444
|
+
check('背景与网架:画布、添加按钮、隐藏与透明度控件齐全',
|
|
445
|
+
Boolean(ready && view && canvas && addImage && addGeo && networkToggle && networkRange && rotationToggle),
|
|
446
|
+
`${ready ? 'canvas 就绪' : '没有 canvas'} / view=${Boolean(view)} / 控件 ${[addImage, addGeo, networkToggle, networkRange, rotationToggle].filter(Boolean).length}/5`)
|
|
447
|
+
if (ready && view && canvas && addImage && addGeo && networkToggle && networkRange && rotationToggle) {
|
|
448
|
+
const beforeImage = view.getResolvedBackground()
|
|
449
|
+
check('背景与网架:初始只渲染网架、没有背景图或 GeoJSON',
|
|
450
|
+
view.getOptions().networkVisible === true && !beforeImage?.image && !beforeImage?.geoJson,
|
|
451
|
+
JSON.stringify({ networkVisible: view.getOptions().networkVisible, background: view.getOptions().background }))
|
|
452
|
+
click('background-add-image')
|
|
453
|
+
await until(() => view.getResolvedBackground()?.image?.quad?.length === 16, 5000)
|
|
454
|
+
const imageCorners = view.getOptions().background?.image?.corners
|
|
455
|
+
check('背景与网架:网架之后再加图片,默认只生成四个角手柄且不显示旋转按钮',
|
|
456
|
+
imageCorners?.length === 4 && view.getResolvedBackground()?.image?.quad?.length === 16 &&
|
|
457
|
+
document.querySelectorAll('.gis-view__background-editor-handle:not([hidden])').length === 4 &&
|
|
458
|
+
document.querySelector('[data-gis-background-rotate]:not([hidden])') === null,
|
|
459
|
+
`corners=${imageCorners?.length ?? 0} / quad=${view.getResolvedBackground()?.image?.quad?.length ?? 0} / handles=${document.querySelectorAll('.gis-view__background-editor-handle:not([hidden])').length} / rotate=${Boolean(document.querySelector('[data-gis-background-rotate]:not([hidden])'))}`)
|
|
460
|
+
await wait(450)
|
|
461
|
+
check('背景与网架:添加后自动进入编辑模式,锁定比例且关闭旋转时只有四角缩放点',
|
|
462
|
+
setup.backgroundEditing === true && view.getOptions().backgroundEditing === true &&
|
|
463
|
+
document.querySelector('[data-gis-background-editor]') !== null &&
|
|
464
|
+
document.querySelector('[data-gis-background-rotate]:not([hidden])') === null &&
|
|
465
|
+
document.querySelector('[data-demo=background-edit-mode]')?.checked === true &&
|
|
466
|
+
rotationToggle.checked === false &&
|
|
467
|
+
document.querySelectorAll('.gis-view__background-editor-handle:not([hidden])').length === 4 &&
|
|
468
|
+
text('background-edit-point-summary').includes('4 个编辑点'),
|
|
469
|
+
JSON.stringify({ setup: setup.backgroundEditing, engine: view.getOptions().backgroundEditing, handles: document.querySelectorAll('.gis-view__background-editor-handle:not([hidden])').length, rotate: Boolean(document.querySelector('[data-gis-background-rotate]:not([hidden])')) }))
|
|
470
|
+
const moveSurface = document.querySelector('[data-gis-background-move]')
|
|
471
|
+
const moveRect = moveSurface?.getBoundingClientRect()
|
|
472
|
+
const moveCenterBefore = [...setup.editCenter]
|
|
473
|
+
const moveCornersBefore = view.getOptions().background.image.corners.map(corner => [...corner])
|
|
474
|
+
const moveHandle = document.querySelector('[data-gis-background-handle=nw]')
|
|
475
|
+
const moveHandleBefore = moveHandle?.getBoundingClientRect()
|
|
476
|
+
let handlesHeldBeforeFrame = false
|
|
477
|
+
let handlesMatchedFrame = false
|
|
478
|
+
let moveFrameReport = ''
|
|
479
|
+
if (moveSurface && moveRect) {
|
|
480
|
+
const pointer = { bubbles: true, cancelable: true, composed: true, pointerId: 11, pointerType: 'mouse', isPrimary: true, button: 0, buttons: 1 }
|
|
481
|
+
const startX = moveRect.left + moveRect.width / 2
|
|
482
|
+
const startY = moveRect.top + moveRect.height / 2
|
|
483
|
+
moveSurface.dispatchEvent(new PointerEvent('pointerdown', { ...pointer, clientX: startX, clientY: startY }))
|
|
484
|
+
window.dispatchEvent(new PointerEvent('pointermove', { ...pointer, clientX: startX + 46, clientY: startY + 28 }))
|
|
485
|
+
const handleBeforeFrame = moveHandle?.getBoundingClientRect()
|
|
486
|
+
const cornersBeforeFrame = view.getOptions().background.image.corners
|
|
487
|
+
handlesHeldBeforeFrame = Boolean(moveHandleBefore && handleBeforeFrame) &&
|
|
488
|
+
Math.abs(handleBeforeFrame.left - moveHandleBefore.left) < 0.1 &&
|
|
489
|
+
Math.abs(handleBeforeFrame.top - moveHandleBefore.top) < 0.1 &&
|
|
490
|
+
cornersBeforeFrame.every((corner, index) =>
|
|
491
|
+
Math.abs(corner[0] - moveCornersBefore[index][0]) < 1e-9 &&
|
|
492
|
+
Math.abs(corner[1] - moveCornersBefore[index][1]) < 1e-9)
|
|
493
|
+
await new Promise(resolve => requestAnimationFrame(resolve))
|
|
494
|
+
await wait(50)
|
|
495
|
+
const cornersAfterFrame = view.getOptions().background.image.corners
|
|
496
|
+
const handleAfterFrame = moveHandle?.getBoundingClientRect()
|
|
497
|
+
const projectedDelta = [
|
|
498
|
+
view.project(cornersAfterFrame[0][0], cornersAfterFrame[0][1])[0] - view.project(moveCornersBefore[0][0], moveCornersBefore[0][1])[0],
|
|
499
|
+
view.project(cornersAfterFrame[0][0], cornersAfterFrame[0][1])[1] - view.project(moveCornersBefore[0][0], moveCornersBefore[0][1])[1]
|
|
500
|
+
]
|
|
501
|
+
const handleDelta = moveHandleBefore && handleAfterFrame
|
|
502
|
+
? [handleAfterFrame.left - moveHandleBefore.left, handleAfterFrame.top - moveHandleBefore.top]
|
|
503
|
+
: [Infinity, Infinity]
|
|
504
|
+
handlesMatchedFrame = Math.hypot(projectedDelta[0], projectedDelta[1]) > 0.5 &&
|
|
505
|
+
Math.hypot(handleDelta[0] - projectedDelta[0], handleDelta[1] - projectedDelta[1]) < 1.5
|
|
506
|
+
moveFrameReport = JSON.stringify({ projectedDelta, handleDelta, held: handlesHeldBeforeFrame, matched: handlesMatchedFrame })
|
|
507
|
+
window.dispatchEvent(new PointerEvent('pointerup', { ...pointer, button: 0, buttons: 0, clientX: startX + 46, clientY: startY + 28 }))
|
|
508
|
+
}
|
|
509
|
+
await wait(350)
|
|
510
|
+
const moveCornersAfter = view.getOptions().background.image.corners
|
|
511
|
+
const moveCenterAfter = setup.editCenter
|
|
512
|
+
const moveDelta = [moveCenterAfter[0] - moveCenterBefore[0], moveCenterAfter[1] - moveCenterBefore[1]]
|
|
513
|
+
check('背景与网架:拖背景内部整体移动,四角同步平移且旋转角不变',
|
|
514
|
+
Math.hypot(moveDelta[0], moveDelta[1]) > 0.05 && setup.editRotation === 0 &&
|
|
515
|
+
moveCornersAfter.length === 4 && moveCornersAfter.every((corner, index) =>
|
|
516
|
+
Math.abs(corner[0] - moveCornersBefore[index][0] - moveDelta[0]) < 0.02 &&
|
|
517
|
+
Math.abs(corner[1] - moveCornersBefore[index][1] - moveDelta[1]) < 0.02),
|
|
518
|
+
JSON.stringify({ delta: moveDelta, before: moveCenterBefore, after: moveCenterAfter }))
|
|
519
|
+
check('背景与网架:指针移动不会让手柄先于底图抢跑,刷新帧内手柄与四角同步落位',
|
|
520
|
+
handlesHeldBeforeFrame && handlesMatchedFrame,
|
|
521
|
+
moveFrameReport)
|
|
522
|
+
click('background-toggle-network')
|
|
523
|
+
await wait(160)
|
|
524
|
+
check('背景与网架:一键隐藏网架后背景与四角手柄仍在',
|
|
525
|
+
view.getOptions().networkVisible === false && view.getOptions().background?.image?.corners?.length === 4 &&
|
|
526
|
+
view.getResolvedBackground()?.image?.quad?.length === 16 && document.querySelectorAll('.gis-view__background-editor-handle:not([hidden])').length === 4 &&
|
|
527
|
+
text('background-readout').includes('网架已隐藏'),
|
|
528
|
+
`networkVisible=${view.getOptions().networkVisible} / handles=${document.querySelectorAll('.gis-view__background-editor-handle:not([hidden])').length} / ${text('background-readout')}`)
|
|
529
|
+
networkRange.value = '0.35'
|
|
530
|
+
networkRange.dispatchEvent(new Event('input', { bubbles: true }))
|
|
531
|
+
await wait(120)
|
|
532
|
+
check('背景与网架:网架整体透明度可从面板修改,背景四角不变',
|
|
533
|
+
Math.abs(view.getOptions().networkOpacity - 0.35) < 1e-6 && view.getOptions().background?.image?.corners?.length === 4,
|
|
534
|
+
`networkOpacity=${view.getOptions().networkOpacity}`)
|
|
535
|
+
networkToggle.click()
|
|
536
|
+
await wait(120)
|
|
537
|
+
const beforeDrag = view.getOptions().background.image.corners
|
|
538
|
+
const beforeWidth = beforeDrag[1][0] - beforeDrag[0][0]
|
|
539
|
+
const neHandle = document.querySelector('[data-gis-background-handle=ne]')
|
|
540
|
+
const handleRect = neHandle?.getBoundingClientRect()
|
|
541
|
+
if (neHandle && handleRect) {
|
|
542
|
+
const pointer = { bubbles: true, cancelable: true, composed: true, pointerId: 7, pointerType: 'mouse', isPrimary: true, button: 0, buttons: 1 }
|
|
543
|
+
neHandle.dispatchEvent(new PointerEvent('pointerdown', { ...pointer, clientX: handleRect.left + handleRect.width / 2, clientY: handleRect.top + handleRect.height / 2 }))
|
|
544
|
+
window.dispatchEvent(new PointerEvent('pointermove', { ...pointer, clientX: handleRect.left + handleRect.width / 2 + 70, clientY: handleRect.top + handleRect.height / 2 - 45 }))
|
|
545
|
+
window.dispatchEvent(new PointerEvent('pointerup', { ...pointer, button: 0, buttons: 0, clientX: handleRect.left + handleRect.width / 2 + 70, clientY: handleRect.top + handleRect.height / 2 - 45 }))
|
|
546
|
+
}
|
|
547
|
+
await wait(300)
|
|
548
|
+
const draggedCorners = view.getOptions().background?.image?.corners
|
|
549
|
+
const draggedWidth = draggedCorners ? draggedCorners[1][0] - draggedCorners[0][0] : 0
|
|
550
|
+
const draggedHeight = draggedCorners ? draggedCorners[0][1] - draggedCorners[2][1] : 0
|
|
551
|
+
const beforeHeight = beforeDrag[0][1] - beforeDrag[2][1]
|
|
552
|
+
check('背景与网架:锁定比例时拖右上角等比缩放,corners、读数与手柄同步',
|
|
553
|
+
draggedCorners?.length === 4 && draggedWidth > beforeWidth + 0.05 &&
|
|
554
|
+
Math.abs(draggedWidth / draggedHeight - beforeWidth / beforeHeight) < 0.01 &&
|
|
555
|
+
Math.abs((setup.editBounds.maxX - setup.editBounds.minX) - draggedWidth) < 0.02 &&
|
|
556
|
+
Number(document.querySelector('[data-demo=background-width]')?.value) > 0,
|
|
557
|
+
`ratio ${(beforeWidth / beforeHeight).toFixed(3)} → ${(draggedWidth / draggedHeight).toFixed(3)} / 输入 ${document.querySelector('[data-demo=background-width]')?.value}`)
|
|
558
|
+
document.querySelector('[data-demo=background-lock-ratio]')?.click()
|
|
559
|
+
await wait(160)
|
|
560
|
+
check('背景与网架:取消宽高锁定后从四角切换为八个缩放手柄,旋转仍关闭',
|
|
561
|
+
setup.aspectLocked === false && document.querySelectorAll('.gis-view__background-editor-handle:not([hidden])').length === 8 &&
|
|
562
|
+
document.querySelectorAll('.gis-view__background-editor-handle--edge:not([hidden])').length === 4 &&
|
|
563
|
+
document.querySelector('[data-gis-background-rotate]:not([hidden])') === null &&
|
|
564
|
+
text('background-edit-point-summary').includes('8 个编辑点'),
|
|
565
|
+
JSON.stringify({ locked: setup.aspectLocked, handles: document.querySelectorAll('.gis-view__background-editor-handle:not([hidden])').length, edges: document.querySelectorAll('.gis-view__background-editor-handle--edge:not([hidden])').length }))
|
|
566
|
+
const editColor = document.querySelector('[data-demo=background-edit-color]')
|
|
567
|
+
const editLineWidth = document.querySelector('[data-demo=background-edit-line-width]')
|
|
568
|
+
const editDashed = document.querySelector('[data-demo=background-edit-dashed]')
|
|
569
|
+
const editHandleSize = document.querySelector('[data-demo=background-edit-handle-size]')
|
|
570
|
+
const editHandleShape = document.querySelector('[data-demo=background-edit-handle-shape]')
|
|
571
|
+
if (editColor && editLineWidth && editDashed && editHandleSize && editHandleShape) {
|
|
572
|
+
editColor.value = '#c2410c'
|
|
573
|
+
editColor.dispatchEvent(new Event('input', { bubbles: true }))
|
|
574
|
+
editLineWidth.value = '3'
|
|
575
|
+
editLineWidth.dispatchEvent(new Event('input', { bubbles: true }))
|
|
576
|
+
editDashed.click()
|
|
577
|
+
editHandleSize.value = '22'
|
|
578
|
+
editHandleSize.dispatchEvent(new Event('input', { bubbles: true }))
|
|
579
|
+
editHandleShape.value = 'square'
|
|
580
|
+
editHandleShape.dispatchEvent(new Event('change', { bubbles: true }))
|
|
581
|
+
}
|
|
582
|
+
await wait(100)
|
|
583
|
+
const styledLayer = document.querySelector('[data-gis-background-editor]')
|
|
584
|
+
const styledHandle = document.querySelector('[data-gis-background-handle=nw]')
|
|
585
|
+
const styledHandleStyle = styledHandle ? getComputedStyle(styledHandle) : null
|
|
586
|
+
check('背景与网架:编辑框颜色、线宽、虚线、手柄尺寸与形状可实时自定义',
|
|
587
|
+
styledLayer && styledHandleStyle &&
|
|
588
|
+
styledLayer.style.getPropertyValue('--gis-view-bg-editor-color').trim().toLowerCase() === '#c2410c' &&
|
|
589
|
+
styledLayer.style.getPropertyValue('--gis-view-bg-editor-line-width').trim() === '3px' &&
|
|
590
|
+
styledLayer.style.getPropertyValue('--gis-view-bg-editor-dash').trim() === 'none' &&
|
|
591
|
+
styledHandleStyle.width === '22px' && styledHandleStyle.borderRadius === '2px',
|
|
592
|
+
JSON.stringify({
|
|
593
|
+
color: styledLayer?.style.getPropertyValue('--gis-view-bg-editor-color').trim(),
|
|
594
|
+
lineWidth: styledLayer?.style.getPropertyValue('--gis-view-bg-editor-line-width').trim(),
|
|
595
|
+
dash: styledLayer?.style.getPropertyValue('--gis-view-bg-editor-dash').trim(),
|
|
596
|
+
width: styledHandleStyle?.width,
|
|
597
|
+
radius: styledHandleStyle?.borderRadius
|
|
598
|
+
}))
|
|
599
|
+
const edgeWidthBefore = setup.editWidth
|
|
600
|
+
const edgeHeightBefore = setup.editHeight
|
|
601
|
+
const edgeCenterBefore = [...setup.editCenter]
|
|
602
|
+
const eastHandle = document.querySelector('[data-gis-background-handle=e]')
|
|
603
|
+
const eastRect = eastHandle?.getBoundingClientRect()
|
|
604
|
+
if (eastHandle && eastRect) {
|
|
605
|
+
const pointer = { bubbles: true, cancelable: true, composed: true, pointerId: 21, pointerType: 'mouse', isPrimary: true, button: 0, buttons: 1 }
|
|
606
|
+
const startX = eastRect.left + eastRect.width / 2
|
|
607
|
+
const startY = eastRect.top + eastRect.height / 2
|
|
608
|
+
eastHandle.dispatchEvent(new PointerEvent('pointerdown', { ...pointer, clientX: startX, clientY: startY }))
|
|
609
|
+
window.dispatchEvent(new PointerEvent('pointermove', { ...pointer, clientX: startX + 64, clientY: startY + 30 }))
|
|
610
|
+
window.dispatchEvent(new PointerEvent('pointerup', { ...pointer, button: 0, buttons: 0, clientX: startX + 64, clientY: startY + 30 }))
|
|
611
|
+
}
|
|
612
|
+
await wait(300)
|
|
613
|
+
check('背景与网架:未旋转时拖右边中点只改宽度,不改高度与中心纵坐标',
|
|
614
|
+
setup.editWidth > edgeWidthBefore + 0.05 &&
|
|
615
|
+
Math.abs(setup.editHeight - edgeHeightBefore) < 1e-6 &&
|
|
616
|
+
Math.abs(setup.editCenter[1] - edgeCenterBefore[1]) < 1e-6,
|
|
617
|
+
JSON.stringify({ width: [edgeWidthBefore, setup.editWidth], height: [edgeHeightBefore, setup.editHeight], centerY: [edgeCenterBefore[1], setup.editCenter[1]] }))
|
|
618
|
+
rotationToggle.click()
|
|
619
|
+
await wait(160)
|
|
620
|
+
const rotationInput = document.querySelector('[data-demo=background-rotation]')
|
|
621
|
+
check('背景与网架:开启旋转后出现旋转按钮,解锁状态下共九个编辑点',
|
|
622
|
+
setup.rotationEnabled === true && rotationToggle.checked === true &&
|
|
623
|
+
document.querySelectorAll('.gis-view__background-editor-handle:not([hidden])').length === 8 &&
|
|
624
|
+
document.querySelectorAll('[data-gis-background-rotate]:not([hidden])').length === 1 &&
|
|
625
|
+
text('background-edit-point-summary').includes('9 个编辑点') && rotationInput,
|
|
626
|
+
JSON.stringify({ enabled: setup.rotationEnabled, handles: document.querySelectorAll('.gis-view__background-editor-handle:not([hidden])').length, rotate: document.querySelectorAll('[data-gis-background-rotate]:not([hidden])').length }))
|
|
627
|
+
document.querySelector('.dv-stage')?.scrollIntoView({ block: 'center' })
|
|
628
|
+
click('background-fit-panel')
|
|
629
|
+
await wait(260)
|
|
630
|
+
const rotationHitButton = document.querySelector('[data-gis-background-rotate]:not([hidden])')
|
|
631
|
+
const rotationHitRect = rotationHitButton?.getBoundingClientRect()
|
|
632
|
+
const rotationHitTarget = rotationHitRect
|
|
633
|
+
? document.elementFromPoint(rotationHitRect.left + rotationHitRect.width / 2, rotationHitRect.top + rotationHitRect.height / 2)
|
|
634
|
+
: null
|
|
635
|
+
check('背景与网架:开启旋转后,旋转点能通过真实指针命中(不是只对按钮直接派发事件)',
|
|
636
|
+
Boolean(rotationHitButton && rotationHitTarget && (rotationHitTarget === rotationHitButton || rotationHitButton.contains(rotationHitTarget))),
|
|
637
|
+
JSON.stringify({ target: rotationHitTarget?.className ?? null, button: rotationHitButton?.className ?? null, pointerEvents: rotationHitButton ? getComputedStyle(rotationHitButton).pointerEvents : null }))
|
|
638
|
+
if (rotationInput) {
|
|
639
|
+
rotationInput.value = '30'
|
|
640
|
+
rotationInput.dispatchEvent(new Event('input', { bubbles: true }))
|
|
641
|
+
rotationInput.dispatchEvent(new Event('change', { bubbles: true }))
|
|
642
|
+
}
|
|
643
|
+
await wait(220)
|
|
644
|
+
const rotatedEdgeCornersBefore = view.getOptions().background.image.corners.map(corner => [...corner])
|
|
645
|
+
const rotatedEdgeWidthBefore = setup.editWidth
|
|
646
|
+
const rotatedEdgeHeightBefore = setup.editHeight
|
|
647
|
+
const westMiddleBefore = [
|
|
648
|
+
(rotatedEdgeCornersBefore[0][0] + rotatedEdgeCornersBefore[3][0]) / 2,
|
|
649
|
+
(rotatedEdgeCornersBefore[0][1] + rotatedEdgeCornersBefore[3][1]) / 2
|
|
650
|
+
]
|
|
651
|
+
const eastRotatedHandle = document.querySelector('[data-gis-background-handle=e]')
|
|
652
|
+
const eastRotatedRect = eastRotatedHandle?.getBoundingClientRect()
|
|
653
|
+
const rotatedSurfaceRect = document.querySelector('[data-gis-background-move]')?.getBoundingClientRect()
|
|
654
|
+
if (eastRotatedHandle && eastRotatedRect && rotatedSurfaceRect) {
|
|
655
|
+
const pointer = { bubbles: true, cancelable: true, composed: true, pointerId: 22, pointerType: 'mouse', isPrimary: true, button: 0, buttons: 1 }
|
|
656
|
+
const startX = eastRotatedRect.left + eastRotatedRect.width / 2
|
|
657
|
+
const startY = eastRotatedRect.top + eastRotatedRect.height / 2
|
|
658
|
+
const centerX = rotatedSurfaceRect.left + rotatedSurfaceRect.width / 2
|
|
659
|
+
const centerY = rotatedSurfaceRect.top + rotatedSurfaceRect.height / 2
|
|
660
|
+
const directionX = startX - centerX
|
|
661
|
+
const directionY = startY - centerY
|
|
662
|
+
const length = Math.max(Math.hypot(directionX, directionY), 1)
|
|
663
|
+
const endX = startX + directionX / length * 56
|
|
664
|
+
const endY = startY + directionY / length * 56
|
|
665
|
+
eastRotatedHandle.dispatchEvent(new PointerEvent('pointerdown', { ...pointer, clientX: startX, clientY: startY }))
|
|
666
|
+
window.dispatchEvent(new PointerEvent('pointermove', { ...pointer, clientX: endX, clientY: endY }))
|
|
667
|
+
window.dispatchEvent(new PointerEvent('pointerup', { ...pointer, button: 0, buttons: 0, clientX: endX, clientY: endY }))
|
|
668
|
+
}
|
|
669
|
+
await wait(300)
|
|
670
|
+
const rotatedEdgeCornersAfter = view.getOptions().background.image.corners
|
|
671
|
+
const westMiddleAfter = [
|
|
672
|
+
(rotatedEdgeCornersAfter[0][0] + rotatedEdgeCornersAfter[3][0]) / 2,
|
|
673
|
+
(rotatedEdgeCornersAfter[0][1] + rotatedEdgeCornersAfter[3][1]) / 2
|
|
674
|
+
]
|
|
675
|
+
check('背景与网架:旋转 30 度后拖右边中点仍只改局部宽度,并固定对边中点',
|
|
676
|
+
Math.abs(setup.editRotation - 30) < 0.01 && setup.editWidth > rotatedEdgeWidthBefore + 0.05 &&
|
|
677
|
+
Math.abs(setup.editHeight - rotatedEdgeHeightBefore) < 1e-6 &&
|
|
678
|
+
Math.hypot(westMiddleAfter[0] - westMiddleBefore[0], westMiddleAfter[1] - westMiddleBefore[1]) < 0.03,
|
|
679
|
+
JSON.stringify({ rotation: setup.editRotation, width: [rotatedEdgeWidthBefore, setup.editWidth], height: [rotatedEdgeHeightBefore, setup.editHeight], anchorDelta: [westMiddleAfter[0] - westMiddleBefore[0], westMiddleAfter[1] - westMiddleBefore[1]] }))
|
|
680
|
+
if (rotationInput) {
|
|
681
|
+
rotationInput.value = '0'
|
|
682
|
+
rotationInput.dispatchEvent(new Event('input', { bubbles: true }))
|
|
683
|
+
rotationInput.dispatchEvent(new Event('change', { bubbles: true }))
|
|
684
|
+
}
|
|
685
|
+
await wait(220)
|
|
686
|
+
click('background-add-geojson')
|
|
687
|
+
await wait(350)
|
|
688
|
+
const geoBefore = view.getOptions().background?.geoJsonStyle?.bounds
|
|
689
|
+
const geoWidthBefore = geoBefore ? geoBefore.maxX - geoBefore.minX : 0
|
|
690
|
+
const geoResolvedBefore = view.getResolvedBackground()?.geoJson
|
|
691
|
+
check('背景与网架:切到 GeoJSON 后写入目标 bounds,区域与文字照常解析',
|
|
692
|
+
geoBefore && geoWidthBefore > 0 && geoResolvedBefore?.bounds &&
|
|
693
|
+
Math.abs((geoResolvedBefore.bounds.maxX - geoResolvedBefore.bounds.minX) - geoWidthBefore) < 0.02 &&
|
|
694
|
+
geoResolvedBefore.regions.length > 0 && geoResolvedBefore.labels.length > 0,
|
|
695
|
+
`bounds=${JSON.stringify(geoBefore)} / regions=${geoResolvedBefore?.regions?.length ?? 0} / labels=${geoResolvedBefore?.labels?.length ?? 0}`)
|
|
696
|
+
const widthInput = document.querySelector('[data-demo=background-width]')
|
|
697
|
+
if (widthInput && geoBefore) {
|
|
698
|
+
widthInput.value = String(geoWidthBefore + 1)
|
|
699
|
+
widthInput.dispatchEvent(new Event('input', { bubbles: true }))
|
|
700
|
+
widthInput.dispatchEvent(new Event('change', { bubbles: true }))
|
|
701
|
+
}
|
|
702
|
+
await wait(350)
|
|
703
|
+
const geoAfter = view.getOptions().background?.geoJsonStyle?.bounds
|
|
704
|
+
const geoResolvedAfter = view.getResolvedBackground()?.geoJson
|
|
705
|
+
const geoWidthAfter = geoAfter ? geoAfter.maxX - geoAfter.minX : 0
|
|
706
|
+
check('背景与网架:GeoJSON 宽高输入能独立改大小,解析后的 bounds 与配置一致',
|
|
707
|
+
geoAfter && Math.abs(geoWidthAfter - (geoWidthBefore + 1)) < 0.03 &&
|
|
708
|
+
geoResolvedAfter?.bounds && Math.abs((geoResolvedAfter.bounds.maxX - geoResolvedAfter.bounds.minX) - geoWidthAfter) < 0.02,
|
|
709
|
+
`width ${geoWidthBefore.toFixed(2)} → ${geoWidthAfter.toFixed(2)} / resolved=${JSON.stringify(geoResolvedAfter?.bounds)}`)
|
|
710
|
+
const rotateHandle = document.querySelector('[data-gis-background-rotate]:not([hidden])')
|
|
711
|
+
const rotateSurface = document.querySelector('[data-gis-background-move]')
|
|
712
|
+
const rotateSurfaceRect = rotateSurface?.getBoundingClientRect()
|
|
713
|
+
const rotateHandleRect = rotateHandle?.getBoundingClientRect()
|
|
714
|
+
if (rotateHandle && rotateHandleRect && rotateSurfaceRect) {
|
|
715
|
+
const pointer = { bubbles: true, cancelable: true, composed: true, pointerId: 12, pointerType: 'mouse', isPrimary: true, button: 0, buttons: 1 }
|
|
716
|
+
const startX = rotateHandleRect.left + rotateHandleRect.width / 2
|
|
717
|
+
const startY = rotateHandleRect.top + rotateHandleRect.height / 2
|
|
718
|
+
const centerX = rotateSurfaceRect.left + rotateSurfaceRect.width / 2
|
|
719
|
+
const centerY = rotateSurfaceRect.top + rotateSurfaceRect.height / 2
|
|
720
|
+
const hitTarget = document.elementFromPoint(startX, startY)
|
|
721
|
+
hitTarget?.dispatchEvent(new PointerEvent('pointerdown', { ...pointer, clientX: startX, clientY: startY }))
|
|
722
|
+
window.dispatchEvent(new PointerEvent('pointermove', { ...pointer, clientX: centerX + 180, clientY: centerY }))
|
|
723
|
+
window.dispatchEvent(new PointerEvent('pointerup', { ...pointer, button: 0, buttons: 0, clientX: centerX + 180, clientY: centerY }))
|
|
724
|
+
}
|
|
725
|
+
await wait(350)
|
|
726
|
+
const rotatedGeo = view.getResolvedBackground()?.geoJson
|
|
727
|
+
const rotatedStyle = view.getOptions().background?.geoJsonStyle
|
|
728
|
+
const styleWidth = geoAfter ? geoAfter.maxX - geoAfter.minX : 0
|
|
729
|
+
const styleHeight = geoAfter ? geoAfter.maxY - geoAfter.minY : 0
|
|
730
|
+
check('背景与网架:拖顶部圆点旋转,GeoJSON 配置与解析角度同步,bounds 变成旋转后的 AABB',
|
|
731
|
+
Math.abs(setup.editRotation - 90) < 1 && rotatedStyle?.rotation === setup.editRotation &&
|
|
732
|
+
rotatedGeo?.rotation === setup.editRotation && rotatedGeo?.bounds &&
|
|
733
|
+
Math.abs((rotatedGeo.bounds.maxX - rotatedGeo.bounds.minX) - styleHeight) < 0.08 &&
|
|
734
|
+
Math.abs((rotatedGeo.bounds.maxY - rotatedGeo.bounds.minY) - styleWidth) < 0.08 &&
|
|
735
|
+
Math.abs(Number.parseFloat(document.querySelector('[data-demo=background-rotation]')?.value) - setup.editRotation) < 0.01,
|
|
736
|
+
JSON.stringify({ rotation: setup.editRotation, style: rotatedStyle?.rotation, resolved: rotatedGeo?.rotation, bounds: rotatedGeo?.bounds }))
|
|
737
|
+
const rotateWheelButton = document.querySelector('[data-gis-background-rotate]:not([hidden])')
|
|
738
|
+
const wheelSurfaceRect = rotateSurface?.getBoundingClientRect()
|
|
739
|
+
const wheelScaleBefore = view.getScale()
|
|
740
|
+
const editWheel = new WheelEvent('wheel', {
|
|
741
|
+
bubbles: true,
|
|
742
|
+
cancelable: true,
|
|
743
|
+
deltaY: -200,
|
|
744
|
+
clientX: wheelSurfaceRect ? wheelSurfaceRect.left + wheelSurfaceRect.width / 2 : 0,
|
|
745
|
+
clientY: wheelSurfaceRect ? wheelSurfaceRect.top + wheelSurfaceRect.height / 2 : 0
|
|
746
|
+
})
|
|
747
|
+
rotateWheelButton?.dispatchEvent(editWheel)
|
|
748
|
+
await wait(220)
|
|
749
|
+
check('背景与网架:编辑手柄上的滚轮仍转发给画布,整张图一起缩放',
|
|
750
|
+
editWheel.defaultPrevented && view.getScale() > wheelScaleBefore,
|
|
751
|
+
`${wheelScaleBefore} -> ${view.getScale()} / prevented=${editWheel.defaultPrevented}`)
|
|
752
|
+
click('background-toggle-editing')
|
|
753
|
+
await wait(220)
|
|
754
|
+
const editingOff = view.getOptions().backgroundEditing === false &&
|
|
755
|
+
document.querySelector('[data-gis-background-editor]') === null &&
|
|
756
|
+
document.querySelectorAll('.gis-view__background-editor-handle:not([hidden])').length === 0
|
|
757
|
+
click('background-toggle-editing')
|
|
758
|
+
await wait(220)
|
|
759
|
+
check('背景与网架:可退出再进入背景编辑模式,图层与手柄随开关显隐',
|
|
760
|
+
editingOff && view.getOptions().backgroundEditing === true &&
|
|
761
|
+
document.querySelector('[data-gis-background-editor]') !== null &&
|
|
762
|
+
document.querySelectorAll('.gis-view__background-editor-handle:not([hidden])').length === 8 &&
|
|
763
|
+
document.querySelector('[data-gis-background-rotate]:not([hidden])') !== null &&
|
|
764
|
+
text('background-edit-point-summary').includes('9 个编辑点'),
|
|
765
|
+
JSON.stringify({ off: editingOff, on: view.getOptions().backgroundEditing, handles: document.querySelectorAll('.gis-view__background-editor-handle:not([hidden])').length }))
|
|
766
|
+
networkToggle.click()
|
|
767
|
+
await wait(140)
|
|
768
|
+
check('背景与网架:隐藏网架时 GeoJSON 背景与区域文字仍保留,恢复按钮可用',
|
|
769
|
+
view.getOptions().networkVisible === false && view.getOptions().background?.geoJson &&
|
|
770
|
+
view.getResolvedBackground()?.geoJson?.labels?.length > 0 &&
|
|
771
|
+
text('background-toggle-network').includes('恢复显示网架'),
|
|
772
|
+
`networkVisible=${view.getOptions().networkVisible} / labels=${view.getResolvedBackground()?.geoJson?.labels?.length ?? 0} / ${text('background-toggle-network')}`)
|
|
773
|
+
networkToggle.click()
|
|
774
|
+
await wait(140)
|
|
775
|
+
if (rotationInput) {
|
|
776
|
+
rotationInput.value = '90'
|
|
777
|
+
rotationInput.dispatchEvent(new Event('input', { bubbles: true }))
|
|
778
|
+
rotationInput.dispatchEvent(new Event('change', { bubbles: true }))
|
|
779
|
+
}
|
|
780
|
+
await wait(250)
|
|
781
|
+
const geoRotationReset = view.getResolvedBackground()?.geoJson
|
|
782
|
+
check('背景与网架:旋转输入框可把 GeoJSON 角度精确设回 90 度',
|
|
783
|
+
Math.abs(setup.editRotation - 90) < 0.001 && geoRotationReset?.rotation === setup.editRotation,
|
|
784
|
+
JSON.stringify({ setup: setup.editRotation, resolved: geoRotationReset?.rotation }))
|
|
785
|
+
click('background-add-image')
|
|
786
|
+
await wait(450)
|
|
787
|
+
const imageAfterRotate = view.getOptions().background?.image
|
|
788
|
+
const imageQuadAfterRotate = view.getResolvedBackground()?.image?.quad
|
|
789
|
+
const [imageCenterX, imageCenterY] = setup.editCenter
|
|
790
|
+
const expectedImageCorners = [
|
|
791
|
+
[imageCenterX + setup.editHeight / 2, imageCenterY + setup.editWidth / 2],
|
|
792
|
+
[imageCenterX + setup.editHeight / 2, imageCenterY - setup.editWidth / 2],
|
|
793
|
+
[imageCenterX - setup.editHeight / 2, imageCenterY - setup.editWidth / 2],
|
|
794
|
+
[imageCenterX - setup.editHeight / 2, imageCenterY + setup.editWidth / 2]
|
|
795
|
+
]
|
|
796
|
+
check('背景与网架:图片背景同样按旋转角写回四角,贴图四边形随之旋转',
|
|
797
|
+
imageAfterRotate?.corners?.length === 4 && imageQuadAfterRotate?.length === 16 &&
|
|
798
|
+
imageAfterRotate.corners.every((corner, index) =>
|
|
799
|
+
Math.abs(corner[0] - expectedImageCorners[index][0]) < 0.03 &&
|
|
800
|
+
Math.abs(corner[1] - expectedImageCorners[index][1]) < 0.03) &&
|
|
801
|
+
Math.abs(setup.editRotation - 90) < 0.01,
|
|
802
|
+
JSON.stringify({ rotation: setup.editRotation, corners: imageAfterRotate?.corners, expected: expectedImageCorners, quad: imageQuadAfterRotate?.length }))
|
|
803
|
+
rotationToggle.click()
|
|
804
|
+
await wait(160)
|
|
805
|
+
check('背景与网架:关闭旋转后旋转按钮消失,保留原角度与八个缩放手柄',
|
|
806
|
+
setup.rotationEnabled === false && Math.abs(setup.editRotation - 90) < 0.01 &&
|
|
807
|
+
document.querySelector('[data-gis-background-rotate]:not([hidden])') === null &&
|
|
808
|
+
document.querySelectorAll('.gis-view__background-editor-handle:not([hidden])').length === 8 &&
|
|
809
|
+
text('background-edit-point-summary').includes('8 个编辑点'),
|
|
810
|
+
JSON.stringify({ enabled: setup.rotationEnabled, rotation: setup.editRotation, handles: document.querySelectorAll('.gis-view__background-editor-handle:not([hidden])').length, rotate: Boolean(document.querySelector('[data-gis-background-rotate]:not([hidden])')) }))
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
else {
|
|
814
|
+
check('背景与网架:页签在', false, '没找到「背景与网架」页签')
|
|
815
|
+
}
|
|
816
|
+
|
|
357
817
|
// 2.0 点聚合:控件齐全、聚合圆点击只发 clusterClick,maxZoom 展开后又回来
|
|
358
818
|
if (await clickTab('点聚合')) {
|
|
359
819
|
const ready = await canvasReady()
|
|
@@ -2196,7 +2656,93 @@
|
|
|
2196
2656
|
check('通道与数据:demo 的线路隐藏 / 显示按钮只改 visible 并恢复原数据',
|
|
2197
2657
|
Boolean(demoLineHidden) && Boolean(demoLineShown) && demoLineId !== undefined,
|
|
2198
2658
|
`${String(demoLineId)} · ${channelField('channel-visibility')}`)
|
|
2659
|
+
// 通道内指定回线:只隐藏所选成员线路,通道 / 分组 / 其它回线都不动
|
|
2660
|
+
const inChannelGroupsBefore = channelView.getChannelGroups(visibilityChannelId)
|
|
2661
|
+
const inChannelGroup = [...inChannelGroupsBefore].reverse().find(group => group.lineIds?.length)
|
|
2662
|
+
const inChannelLineId = inChannelGroup?.lineIds?.[inChannelGroup.lineIds.length - 1]
|
|
2663
|
+
const inChannelLineIndex = channelView.getData().lines.findIndex(line => String(line.id) === String(inChannelLineId))
|
|
2664
|
+
const inChannelMemberCount = inChannelGroupsBefore.reduce((sum, group) => sum + (group.lineIds?.length ?? 0), 0)
|
|
2665
|
+
channelDemo.querySelector('[data-demo="channel-line-hide"]')?.click()
|
|
2666
|
+
const inChannelHidden = await until(() => {
|
|
2667
|
+
const line = channelView.getOptions().lines?.find(item => String(item.id) === String(inChannelLineId))
|
|
2668
|
+
return line?.visible === false && inChannelLineIndex >= 0 && channelView.getLineStyle(inChannelLineIndex) === null && channelField('channel-line-visibility').includes('隐藏通道内回线')
|
|
2669
|
+
}, 5000)
|
|
2670
|
+
const groupsDuringLineHide = channelView.getChannelGroups(visibilityChannelId)
|
|
2671
|
+
const othersDuringLineHide = channelView.getOptions().lines
|
|
2672
|
+
.filter(line => groupsDuringLineHide.some(group => group.lineIds?.some(id => String(id) === String(line.id))) && String(line.id) !== String(inChannelLineId))
|
|
2673
|
+
.every(line => line.visible !== false)
|
|
2674
|
+
check('通道与数据:可单独隐藏某条成员回线,通道分组、其它回线与线路数据都保留',
|
|
2675
|
+
Boolean(inChannelHidden) && inChannelMemberCount > 1 && othersDuringLineHide && groupsDuringLineHide.length === inChannelGroupsBefore.length && groupsDuringLineHide.some(group => group.lineIds?.some(id => String(id) === String(inChannelLineId))),
|
|
2676
|
+
`${String(inChannelLineId)} · ${channelField('channel-line-visibility')}`)
|
|
2677
|
+
channelDemo.querySelector('[data-demo="channel-line-show"]')?.click()
|
|
2678
|
+
const inChannelShown = await until(() => {
|
|
2679
|
+
const line = channelView.getOptions().lines?.find(item => String(item.id) === String(inChannelLineId))
|
|
2680
|
+
return line?.visible === true && channelView.getLineStyle(inChannelLineIndex) !== null && channelField('channel-line-visibility').includes('显示通道内回线')
|
|
2681
|
+
}, 5000)
|
|
2682
|
+
check('通道与数据:显示首通道末回线后恢复原样式,成员与分组声明未变',
|
|
2683
|
+
Boolean(inChannelShown) && channelView.getChannelGroups(visibilityChannelId).length === inChannelGroupsBefore.length,
|
|
2684
|
+
channelField('channel-line-visibility'))
|
|
2199
2685
|
const channelBox = channelCanvas.getBoundingClientRect()
|
|
2686
|
+
// 分组显隐与隐藏回线车道:准备两分组 -> 单组隐藏 -> center -> 恢复 -> 批量隐藏 / 恢复
|
|
2687
|
+
channelDemo.querySelector('[data-demo=channel-group-prepare]').click()
|
|
2688
|
+
const preparedGroupState = await until(() => {
|
|
2689
|
+
const groups = channelView.getChannelGroups(visibilityChannelId)
|
|
2690
|
+
return groups.length >= 2 && groups[0]?.lineIds?.length >= 2 && channelField('channel-group-visibility').includes('末组') ? groups : null
|
|
2691
|
+
}, 5000)
|
|
2692
|
+
const laneStates = () => channelView.getChannels()
|
|
2693
|
+
.filter(state => String(state.channelId) === String(visibilityChannelId))
|
|
2694
|
+
.map(state => ({ id: state.id, visible: state.visible, offsets: [...state.offsets] }))
|
|
2695
|
+
const lanesBeforeGroupHide = laneStates()
|
|
2696
|
+
channelDemo.querySelector('[data-demo=channel-group-hide]').click()
|
|
2697
|
+
const groupHidden = await until(() => {
|
|
2698
|
+
const groups = channelView.getChannelGroups(visibilityChannelId)
|
|
2699
|
+
return groups.length >= 2 && groups[groups.length - 1]?.visible === false && groups.some(group => group.visible) && channelField('channel-group-visibility').includes('隐藏末组')
|
|
2700
|
+
}, 5000)
|
|
2701
|
+
const lanesAfterGroupHide = laneStates()
|
|
2702
|
+
const offsetsByGroup = states => Object.fromEntries(states.filter(state => state.visible).map(state => [String(state.id), JSON.stringify(state.offsets)]))
|
|
2703
|
+
const lanesPreserved = Object.entries(offsetsByGroup(lanesAfterGroupHide)).every(([id, offsets]) => offsetsByGroup(lanesBeforeGroupHide)[id] === offsets)
|
|
2704
|
+
check('通道与数据:分组 demo 能准备两分组并单组隐藏,隐藏组仍保留成员与骨架,其余回线保持原车道',
|
|
2705
|
+
Boolean(preparedGroupState) && Boolean(groupHidden) && lanesAfterGroupHide.length === lanesBeforeGroupHide.length && lanesPreserved && channelField('channel-lane-layout').includes('(隐)'),
|
|
2706
|
+
`${channelField('channel-group-visibility')} / ${channelField('channel-lane-layout')}`)
|
|
2707
|
+
const layoutSelect = channelDemo.querySelector('[data-demo=channel-hidden-line-layout]')
|
|
2708
|
+
layoutSelect.value = 'center'
|
|
2709
|
+
layoutSelect.dispatchEvent(new Event('change', { bubbles: true }))
|
|
2710
|
+
const centeredLanes = await until(() => {
|
|
2711
|
+
const states = laneStates()
|
|
2712
|
+
return channelView.getOptions().channelHiddenLineLayout === 'center' && channelField('channel-lane-layout').includes('center') && channelField('channel-lane-layout').includes('(隐)') ? states : null
|
|
2713
|
+
}, 5000)
|
|
2714
|
+
const centeredOffsets = centeredLanes?.filter(state => state.visible).flatMap(state => state.offsets) ?? []
|
|
2715
|
+
const hiddenOffsets = lanesAfterGroupHide.filter(state => state.visible).flatMap(state => state.offsets)
|
|
2716
|
+
check('通道与数据:channelHiddenLineLayout=center 后,隐藏末组时剩余回线重新居中(offset 与 preserve 不同)',
|
|
2717
|
+
Boolean(centeredLanes) && JSON.stringify(centeredOffsets) !== JSON.stringify(hiddenOffsets),
|
|
2718
|
+
`${JSON.stringify(hiddenOffsets)} → ${JSON.stringify(centeredOffsets)}`)
|
|
2719
|
+
channelDemo.querySelector('[data-demo=channel-group-show]').click()
|
|
2720
|
+
const lastGroupShown = await until(() => {
|
|
2721
|
+
const groups = channelView.getChannelGroups(visibilityChannelId)
|
|
2722
|
+
return groups[groups.length - 1]?.visible === true && channelField('channel-group-visibility').includes('显示末组')
|
|
2723
|
+
}, 5000)
|
|
2724
|
+
channelDemo.querySelector('[data-demo=channel-group-hide-all]').click()
|
|
2725
|
+
const allGroupsHidden = await until(() => {
|
|
2726
|
+
const groups = channelView.getChannelGroups(visibilityChannelId)
|
|
2727
|
+
return groups.length >= 2 && groups.every(group => group.visible === false) && channelField('channel-group-visibility').includes('全部组(批量)')
|
|
2728
|
+
}, 5000)
|
|
2729
|
+
channelDemo.querySelector('[data-demo=channel-group-show-all]').click()
|
|
2730
|
+
const allGroupsShown = await until(() => {
|
|
2731
|
+
const groups = channelView.getChannelGroups(visibilityChannelId)
|
|
2732
|
+
return groups.length >= 2 && groups.every(group => group.visible === true) && channelField('channel-group-visibility').includes('显示全部组(批量)')
|
|
2733
|
+
}, 5000)
|
|
2734
|
+
check('通道与数据:单组恢复后,批量隐藏 / 恢复所有分组各走一次 group 引用批次,分组声明仍在',
|
|
2735
|
+
Boolean(lastGroupShown) && Boolean(allGroupsHidden) && Boolean(allGroupsShown) && channelView.getChannelGroups(visibilityChannelId).length >= 2,
|
|
2736
|
+
channelField('channel-group-visibility'))
|
|
2737
|
+
layoutSelect.value = 'preserve'
|
|
2738
|
+
layoutSelect.dispatchEvent(new Event('change', { bubbles: true }))
|
|
2739
|
+
await until(() => channelView.getOptions().channelHiddenLineLayout === 'preserve', 3000)
|
|
2740
|
+
const groupsForCleanup = channelView.getChannelGroups(visibilityChannelId)
|
|
2741
|
+
if (groupsForCleanup.length > 1) {
|
|
2742
|
+
channelView.mergeChannelGroups(visibilityChannelId, groupsForCleanup.slice(1).map(group => group.id), groupsForCleanup[0].id)
|
|
2743
|
+
}
|
|
2744
|
+
await wait(120)
|
|
2745
|
+
channelSetup.syncReadouts?.()
|
|
2200
2746
|
const channelRightClick = (screen) => {
|
|
2201
2747
|
channelCanvas.dispatchEvent(new MouseEvent('contextmenu', {
|
|
2202
2748
|
bubbles: true,
|
|
@@ -2756,6 +3302,75 @@
|
|
|
2756
3302
|
check('合并样式 demo:读数明确说明它是最终 size / symbol,并给出规则与改写入口',
|
|
2757
3303
|
Boolean(mergeHint) && mergeHint.textContent.includes('合并样式') && mergeHint.textContent.includes('不是一项额外配置') && mergeHint.textContent.includes('尺寸取双方较大值') && mergeHint.textContent.includes('merge.createItem'),
|
|
2758
3304
|
mergeHint?.textContent.trim() ?? '没有合并样式读数')
|
|
3305
|
+
// 保留框:默认开持久化 + DOM 框,框选后能读坐标、切线型 / 圆角、切 canvas / div 并手动收起
|
|
3306
|
+
;[...document.querySelectorAll('.demo-panel-buttons button')].find(node => node.textContent.includes('导出图片与选中样式'))?.click()
|
|
3307
|
+
await wait(100)
|
|
3308
|
+
const persistentToggle = document.querySelector('[data-demo=selection-box-persistent]')
|
|
3309
|
+
const renderSelect = document.querySelector('[data-demo=selection-box-render]')
|
|
3310
|
+
const borderSelect = document.querySelector('[data-demo=selection-box-border-style]')
|
|
3311
|
+
const radiusInput = document.querySelector('[data-demo=selection-box-radius]')
|
|
3312
|
+
const classNameToggle = document.querySelector('[data-demo=selection-box-class-name]')
|
|
3313
|
+
const boxReadoutNode = document.querySelector('[data-demo=selection-box-readout]')
|
|
3314
|
+
check('保留框 demo:导出 / 选中样式面板摆出持久化开关、DOM 渲染、线型、圆角、类名与读数',
|
|
3315
|
+
Boolean(persistentToggle && renderSelect && borderSelect && radiusInput && classNameToggle && boxReadoutNode) && persistentToggle.checked && renderSelect.value === 'div' && borderSelect.value === 'dashed' && radiusInput.value === '8' && classNameToggle.checked,
|
|
3316
|
+
`${persistentToggle?.checked} / ${renderSelect?.value} / ${borderSelect?.value} / ${radiusInput?.value} / ${classNameToggle?.checked}`)
|
|
3317
|
+
const fullBoxRect = () => ({ x: 0, y: 0, width: cascadeCanvas.clientWidth, height: cascadeCanvas.clientHeight })
|
|
3318
|
+
const retainedElement = () => cascadeCanvas.parentElement.querySelector('.gis-view__selection-box.demo-retained-box')
|
|
3319
|
+
cascadeView.selectInBox(fullBoxRect())
|
|
3320
|
+
const retainedBox = await until(() => cascadeView.getSelectionBox(), 3000)
|
|
3321
|
+
const domBox = await until(() => retainedElement(), 3000)
|
|
3322
|
+
const initialBorderStyle = domBox?.style.getPropertyValue('--gis-view-selection-box-border-style').trim() ?? ''
|
|
3323
|
+
const initialRadius = domBox?.style.getPropertyValue('--gis-view-selection-box-radius').trim() ?? ''
|
|
3324
|
+
const selectionCountBeforeClear = cascadeView.getSelectionInfo().count
|
|
3325
|
+
check('保留框 demo:框选后保留矩形,DOM 框挂自定义类名并应用虚线 / 圆角,选中集仍在',
|
|
3326
|
+
Boolean(retainedBox && domBox) && initialBorderStyle === 'dashed' && initialRadius === '8px' && selectionCountBeforeClear > 0,
|
|
3327
|
+
JSON.stringify({ box: retainedBox, classes: domBox?.className, border: initialBorderStyle, radius: initialRadius, selected: selectionCountBeforeClear }))
|
|
3328
|
+
document.querySelector('[data-demo=selection-box-read]').click()
|
|
3329
|
+
await wait(60)
|
|
3330
|
+
check('保留框 demo:读取按钮走 getSelectionBox(),读数给出 CSS 像素坐标与宽高',
|
|
3331
|
+
boxReadoutNode.textContent.includes('getSelectionBox():x') && boxReadoutNode.textContent.includes('×'),
|
|
3332
|
+
boxReadoutNode.textContent.trim())
|
|
3333
|
+
borderSelect.value = 'dotted'
|
|
3334
|
+
borderSelect.dispatchEvent(new Event('change', { bubbles: true }))
|
|
3335
|
+
radiusInput.value = '14'
|
|
3336
|
+
radiusInput.dispatchEvent(new Event('input', { bubbles: true }))
|
|
3337
|
+
radiusInput.dispatchEvent(new Event('change', { bubbles: true }))
|
|
3338
|
+
const boxStyleChanged = await until(() => {
|
|
3339
|
+
const element = retainedElement()
|
|
3340
|
+
return cascadeView.getOptions().selectionBoxStyle?.borderStyle === 'dotted' && cascadeView.getOptions().selectionBoxStyle?.radius === 14 && element?.style.getPropertyValue('--gis-view-selection-box-border-style').trim() === 'dotted' && element?.style.getPropertyValue('--gis-view-selection-box-radius').trim() === '14px'
|
|
3341
|
+
}, 3000)
|
|
3342
|
+
check('保留框 demo:div 框的线型 / 圆角改完即时落到 DOM(options 与元素同步)', Boolean(boxStyleChanged), boxStyleChanged ? 'dotted / 14px' : boxReadoutNode.textContent.trim())
|
|
3343
|
+
renderSelect.value = 'canvas'
|
|
3344
|
+
renderSelect.dispatchEvent(new Event('change', { bubbles: true }))
|
|
3345
|
+
const canvasRendered = await until(() => cascadeView.getOptions().selectionBoxStyle?.render === 'canvas' && !retainedElement(), 3000)
|
|
3346
|
+
renderSelect.value = 'div'
|
|
3347
|
+
renderSelect.dispatchEvent(new Event('change', { bubbles: true }))
|
|
3348
|
+
const divRendered = await until(() => cascadeView.getOptions().selectionBoxStyle?.render === 'div' && Boolean(retainedElement()), 3000)
|
|
3349
|
+
check('保留框 demo:canvas / div 渲染可运行时切换,切回 div 后 DOM 框重新挂上',
|
|
3350
|
+
Boolean(canvasRendered) && Boolean(divRendered),
|
|
3351
|
+
`${canvasRendered} / ${divRendered}`)
|
|
3352
|
+
document.querySelector('[data-demo=selection-box-clear]').click()
|
|
3353
|
+
const boxCleared = await until(() => cascadeView.getSelectionBox() === null && !retainedElement(), 3000)
|
|
3354
|
+
check('保留框 demo:clearSelectionBox() 按钮只收起框,选中集不变,读数回到 null',
|
|
3355
|
+
Boolean(boxCleared) && cascadeView.getSelectionInfo().count === selectionCountBeforeClear && boxReadoutNode.textContent.includes('null'),
|
|
3356
|
+
`${cascadeView.getSelectionInfo().count} / ${boxReadoutNode.textContent.trim()}`)
|
|
3357
|
+
cascadeView.selectInBox(fullBoxRect())
|
|
3358
|
+
await until(() => cascadeView.getSelectionBox(), 3000)
|
|
3359
|
+
persistentToggle.click()
|
|
3360
|
+
const persistentDisabled = await until(() => cascadeView.getOptions().selectionBoxPersistent === false && cascadeView.getSelectionBox() === null, 3000)
|
|
3361
|
+
persistentToggle.click()
|
|
3362
|
+
const persistentEnabled = await until(() => cascadeView.getOptions().selectionBoxPersistent === true, 3000)
|
|
3363
|
+
check('保留框 demo:勾掉持久化会收起现有框并写回 options,重新勾上恢复可保留',
|
|
3364
|
+
Boolean(persistentDisabled) && Boolean(persistentEnabled),
|
|
3365
|
+
`${cascadeView.getOptions().selectionBoxPersistent} / ${cascadeView.getSelectionBox() === null ? '无框' : '有框'}`)
|
|
3366
|
+
borderSelect.value = 'dashed'
|
|
3367
|
+
borderSelect.dispatchEvent(new Event('change', { bubbles: true }))
|
|
3368
|
+
radiusInput.value = '8'
|
|
3369
|
+
radiusInput.dispatchEvent(new Event('input', { bubbles: true }))
|
|
3370
|
+
radiusInput.dispatchEvent(new Event('change', { bubbles: true }))
|
|
3371
|
+
cascadeView.clearSelectionBox()
|
|
3372
|
+
cascadeView.selectFeatures(null)
|
|
3373
|
+
await wait(100)
|
|
2759
3374
|
}
|
|
2760
3375
|
else {
|
|
2761
3376
|
check('级联高亮 demo:画布与视图都起来了', false, ready ? '没有 setupState.viewRef' : '没有 canvas')
|
|
@@ -2767,8 +3382,8 @@
|
|
|
2767
3382
|
await wait(150)
|
|
2768
3383
|
const apiItems = () => [...document.querySelectorAll('.demo-api-list:not(.demo-api-list--options) .demo-api-item')]
|
|
2769
3384
|
const optionItems = () => [...document.querySelectorAll('.demo-api-list--options .demo-api-item')]
|
|
2770
|
-
check('实例方法速查:整份成员清单按分组列全(16 组 /
|
|
2771
|
-
Boolean(ready) && document.querySelectorAll('.demo-api-group').length === 16 && apiItems().length ===
|
|
3385
|
+
check('实例方法速查:整份成员清单按分组列全(16 组 / 283 个成员)',
|
|
3386
|
+
Boolean(ready) && document.querySelectorAll('.demo-api-group').length === 16 && apiItems().length === 283,
|
|
2772
3387
|
`${document.querySelectorAll('.demo-api-group').length} 组 / ${apiItems().length} 个成员`)
|
|
2773
3388
|
const apiNames = apiItems().map(node => node.querySelector('b')?.textContent)
|
|
2774
3389
|
const roundNames = ['registerSymbol', 'unregisterSymbol', 'listSymbols']
|
|
@@ -2787,7 +3402,7 @@
|
|
|
2787
3402
|
check('实例方法速查:这一轮拆出来的方法也在清单里(addChannelGroupLines / joinChannelGroupLines / endAddChannel)',
|
|
2788
3403
|
roundNames1597.every(name => apiNames.includes(name)),
|
|
2789
3404
|
roundNames1597.filter(name => !apiNames.includes(name)).join(' / ') || '三个都在')
|
|
2790
|
-
check('实例方法速查:options 折叠清单列全
|
|
3405
|
+
check('实例方法速查:options 折叠清单列全 107 个键', optionItems().length === 107, `${optionItems().length} 个键`)
|
|
2791
3406
|
const apiSearch = document.querySelector('.demo-api-search input[type="search"]')
|
|
2792
3407
|
apiSearch.value = 'focusOn'
|
|
2793
3408
|
apiSearch.dispatchEvent(new Event('input', { bubbles: true }))
|