diff --git a/__tests__/integration/snapshots/interaction/aapl-line-slider-filter/step2.png b/__tests__/integration/snapshots/interaction/aapl-line-slider-filter/step2.png new file mode 100644 index 0000000000..d0476821f5 Binary files /dev/null and b/__tests__/integration/snapshots/interaction/aapl-line-slider-filter/step2.png differ diff --git a/__tests__/plots/interaction/appl-line-slider-filter.ts b/__tests__/plots/interaction/appl-line-slider-filter.ts index acc2e49127..561cba5241 100644 --- a/__tests__/plots/interaction/appl-line-slider-filter.ts +++ b/__tests__/plots/interaction/appl-line-slider-filter.ts @@ -30,9 +30,7 @@ export function dispatchValueChange(slider, values = [0.25, 0.75]) { slider.update({ values }); slider.dispatchEvent( new CustomEvent('valuechange', { - detail: { - value: [0.25, 0.75], - }, + detail: { value: values }, }), ); } @@ -54,5 +52,10 @@ aaplLineSliderFilter.steps = ({ canvas }) => { dispatchValueChange(s2); }, }, + { + changeState: () => { + dispatchValueChange(s1, [0.7, 0.9]); + }, + }, ]; }; diff --git a/src/interaction/scrollbarFilter.ts b/src/interaction/scrollbarFilter.ts index ced43727d0..e398dad499 100644 --- a/src/interaction/scrollbarFilter.ts +++ b/src/interaction/scrollbarFilter.ts @@ -9,19 +9,20 @@ export function ScrollbarFilter(options: any = {}) { if (!scrollbars.length) return () => {}; const { scale } = view; const { x: scaleX, y: scaleY } = scale; - const channelDomain = { - x: scaleX.getOptions().domain, - y: scaleY.getOptions().domain, + + // The filtered domain, computed by the ratio attribute. + const initDomain = { + x: [...scaleX.getOptions().domain], + y: [...scaleY.getOptions().domain], }; - scaleX.update({ - domain: scaleX.getOptions().expectedDomain, - }); - scaleY.update({ - domain: scaleY.getOptions().expectedDomain, - }); + + // The ordinal domain for each channel. + scaleX.update({ domain: scaleX.getOptions().expectedDomain }); + scaleY.update({ domain: scaleY.getOptions().expectedDomain }); + const interaction = SliderFilter({ ...options, - channelDomain, + initDomain, className: SCROLLBAR_CLASS_NAME, prefix: 'scrollbar', hasState: true, diff --git a/src/interaction/sliderFilter.ts b/src/interaction/sliderFilter.ts index 61d0c63688..0af52aafe1 100644 --- a/src/interaction/sliderFilter.ts +++ b/src/interaction/sliderFilter.ts @@ -5,7 +5,14 @@ import { invert, domainOf, abstractOf } from '../utils/scale'; export const SLIDER_CLASS_NAME = 'slider'; -function filterDataByDomain(options, scaleOptions, prefix, hasState = false) { +function filterDataByDomain( + options, + scaleOptions, + prefix, + hasState = false, + channel0 = 'x', + channel1 = 'y', +) { const { marks } = options; const newMarks = marks.map((mark) => deepMix( @@ -21,11 +28,12 @@ function filterDataByDomain(options, scaleOptions, prefix, hasState = false) { scale: scaleOptions, // Don't rerender sliders. [prefix]: { - ...(mark[prefix]?.x && { - x: { preserve: true, ...(hasState && { ratio: null }) }, + ...(mark[prefix]?.[channel0] && { + [channel0]: { preserve: true, ...(hasState && { ratio: null }) }, }), - ...(mark[prefix]?.y && { - y: { preserve: true, ...(hasState && { ratio: null }) }, + // Only remove ratio state with filtered channel. + ...(mark[prefix]?.[channel1] && { + [channel1]: { preserve: true }, }), }, animate: false, @@ -58,7 +66,7 @@ function extentOf(domain) { * @todo Support click to reset after fix click and dragend conflict. */ export function SliderFilter({ - channelDomain, + initDomain = {}, className = SLIDER_CLASS_NAME, prefix = 'slider', setValue = (component, values) => component.setValues(values), @@ -89,12 +97,10 @@ export function SliderFilter({ const emitHandlers = new Set<[string, (event: any) => void]>(); // Store current domain of x and y scale. - if (!channelDomain) { - channelDomain = { - x: scaleX.getOptions().domain, - y: scaleY.getOptions().domain, - }; - } + const channelDomain = { + x: initDomain.x || scaleX.getOptions().domain, + y: initDomain.y || scaleY.getOptions().domain, + }; for (const slider of sliders) { const { orientation } = slider.attributes; @@ -152,13 +158,13 @@ export function SliderFilter({ setState(slider, (options) => ({ ...filterDataByDomain( options, - { - // Set nice to false to avoid modify domain. - [channel0]: { domain: domain0, nice: false }, - [channel1]: { domain: domain1, nice: false }, - }, + // Set nice to false to avoid modify domain. + // Only update domain of current slider / scrollbar. + { [channel0]: { domain: domain0, nice: false } }, prefix, hasState, + channel0, + channel1, ), paddingLeft, paddingTop,