Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug] ScatterChart brush selection with large amount of data is invalid #17079

Open
shiboqingning opened this issue May 21, 2022 · 10 comments
Open
Labels
bug en This issue is in English pending We are not sure about whether this is a bug/new feature. waiting-for: community

Comments

@shiboqingning
Copy link

Version

5.3

Link to Minimal Reproduction

https://echarts.apache.org/examples/zh/editor.html?c=scatter-large

Steps to Reproduce

  1. Create a scatter chart of a large amount of data
  2. Add brush configuration items to scatter chart
  3. Brush selected data

The specific code is as follows:

function genData(len, offset) {
  let arr = new Float32Array(len * 2);
  let off = 0;
  for (let i = 0; i < len; i++) {
    let x = +Math.random() * 10;
    let y =
      +Math.sin(x) -
      x * (len % 2 ? 0.1 : -0.1) * Math.random() +
      (offset || 0) / 10;
    arr[off++] = x;
    arr[off++] = y;
  }
  return arr;
}
const data1 = genData(5e5);
const data2 = genData(5e5, 10);
option = {
  title: {
    text:
      echarts.format.addCommas(data1.length / 2 + data2.length / 2) + ' Points'
  },
  tooltip: {},
  toolbox: {
    left: 'center',
    feature: {
      dataZoom: {}
    }
  },
  legend: {
    orient: 'vertical',
    right: 10
  },
  xAxis: [{}],
  yAxis: [{}],
  dataZoom: [
    {
      type: 'inside',
      xAxisIndex: [0]
    },
    {
      type: 'inside',
      yAxisIndex: [0]
    }
  ],
  animation: false,
  brush: {
    brushLink: 'all',
    toolbox: ['rect', 'polygon' , 'clear'],
    seriesIndex: 'all',
    xAxisIndex: 0,
    inBrush: {
      opacity: 1
    },
    throttleType: 'debounce',
    throttleDelay: 1000
  },
  series: [
    {
      name: 'A',
      type: 'scatter',
      data: data1,
      dimensions: ['x', 'y'],
      symbolSize: 3,
      itemStyle: {
        opacity: 0.4
      },
      large: true,
    },
    {
      name: 'B',
      type: 'scatter',
      data: data2,
      dimensions: ['x', 'y'],
      symbolSize: 3,
      itemStyle: {
        opacity: 0.4
      },
      large: true
    }
  ]
};

The renderings are as follows:
image

Current Behavior

Does not get the value of the brush selection and has no visual effects

Expected Behavior

Can get the brush selected data and have a visual effect

Environment

- OS:
- Browser:
- Framework:

Any additional comments?

No response

@echarts-bot echarts-bot bot added en This issue is in English pending We are not sure about whether this is a bug/new feature. waiting-for: community labels May 21, 2022
@FPI38
Copy link

FPI38 commented Oct 24, 2022

Same issue here. Is there anybody on this ? :)

@shiboqingning
Copy link
Author

Yes, they are the same, because no reply, thought not to be seen

@MatthiasMert
Copy link

MatthiasMert commented Jul 24, 2023

Brush selection doesnt seem to work with large data optimization which is enabled for both series (large: true). If large data optimization is disabled, the selection works as intended, though very slow compared to the zoom.

I would appreciate getting a selection tool that either works with large data optimization or is better optimized to begin with.

Here is the working code:

function genData(len, offset) {
  let arr = new Float32Array(len * 2);
  let off = 0;
  for (let i = 0; i < len; i++) {
    let x = +Math.random() * 10;
    let y =
      +Math.sin(x) -
      x * (len % 2 ? 0.1 : -0.1) * Math.random() +
      (offset || 0) / 10;
    arr[off++] = x;
    arr[off++] = y;
  }
  return arr;
}
const data1 = genData(5e5);
const data2 = genData(5e5, 10);
option = {
  title: {
    text:
      echarts.format.addCommas(data1.length / 2 + data2.length / 2) + ' Points'
  },
  tooltip: {},
  toolbox: {
    left: 'center',
    feature: {
      dataZoom: {}
    }
  },
  legend: {
    orient: 'vertical',
    right: 10
  },
  xAxis: [{}],
  yAxis: [{}],
  dataZoom: [
    {
      type: 'inside'
    },
    {
      type: 'slider'
    }
  ],
  animation: false,
  brush: {
    toolbox: ['rect', 'polygon', 'keep', 'clear'],
  },
  series: [
    {
      name: 'A',
      type: 'scatter',
      data: data1,
      dimensions: ['x', 'y'],
      symbolSize: 3,
      itemStyle: {
        opacity: 0.4
      },
    },
    {
      name: 'B',
      type: 'scatter',
      data: data2,
      dimensions: ['x', 'y'],
      symbolSize: 3,
      itemStyle: {
        opacity: 0.4
      },
    }
  ]
};

@shiboqingning
Copy link
Author

But the display of large amounts of data would be very slow

@MatthiasMert
Copy link

Are you planning to improve the brush/selection tool in the near future?

@shiboqingning
Copy link
Author

I hope to solve this problem, some business sometimes need to use, it is best to add circular box selection, triangle box selection and so on.

@MatthiasMert
Copy link

I think the brush is slower than zoom, because the points in the selected region have to be rerendered/highlighted on every mousemove while the selection box is drawn, whereas the zoom is only calculated once on brushEnd. I would suggest to implement a brush behaviour similar to zoom if the largeThreshold is exceeded.
So it would be still useable & performant with large scale data.

Should I open a new feature request for that?

@shiboqingning
Copy link
Author

I think it is OK, depending on how much work you do. My business is mainly used for the Mapping of the wafer.

@stephweiss
Copy link

I have the same problem here

@MatthiasMert
Copy link

MatthiasMert commented Aug 21, 2023

The following small change in the source code seems to work:
In BrushView.ts exchange the _onBrush method:

// original code from BrushView.ts
private _onBrush(eventParam: BrushControllerEvents['brush']): void {
    const modelId = this.model.id;

    const areas = this.model.brushTargetManager.setOutputRanges(eventParam.areas, this.ecModel);

    // Action is not dispatched on drag end, because the drag end
    // emits the same params with the last drag move event, and
    // may have some delay when using touch pad, which makes
    // animation not smooth (when using debounce).
    (!eventParam.isEnd || eventParam.removeOnClick) && this.api.dispatchAction({
        type: 'brush',
        brushId: modelId,
        areas: zrUtil.clone(areas),
        $from: modelId
    });
    eventParam.isEnd && this.api.dispatchAction({
        type: 'brushEnd',
        brushId: modelId,
        areas: zrUtil.clone(areas),
        $from: modelId
    });
}

by the following code:

// changed code
private _onBrush(eventParam: BrushControllerEvents['brush']): void {
    const throttleType = this.model.option.throttleType;
    if (throttleType === 'debounce' && !eventParam.isEnd) {
        return;
    }

    const modelId = this.model.id;

    const areas = this.model.brushTargetManager.setOutputRanges(eventParam.areas, this.ecModel);

    // Action is not dispatched on drag end, because the drag end
    // emits the same params with the last drag move event, and
    // may have some delay when using touch pad, which makes
    // animation not smooth (when using debounce).
    (throttleType === 'debounce' || !eventParam.isEnd || eventParam.removeOnClick) && this.api.dispatchAction({
        type: 'brush',
        brushId: modelId,
        areas: zrUtil.clone(areas),
        $from: modelId
    });
    eventParam.isEnd && this.api.dispatchAction({
        type: 'brushEnd',
        brushId: modelId,
        areas: zrUtil.clone(areas),
        $from: modelId
    });
}

using the throttleType property (as it is intended if i understand correctly) to enable an "only render on release" mode.

Now use the brush component with debounce mode:

brush: {
    throttleType: 'debounce'
}

And enable large data optimization mode for your series and set the largeThreshold to a value larger than the number of items in your series (dont ask me why but it works this way):

series: [
    {
        type: 'scatter'.
        ...,
        large: true,
        largeThreshold: 99999999,
    },
    ...
]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug en This issue is in English pending We are not sure about whether this is a bug/new feature. waiting-for: community
Projects
None yet
Development

No branches or pull requests

4 participants