Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"changes": [
{
"comment": "update changes for 009-fix-heatmap-scrollbar-axis-direction: Align ScrollBar with DataZoom by using the shared reverse-axis detection when converting scrollbar state percentages back into domain values.",
"type": "none",
"packageName": "@visactor/vchart"
}
],
"packageName": "@visactor/vchart",
"email": "lixuef1313@163.com"
}
Original file line number Diff line number Diff line change
Expand Up @@ -76,4 +76,48 @@ describe('ScrollBar', () => {
expect(attrs.range[0]).toBeCloseTo(0.98);
expect(attrs.range[1]).toBeCloseTo(1);
});

it('should map reversed vertical axis state to top-first domain values', () => {
const spec: any = {
orient: 'right'
};

scrollBar = new ScrollBar(spec, option);

const handleStateChange = jest.fn().mockReturnValue(true);
const emit = jest.fn();

(scrollBar as any)._handleStateChange = handleStateChange;
(scrollBar as any)._stateScale = {
type: 'band',
range: () => [100, 0],
domain: () => ['A', 'B', 'C', 'D'],
invert: (value: number) => {
if (value < 25) {
return 'A';
}
if (value < 50) {
return 'B';
}
if (value < 75) {
return 'C';
}
return 'D';
}
};
(scrollBar as any)._relatedAxisComponent = {
getScale: () => ({
range: () => [100, 0]
}),
getInverse: () => false
};
(scrollBar as any).event = { emit };
(scrollBar as any)._start = 0;
(scrollBar as any)._end = 1;

(scrollBar as any)._handleChange(0, 0.5);

expect(handleStateChange).toHaveBeenCalledWith('A', 'C');
expect(emit).toHaveBeenCalled();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ import { Factory } from '../../../core/factory';
import type { ILayoutType } from '../../../typings/layout';
import { isClose } from '../../../util';
import { scrollBar } from '../../../theme/builtin/common/component/scroll-bar';
import { statePointToData } from '../util';
import { isReverse, statePointToData } from '../util';
import type { CartesianAxis } from '../../axis/cartesian';
// import { SCROLLBAR_EVENT, SCROLLBAR_END_EVENT } from '@visactor/vrender-components/es/constant';

// 由vrender透出, 接入新版本后需修改
Expand Down Expand Up @@ -59,8 +60,10 @@ export class ScrollBar<T extends IScrollBarSpec = IScrollBarSpec> extends DataFi

this._start = start;
this._end = end;
const startValue = statePointToData(start, this._stateScale, false);
const endValue = statePointToData(end, this._stateScale, false);
const axis = this._relatedAxisComponent as CartesianAxis<any>;
const reverse = isReverse(axis, this._isHorizontal);
const startValue = statePointToData(start, this._stateScale, reverse);
const endValue = statePointToData(end, this._stateScale, reverse);
const hasChange = isFunction(this._spec.updateDataAfterChange)
? this._spec.updateDataAfterChange(start, end, startValue, endValue)
: this._handleStateChange(startValue, endValue);
Expand Down
44 changes: 44 additions & 0 deletions specs/009-fix-heatmap-scrollbar-axis-direction/plan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Implementation Plan: Fix Heatmap Scrollbar Axis Direction

**Branch**: `009-fix-heatmap-scrollbar-axis-direction` | **Date**: 2026-03-23 | **Spec**: [/data00/home/lixuefei.1313/github/VChart/specs/009-fix-heatmap-scrollbar-axis-direction/spec.md](/data00/home/lixuefei.1313/github/VChart/specs/009-fix-heatmap-scrollbar-axis-direction/spec.md)
**Input**: Feature specification from `/specs/009-fix-heatmap-scrollbar-axis-direction/spec.md`

## Summary

Fix the heatmap scrollbar and left-axis direction mismatch by aligning `ScrollBar` with `DataZoom` when converting scrollbar state percentages back into domain values. Add a focused regression test covering a vertical reversed discrete axis, which is the path exercised by the heatmap reproduction.

## Technical Context

**Language/Version**: TypeScript 4.9.x
**Primary Dependencies**: `@visactor/vscale`, `@visactor/vutils`, `@visactor/vrender-components`
**Testing**: Jest 26 unit tests under `packages/vchart/__tests__`
**Target Platform**: Browser and cross-platform cartesian chart runtime
**Project Type**: Monorepo charting library package (`packages/vchart`)
**Constraints**: Preserve existing `dataZoom` behavior; avoid changing axis range calculation; keep the fix scoped to scrollbar state-domain conversion

## Constitution Check

- Pass: The work is narrowly scoped to the documented bug.
- Pass: The change reuses an existing shared utility instead of introducing a new behavior branch.
- Pass: Regression coverage will be added for the user-visible bug path.

## Project Structure

```text
specs/009-fix-heatmap-scrollbar-axis-direction/
├── plan.md
├── spec.md
└── tasks.md
```

```text
packages/vchart/
├── src/component/data-zoom/scroll-bar/scroll-bar.ts
└── __tests__/unit/component/data-zoom/scroll-bar/scroll-bar.test.ts
```

## Implementation Strategy

1. Update `ScrollBar._handleChange` to derive `startValue` and `endValue` with `isReverse(axis, this._isHorizontal)`.
2. Add a regression test that mocks a reversed vertical band axis and asserts scrollbar state `0 -> 0.5` maps to the top half of the domain.
3. Run the focused Jest test file and inspect the diff for unintended churn.
41 changes: 41 additions & 0 deletions specs/009-fix-heatmap-scrollbar-axis-direction/spec.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Feature Specification: Fix Heatmap Scrollbar Axis Direction

**Feature Branch**: `009-fix-heatmap-scrollbar-axis-direction`
**Created**: 2026-03-23
**Status**: Draft
**Input**: User description: "Fix VChart issue #4320: heatmap right scrollbar scroll direction is opposite to the left band axis order"

## User Scenarios & Testing *(mandatory)*

### User Story 1 - Keep Vertical Scroll Direction Consistent (Priority: P1)

As a chart author using a heatmap with a right-side vertical scrollbar, I want the visible left-axis labels to move in the same direction as the scrollbar thumb so that the viewport behaves consistently with bar charts and user expectations.

**Why this priority**: The reported bug breaks the primary interaction for scrolling long heatmap category axes and makes the chart feel inverted.

**Independent Test**: Render a heatmap with a left `band` axis and a right `scrollBar` bound to the same Y field. Move the scrollbar to the top and verify the axis viewport shows the first categories rather than the last categories.

**Acceptance Scenarios**:

1. **Given** a heatmap whose Y axis is a vertical band axis and whose `scrollBar.orient` is `right`, **When** the scrollbar range starts at `0`, **Then** the left axis viewport shows the earliest/top categories in the axis domain.
2. **Given** the same chart, **When** the scrollbar is dragged downward, **Then** the visible Y-axis categories advance downward in the same direction as the scrollbar thumb.

### Edge Cases

- Vertical discrete axes whose internal scale range is reversed because of cartesian axis layout should still map scrollbar state to domain values correctly.
- Horizontal scrollbars and already-correct dataZoom behavior must remain unchanged.

## Requirements *(mandatory)*

### Functional Requirements

- **FR-001**: The scrollbar component MUST resolve discrete axis domain values using the same reverse-axis logic as other data-filter components.
- **FR-002**: For vertical cartesian band axes, a scrollbar state near `start = 0` MUST map to the top of the visible axis domain instead of the bottom when the axis scale range is reversed by layout.
- **FR-003**: Existing scrollbar behavior for non-reversed or horizontal axes MUST remain backward compatible.

## Success Criteria *(mandatory)*

### Measurable Outcomes

- **SC-001**: In the issue #4320 reproduction, placing the right scrollbar thumb at the top shows the top portion of the heatmap Y-axis domain.
- **SC-002**: A focused automated regression test proves scrollbar state-to-domain conversion respects reversed vertical axis ranges.
27 changes: 27 additions & 0 deletions specs/009-fix-heatmap-scrollbar-axis-direction/tasks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Tasks: Heatmap Scrollbar Axis Direction

**Input**: Design documents from `/specs/009-fix-heatmap-scrollbar-axis-direction/`
**Prerequisites**: plan.md, spec.md

**Tests**: Include focused unit regression coverage for the reversed vertical axis path.

## Phase 1: Setup

- [x] T001 Inspect scrollbar reverse-mapping logic and compare it with `dataZoom`

## Phase 2: User Story 1 - Keep Vertical Scroll Direction Consistent (Priority: P1)

**Goal**: Make right-side heatmap scrollbar movement and left-axis viewport order move in the same direction

### Tests for User Story 1

- [x] T002 [US1] Add a scrollbar regression test for reversed vertical axis mapping in `packages/vchart/__tests__/unit/component/data-zoom/scroll-bar/scroll-bar.test.ts`

### Implementation for User Story 1

- [x] T003 [US1] Reuse shared reverse-axis detection in `packages/vchart/src/component/data-zoom/scroll-bar/scroll-bar.ts`

## Phase 3: Polish

- [ ] T004 Run the focused Jest test for scrollbar regressions
- [x] T005 Update task tracking after implementation
Loading