diff --git a/__tests__/integration/api-chart-emit-scrollbar-filter.spec.ts b/__tests__/integration/api-chart-emit-scrollbar-filter.spec.ts index 5aa3da0c38..552161f292 100644 --- a/__tests__/integration/api-chart-emit-scrollbar-filter.spec.ts +++ b/__tests__/integration/api-chart-emit-scrollbar-filter.spec.ts @@ -46,7 +46,7 @@ describe('chart.emit', () => { chart.on('scrollbarX:filter', (event) => { if (!event.nativeEvent) return; expect(event.data.selection).toEqual([ - ['2001-05', '2002-03'], + ['2001-05', '2002-04'], [50, 500], ]); resolveX(); @@ -60,7 +60,7 @@ describe('chart.emit', () => { chart.on('scrollbarY:filter', (event) => { if (!event.nativeEvent) return; expect(event.data.selection).toEqual([ - ['2001-05', '2002-03'], + ['2001-05', '2002-04'], [150, 450], ]); resolveY(); diff --git a/__tests__/integration/api-chart-emit-slider-filter.spec.ts b/__tests__/integration/api-chart-emit-slider-filter.spec.ts index fe8482f9a6..06148bd15e 100644 --- a/__tests__/integration/api-chart-emit-slider-filter.spec.ts +++ b/__tests__/integration/api-chart-emit-slider-filter.spec.ts @@ -46,7 +46,7 @@ describe('chart.emit', () => { chart.on('sliderX:filter', (event) => { if (!event.nativeEvent) return; expect(event.data.selection).toEqual([ - ['2001-05', '2002-03'], + ['2001-05', '2002-04'], [50, 550], ]); resolveX(); @@ -60,7 +60,7 @@ describe('chart.emit', () => { chart.on('sliderY:filter', (event) => { if (!event.nativeEvent) return; expect(event.data.selection).toEqual([ - ['2001-05', '2002-03'], + ['2001-05', '2002-04'], [150, 450], ]); resolveY(); diff --git a/__tests__/integration/snapshots/interaction/stocks-line-slider-wheel/step0.svg b/__tests__/integration/snapshots/interaction/stocks-line-slider-wheel/step0.svg index 5b489f935a..85636a22b6 100644 --- a/__tests__/integration/snapshots/interaction/stocks-line-slider-wheel/step0.svg +++ b/__tests__/integration/snapshots/interaction/stocks-line-slider-wheel/step0.svg @@ -292,19 +292,19 @@ - + - + - + - + - + diff --git a/__tests__/integration/snapshots/interaction/stocks-line-slider-wheel/step1.svg b/__tests__/integration/snapshots/interaction/stocks-line-slider-wheel/step1.svg index b783135ef0..c848190282 100644 --- a/__tests__/integration/snapshots/interaction/stocks-line-slider-wheel/step1.svg +++ b/__tests__/integration/snapshots/interaction/stocks-line-slider-wheel/step1.svg @@ -293,19 +293,19 @@ - + - + - + - + - + diff --git a/__tests__/integration/snapshots/interaction/stocks-line-slider-wheel/step2.svg b/__tests__/integration/snapshots/interaction/stocks-line-slider-wheel/step2.svg index e576b461f5..09f8f26676 100644 --- a/__tests__/integration/snapshots/interaction/stocks-line-slider-wheel/step2.svg +++ b/__tests__/integration/snapshots/interaction/stocks-line-slider-wheel/step2.svg @@ -294,19 +294,19 @@ - + - + - + - + - + diff --git a/__tests__/integration/snapshots/interaction/stocks-line-slider-wheel/step3.svg b/__tests__/integration/snapshots/interaction/stocks-line-slider-wheel/step3.svg index 327bf1774e..b61852e3ca 100644 --- a/__tests__/integration/snapshots/interaction/stocks-line-slider-wheel/step3.svg +++ b/__tests__/integration/snapshots/interaction/stocks-line-slider-wheel/step3.svg @@ -295,19 +295,19 @@ - + - + - + - + - + diff --git a/__tests__/integration/snapshots/interaction/stocks-line-slider/step1.svg b/__tests__/integration/snapshots/interaction/stocks-line-slider/step1.svg index 8fa5d554e2..dc47463a83 100644 --- a/__tests__/integration/snapshots/interaction/stocks-line-slider/step1.svg +++ b/__tests__/integration/snapshots/interaction/stocks-line-slider/step1.svg @@ -230,1586 +230,1574 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - + - + - + - + - + - + diff --git a/__tests__/plots/bugfix/index.ts b/__tests__/plots/bugfix/index.ts index 6d4fc9d614..fa1940286b 100644 --- a/__tests__/plots/bugfix/index.ts +++ b/__tests__/plots/bugfix/index.ts @@ -12,3 +12,4 @@ export { issue6747 } from './issue-6747'; export { issueChart2897 } from './issue-chart-2897'; export { issue6863 } from './issue-6863'; export { issue6970 } from './issue-6970'; +export { issue6751 } from './issue-6751'; diff --git a/__tests__/plots/bugfix/issue-6751.ts b/__tests__/plots/bugfix/issue-6751.ts new file mode 100644 index 0000000000..9d9588d4f8 --- /dev/null +++ b/__tests__/plots/bugfix/issue-6751.ts @@ -0,0 +1,52 @@ +import { Chart } from '../../../src'; + +export async function issue6751(context) { + const { container, canvas } = context; + const chart = new Chart({ + container, + canvas, + }); + const data = [ + { + x: 0.8, + y: 'A', + }, + { + x: 1, + y: 'A', + }, + { + x: 2, + y: 'B', + }, + { + x: 3, + y: 'C', + }, + ]; + chart + .point() + .data(data) + .encode('x', 'x') + .encode('y', 'y') + .interaction('brushHighlight', {}) + .scale({ + x: { + domain: [0.5, 5], + }, + y: { + range: [1, 0], + }, + }); + + chart.on('brush:end', (e) => { + console.log(e.data.selection); + }); + + const finished = chart.render(); + + return { + chart, + finished, + }; +} diff --git a/src/component/slider.ts b/src/component/slider.ts index f8b31ebb2e..716babc7d7 100644 --- a/src/component/slider.ts +++ b/src/component/slider.ts @@ -71,7 +71,7 @@ export const Slider: GCC = (options) => { formatter: (v) => { const f = formatter || defaultFormatter; const v1 = reverse ? 1 - v : v; - const tick = invert(scale, v1, true); + const tick = invert(scale, v1); return f(tick); }, sparklineData: inferSparklineData(options, context), diff --git a/src/interaction/sliderFilter.ts b/src/interaction/sliderFilter.ts index 63ca337b71..621d886996 100644 --- a/src/interaction/sliderFilter.ts +++ b/src/interaction/sliderFilter.ts @@ -352,8 +352,8 @@ function abstractValue( ) { const [x, x1] = values; const v = reverse ? (d: number) => 1 - d : (d: number) => d; - const d0 = invert(scale, v(x), true); - const d1 = invert(scale, v(x1), false); + const d0 = invert(scale, v(x)); + const d1 = invert(scale, v(x1)); return domainOf(scale, [d0, d1]); } diff --git a/src/interaction/tooltip.ts b/src/interaction/tooltip.ts index 12142c0158..03ab019c76 100644 --- a/src/interaction/tooltip.ts +++ b/src/interaction/tooltip.ts @@ -1096,7 +1096,7 @@ export function seriesTooltip( nativeEvent: true, data: { ...tooltipData, - data: { x: invert(scale.x, transformedX, true) }, + data: { x: invert(scale.x, transformedX) }, }, }); }, diff --git a/src/utils/scale.ts b/src/utils/scale.ts index 1a904d1a40..02ca1eee92 100644 --- a/src/utils/scale.ts +++ b/src/utils/scale.ts @@ -1,27 +1,32 @@ -import { bisectLeft, sort } from '@antv/vendor/d3-array'; - -function constrain(x, lo, hi) { - return Math.min(hi, Math.max(lo, x)); -} +import { sort } from '@antv/vendor/d3-array'; export function isOrdinalScale(scale) { return !!scale.getBandWidth; } -export function invert(scale, x, start) { +export function invert(scale, x) { if (!isOrdinalScale(scale)) return scale.invert(x); - const { adjustedRange } = scale; - if (adjustedRange.includes(x)) { - return scale.invert(x); - } - const { domain } = scale.getOptions(); - const offset = start ? -1 : 0; + const domain = scale.getOptions().domain; + const range = scale.adjustedRange; const step = scale.getStep(); - const range = start ? adjustedRange : adjustedRange.map((d) => d + step); - // R[i0 - 1] < x <= R[i0] - const i0 = bisectLeft(range, x); - const i1 = constrain(i0 + offset, 0, domain.length - 1); - return domain[i1]; + const bandwidth = scale.getBandWidth?.() ?? step; + + // compute centers of each band + const centers = range.map((r) => r + bandwidth / 2); + + // find nearest center + let min = Infinity; + let index = 0; + + for (let i = 0; i < centers.length; i++) { + const d = Math.abs(x - centers[i]); + if (d < min) { + min = d; + index = i; + } + } + + return domain[index]; } export function domainOf(scale, values, ratioX?) { @@ -50,14 +55,14 @@ export function domainOf(scale, values, ratioX?) { export function selectionOf(x, y, x1, y1, scale, coordinate) { const { x: scaleX, y: scaleY } = scale; - const abstractDomain = (point, start) => { - const [x, y] = coordinate.invert(point); - return [invert(scaleX, x, start), invert(scaleY, y, start)]; + const abstract = (point) => { + const [px, py] = coordinate.invert(point); + return [invert(scaleX, px), invert(scaleY, py)]; }; - const p0 = abstractDomain([x, y], true); - const p1 = abstractDomain([x1, y1], false); - const domainX = domainOf(scaleX, [p0[0], p1[0]]); - const domainY = domainOf(scaleY, [p0[1], p1[1]]); + const p0 = abstract([x, y]); + const p1 = abstract([x1, y1]); + const domainX = domainOf(scaleX, p0[0] !== undefined ? [p0[0], p1[0]] : []); + const domainY = domainOf(scaleY, p0[1] !== undefined ? [p0[1], p1[1]] : []); return [domainX, domainY]; } diff --git a/vite.config.ts b/vite.config.ts index 2cee6b3fc8..78776b96e5 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -16,10 +16,6 @@ if (LINK === '1' && !MODULE) { */ const baseOptions: UserConfig = { root: './__tests__/', - server: { - port: 8080, - open: '/', - }, build: { outDir: '../' }, };