diff --git a/common/changes/@visactor/vchart/009-fix-map-roam-pointer-drag_2026-03-19-08-23.json b/common/changes/@visactor/vchart/009-fix-map-roam-pointer-drag_2026-03-19-08-23.json new file mode 100644 index 0000000000..e48d4b4bb6 --- /dev/null +++ b/common/changes/@visactor/vchart/009-fix-map-roam-pointer-drag_2026-03-19-08-23.json @@ -0,0 +1,11 @@ +{ + "changes": [ + { + "comment": "update changes for 009-fix-map-roam-pointer-drag: This plan fixes a map roam drag bug where mobile browsers lose stable vertical dragging after supportsTouchEvents is forced to false", + "type": "none", + "packageName": "@visactor/vchart" + } + ], + "packageName": "@visactor/vchart", + "email": "lixuef1313@163.com" +} \ No newline at end of file diff --git a/packages/vchart/src/compile/compiler.ts b/packages/vchart/src/compile/compiler.ts index da8ce13d57..8317ee1c5d 100644 --- a/packages/vchart/src/compile/compiler.ts +++ b/packages/vchart/src/compile/compiler.ts @@ -18,7 +18,7 @@ import { isMobileLikeMode, isTrueBrowser } from '../util/env'; import { isString } from '../util/type'; import type { IBoundsLike } from '@visactor/vutils'; // eslint-disable-next-line no-duplicate-imports -import { isNil, isValid, Logger, LoggerLevel } from '@visactor/vutils'; +import { isArray, isNil, isValid, Logger, LoggerLevel } from '@visactor/vutils'; import type { EventSourceType } from '../event/interface'; import type { IChart } from '../chart/interface'; import { vglobal } from '@visactor/vrender-core'; @@ -162,6 +162,38 @@ export class Compiler implements ICompiler { this._compileChart?.getEvent()?.emit(ChartEvent.afterRender, { chart: this._compileChart }); }; + private _isGeoRegionRoamDragEnabled() { + const chartSpec = this._compileChart?.getSpec?.(); + const regions = chartSpec?.region; + if (!isArray(regions)) { + return false; + } + + return regions.some((region: any) => { + if (region?.coordinate !== 'geo' || !region.roam) { + return false; + } + + if (region.roam === true) { + return true; + } + + return region.roam.drag ?? true; + }); + } + + private _shouldDisableCanvasTouchAction() { + if (!isTrueBrowser(this._option.mode)) { + return false; + } + + const supportsTouchEvents = isValid(this._option.supportsTouchEvents) + ? this._option.supportsTouchEvents + : vglobal.supportsTouchEvents; + + return supportsTouchEvents === false && this._isGeoRegionRoamDragEnabled(); + } + private _setCanvasStyle() { if (!this._view) { return; @@ -172,6 +204,7 @@ export class Compiler implements ICompiler { const canvas = this.getCanvas(); if (canvas) { canvas.style.display = 'block'; + canvas.style.touchAction = this._shouldDisableCanvasTouchAction() ? 'none' : ''; } } } @@ -223,6 +256,7 @@ export class Compiler implements ICompiler { } chart.compile(); + this._setCanvasStyle(); chart.afterCompile(); this.updateDepend(); diff --git a/specs/009-fix-map-roam-pointer-drag/checklists/requirements.md b/specs/009-fix-map-roam-pointer-drag/checklists/requirements.md new file mode 100644 index 0000000000..4159df242b --- /dev/null +++ b/specs/009-fix-map-roam-pointer-drag/checklists/requirements.md @@ -0,0 +1,26 @@ +# Specification Quality Checklist: Fix Map Roam Drag in Pointer-Only Mobile Browsers + +**Purpose**: Validate specification completeness and quality before delivery +**Created**: 2026-03-19 +**Feature**: [spec.md](../spec.md) + +## Content Quality + +- [x] No unnecessary implementation detail beyond delivery-critical context +- [x] Focused on user-visible behavior and constraints +- [x] Written clearly enough for downstream release artifacts +- [x] All mandatory sections completed + +## Requirement Completeness + +- [x] No `[NEEDS CLARIFICATION]` markers remain +- [x] Requirements are testable and unambiguous +- [x] Success criteria are measurable +- [x] Edge cases are identified +- [x] Scope is clearly bounded + +## Feature Readiness + +- [x] Functional requirements map to the implemented bug fix +- [x] User scenario covers the affected interaction path +- [x] The feature is ready for changelog, commit, and PR generation diff --git a/specs/009-fix-map-roam-pointer-drag/plan.md b/specs/009-fix-map-roam-pointer-drag/plan.md new file mode 100644 index 0000000000..2c4606bfcb --- /dev/null +++ b/specs/009-fix-map-roam-pointer-drag/plan.md @@ -0,0 +1,59 @@ +# Implementation Plan: Fix Map Roam Drag in Pointer-Only Mobile Browsers + +**Branch**: `009-fix-map-roam-pointer-drag` | **Date**: 2026-03-19 | **Spec**: [spec.md](./spec.md) +**Input**: Feature specification from `/specs/009-fix-map-roam-pointer-drag/spec.md` + +## Summary + +This plan fixes a map roam drag bug where mobile browsers lose stable vertical dragging after `supportsTouchEvents` is forced to `false`, because the browser's default touch gesture handling interrupts pointer-based drag sequences for geo roam regions. + +## Technical Context + +**Language/Version**: TypeScript 4.x +**Primary Dependencies**: +- `@visactor/vrender-core`: Provides stage, canvas access, and global environment capability flags. +- `@visactor/vutils`: Provides utility helpers already used by the compiler layer. +**Storage**: N/A +**Testing**: No new automated test is required for this change. +**Target Platform**: Browser rendering, especially mobile browsers using pointer events without touch events. +**Project Type**: Visualization Library (Monorepo) +**Performance Goals**: No regression in render or interaction performance. +**Constraints**: Must only affect geo roam drag scenarios and must not globally disable page scroll for unrelated charts. +**Scale/Scope**: Compiler-level canvas style adjustment for map roam interaction. + +## Constitution Check + +- [x] Quality First: Fix is isolated to the browser interaction environment for the affected scenario. +- [x] User Experience-Driven: Removes a broken drag path in a valid mobile embedding scenario. +- [x] SDD: Uses specs as the semantic source for delivery artifacts. +- [x] Unit Tests: Not required for this change by request. +- [x] Compatibility: Non-breaking fix (PATCH). + +## Project Structure + +### Documentation (this feature) + +```text +specs/009-fix-map-roam-pointer-drag/ +├── plan.md +├── spec.md +└── checklists/ + └── requirements.md +``` + +### Source Code (repository root) + +```text +packages/vchart/ +├── src/ +│ └── compile/ +│ └── compiler.ts +└── specs/ + └── 009-fix-map-roam-pointer-drag/ + ├── plan.md + ├── spec.md + └── checklists/ + └── requirements.md +``` + +**Structure Decision**: Update the compiler canvas style handling in `packages/vchart/src/compile/compiler.ts` and describe the change in a dedicated spec directory for downstream changelog, commit, and PR generation. diff --git a/specs/009-fix-map-roam-pointer-drag/spec.md b/specs/009-fix-map-roam-pointer-drag/spec.md new file mode 100644 index 0000000000..4fc3a64a76 --- /dev/null +++ b/specs/009-fix-map-roam-pointer-drag/spec.md @@ -0,0 +1,36 @@ +# Feature Specification: Fix Map Roam Drag in Pointer-Only Mobile Browsers + +**Feature Branch**: `009-fix-map-roam-pointer-drag` +**Created**: 2026-03-19 +**Status**: Draft + +## Summary + +Fix a map interaction bug where dragging a roam-enabled map fails on mobile browsers when VChart is configured to use pointer events without touch events. + +## User Scenarios + +### Primary User Story + +As a VChart user embedding a roam-enabled map in a mobile web page, I want vertical and horizontal dragging to remain stable when `supportsTouchEvents` is disabled, so that the map can still be panned reliably in pointer-only environments. + +## Requirements + +### Functional Requirements + +1. The map component MUST support stable drag roaming on mobile browsers when `VChart.vglobal.supportsTouchEvents` is set to `false`. +2. The fix MUST prevent the browser's default touch gesture handling from interrupting map drag sequences when a geo region enables roam dragging. +3. The fix MUST preserve existing drag behavior for roam-enabled geo maps in normal browser rendering. +4. The fix MUST NOT change interaction behavior for charts that are not geo roam drag scenarios. + +### Edge Cases + +1. When a geo region disables `roam.drag`, the browser's default touch behavior should remain unchanged. +2. When a chart does not use geo regions, the fix should not alter canvas touch handling. +3. When roam is toggled by spec updates, the canvas touch handling should reflect the latest spec state. + +## Success Criteria + +1. In pointer-only mobile browser mode, initial vertical dragging on a roam-enabled map no longer enters a broken partial-drag state. +2. Horizontal and vertical panning both work consistently without requiring a prior horizontal gesture. +3. Non-map or non-roam charts keep their existing page scrolling behavior.