amcharts / amcharts5

The newest, fastest, and most advanced amCharts charting library for JavaScript and TypeScript apps.
324 stars 90 forks source link

Switching between two different chart types doesn't display all parts of the chart #470

Closed BabakAmini closed 1 year ago

BabakAmini commented 2 years ago

I have a dataset that includes OHLC data as well as prices that are named plp.

The first time my page renders, it displays plp data against time as a SmoothedXLineSeries chart without any issues. I've added a switch button to the top left corner of the page to switch between the SmoothedXLineSeries and CandlestickSeries charts. But if you click on that button, you can see that only a small part of the new chart is displaying, and if you zoom in or out, then all parts of the chart will display correctly. The same thing will happen if you click on the switch button again.

The only way to resolve this issue is to enable groupData: true at line 1229. You can also try to reduce the number of items in the dataset without enabling data grouping, but it yields unpredictable results.

Here is a simplified version of my code:

https://codepen.io/BabakA/pen/NWYPMXY

I wonder why this is happening, and I don't want to use data grouping for this code.

xorspark commented 2 years ago

One thing that sticks out is that you didn't set the data processor on the candlestick series so that it parses the dates correctly, as you only did this on the line series. Unfortunately the chart still requires some sort of interaction for the candlestick series to finish redrawing itself.

As an alternative, why not just set the data on both charts and toggle their visibility using show/hide instead? This gives the same intended result without having the overhead of re-parsing the same dataset to toggle views (and the candlestick renders correctly in this scenario):


candleSeries = chart.series.push(
  am5xy.CandlestickSeries.new(root,
    // ...
    visible: false,
    // ...
  })
);

// ...
candleSeries.data.processor = am5.DataProcessor.new(root, {
  dateFields: ["time"],
  dateFormat: "HH:mm:ss"
});
candleSeries.data.setAll(data);
// ...

function onCandelicChanged() {
  var x = document.getElementById("candle switch");
  if (x.checked) {
    plSeries.hide(0); // pass zero to show/hide transitions if desired
    candleSeries.show(0);
  } else {
    candleSeries.hide(0);
    plSeries.show(0);
  }
}

Codepen

zeroin commented 2 years ago

Initially your series has no data, so it saves it's indexes as 0,0. And it keeps them after the data is set. So a proper solution would be to set private endIndex to the length of your data:

function onCandelicChanged() {
  var x = document.getElementById("candle switch");
  if (x.checked) {
    plSeries.data.clear();
    candleSeries.data.setAll(data);
    candleSeries.setPrivate("startIndex", 0)
    candleSeries.setPrivate("endIndex", data.length)    

  } else {
    candleSeries.data.clear();
    plSeries.data.setAll(data);
    plSeries.setPrivate("startIndex", 0)
    plSeries.setPrivate("endIndex", data.length)        
  }
}
BabakAmini commented 2 years ago

@xorspark Your workaround saved me, thanks. According to this link, only one series needs to define data processors. Adding candleSeries.data.setAll(data) at initial state also works but show/hide trick is much better than this.

@zeroin If indexes were set to zero, then nothing should be displayed, but as you can see, whenever you switch the button, two data items are displayed. Also, as far as I know, data is parsed and processed immediately after it is set. So, indexes should be set after the data is set in the event handler. I don't understand why setting the data isn't enough to redraw the chart and why I have to do a zoom or enable data grouping to make this work.

martynasma commented 2 years ago

Let's keep this place clutter-free, both for our own sake and the other's. If you have other questions, not directly related to original topic, please post a separate issue.

github-actions[bot] commented 1 year ago

This issue is stale because it has been open 30 days with no activity. It will be closed in 5 days unless a new comment is added.