fix(h5): prevent native scrolling from stealing diagonal image swipes

This commit is contained in:
xsl
2026-10-13 00:42:01 +08:00
parent 4c478b16e3
commit 98935dd168
10 changed files with 197 additions and 171 deletions
+16 -3
View File
@@ -65,7 +65,7 @@ try {
const touch = (type, x, y, timestamp) => cdp.send('Input.dispatchTouchEvent', {
type, ...(timestamp ? { timestamp } : {}), touchPoints: /touchEnd|touchCancel/.test(type) ? [] : [{ x, y, id: 1 }]
});
async function drag(card, dx, { dy = 0, cancel = false, pause = 0, flick = false, verify = false, text = false } = {}) {
async function drag(card, dx, { dy = 0, cancel = false, pause = 0, flick = false, verify = false, text = false, steps = 2, horizontal = false } = {}) {
const frame = card.locator('.dpanel.active ' + (text ? '.ditem-text' : '.viz-frame'));
await frame.scrollIntoViewIfNeeded(); await page.waitForTimeout(400);
const box = await frame.boundingBox(), x = box.x + box.width / 2, y = box.y + box.height / 2;
@@ -73,10 +73,17 @@ try {
const scrollBefore = await page.locator('#s-report').evaluate(el => el.scrollTop);
const beforeHeight = await card.locator('.detail-viewport').evaluate(el => el.getBoundingClientRect().height);
await touch('touchStart', x, y, now);
await touch('touchMove', x + dx / 2, y + dy / 2, now && now + .02);
await touch('touchMove', x + dx, y + dy, now && now + .04);
for (let step = 1; step <= steps; step++) {
await touch('touchMove', x + dx * step / steps, y + dy * step / steps, now && now + .04 * step / steps);
if (steps > 2) await page.waitForTimeout(20);
}
const liveOffset = await offset(card), limit = await card.locator('.detail-viewport').evaluate(el => el.clientWidth * (el.querySelectorAll('.dpanel').length - 1));
assert(liveOffset <= 17 && liveOffset >= -limit - 17, 'edge resistance caps overscroll at 16px');
if (horizontal) {
assert(Math.abs(liveOffset - before - dx) < 3, 'diagonal drag remains finger-following before release');
assert.equal(await card.locator('.detail-panels.dragging').count(), 1, 'browser does not cancel diagonal image gesture');
assert(Math.abs(await page.locator('#s-report').evaluate(el => el.scrollTop) - scrollBefore) < 1, 'diagonal image gesture does not scroll the report');
}
if (verify) {
assert(Math.abs(await offset(card) - before - dx) < 3, 'report follows finger before release');
assert.equal(await selected(card), previous, 'selection commits only on release');
@@ -97,6 +104,7 @@ try {
if (pause) await page.waitForTimeout(pause);
await touch(cancel ? 'touchCancel' : 'touchEnd', 0, 0, now && now + .05);
await page.waitForTimeout(400);
if (horizontal) assert(Math.abs(await page.locator('#s-report').evaluate(el => el.scrollTop) - scrollBefore) < 1, 'horizontal release has no vertical momentum');
if (dy <= -80 && Math.abs(dx) < 10) {
assert(await page.locator('#s-report').evaluate(el => el.scrollTop) > scrollBefore + 10, 'vertical gesture actually scrolls the report');
}
@@ -121,6 +129,11 @@ try {
await drag(card, 100, { cancel: true }); assert.equal(await selected(card), '1', 'cancellation restores selection');
await drag(card, 2, { dy: -90 }); assert.equal(await selected(card), '1', 'vertical scrolling preserves tab');
await drag(card, 65, { dy: -60 }); assert.equal(await selected(card), '0', 'diagonal image gesture prioritizes horizontal switching');
for (const [dx, dy] of [[-60, -75], [-80, -90]]) {
await drag(card, dx, { dy, steps: 6, horizontal: true });
assert.equal(await selected(card), '1', 'vertical-heavy diagonal still uses configured horizontal priority');
await card.locator('.dtab').first().click(); await page.waitForTimeout(400);
}
await card.locator('.dtab').nth(1).click(); await page.waitForTimeout(400);
await drag(card, 100, { text: true }); assert.equal(await selected(card), '1', 'horizontal dragging on analysis text does not switch tabs');
await drag(card, 2, { dy: -90, text: true }); assert.equal(await selected(card), '1', 'reading text keeps vertical scrolling and current tab');