ChartJS re-rendering bug - javascript

So I'm building a trading tool and am using chartJS for the charts. This is how my charts look now on the page:
So my problem is that when I change the time period of the chart, the chart shows randomly the old data mixed with the new one.
You can see the behaviour here: https://gifyu.com/image/vda5
For now I can't use the Big chart together with the small one on the same page because the big chart which has the timing period has also multiple AJAX calls so every time I click on "1W" for example, a new call is being made and the chart is drawn over.
Things I tried:
I know that for dynamic charts in chartJS I have to destroy the chart, so I'm using
if (window.chart !== undefined) window.chart.destroy();
and for the small charts I use an empty array and push the elements inside. Here is how I do it:
if ($(quoteDisplayEl).hasClass('quoteDisplay-light')) {
chartHandel.push(quoteChart);
} else {
window.chart = quoteChart;
}
so for the big chart I assign it to a global variable and the small one I push it to the empty array - that allows me to have multiple charts on one page.
But in order for the big chart to be destroyed I should destroy and re-render all charts from scratch (I guess) and I tried multiple was of achieving that with now luck.
Unfortunately the code is over 500 lines and has lots of variable data coming from APIs and DB thus I can't make a fiddle demo.

I prefer chart.update() over chart.destroy().
Here's a small, simple example how I usually update data.
I make one object per chart with labels (empty array) and data (empty array) and colors and all the stuff you need.
I fill these arrays with data I get (AJAX).
Optional: If I get all the data and need to filter it to show less data, I copy my object to keep all the data I got and have all the data I need now for my chart in another object
Make an updateChart() function which alters your displayed data or saved data from your backup object or use new data from a new AJAX request.
End your updateChart() with chart.update() (or whatever your chart is called).
Multiple charts shouldn't be a problem and you shouldn't have to destroy your chart.

Related

Unable to create custom indicator

Checked all the samples in here: https://www.anychart.com/products/anystock/gallery/Stock_Technical_Indicators/?theme=darkEarth All are calculated by any chart functions. indicatorPlot is getting members like .adl etc..
Also checked the sample here with setCalculationFunction: https://www.anychart.com/blog/2018/03/14/custom-technical-indicators-javascript-stock-charts/
Is there a way to "map indicatorPlot" with a csv values like drawing the main graph? Or is datatable can store indicator values to show underneath the chart like oscilators.
The main question is: Is there a way to display a custom oscillator under the chart feeded with values from csv, json etc.. ?
Yes, in this case, the indicator is a usual series that is based on your data. Simply create a series from your data, provide the desired name and that's it.

Creating datapoints on mouseclick Chart.js

I am new to Chart.js and JavaScript. Currently working with a line chart, and now I want to add custom data points to a mouse click event (when I press somewhere on the data set, it takes the current value of the Y axis and using that value it creates a data point in that place). I took the code from http://www.chartjs.org/samples/latest/charts/line/basic.html and trying to modify it. Here is a link to my current chart:
https://i.stack.imgur.com/M9MF1.jpg
I am using the basic chart.bundle.js library, and used D3.js libraries for making data points draggable.
Trying to implement the creation of points per mouse click using the following code, but it seems that it's not good so far.
document.getElementById('canvas').onclick = function(e){
//getting value by pressing on dataset
value = chartInstance.scales[scale].getValueForPixel(e.clientY)
//trying to create dataPoint
myLineChart.points.push(new this.PointClass({
y: value;
strokeColor: this.datasets[datasetIndex].pointStrokeColor,
fillColor: this.datasets[datasetIndex].pointColor
}));
//after all updating my chart
chartInstance.Update(0)
};
Maybe anyone could explain more about this library and how it creates data points?
Every new point in the chart is data, so you need to add that point in the data (chartData.data.dataset[]) array. Instead of adding to the, myLineChart.points which i'm not sure why you have used you should add the data-point in the data array and the UI decorations such as colors are supposed to be specified in the chartOptions.scales.yAxes[] array. Therefore in order to add the point in the chart use:
// here i is the corresponding parameter for which you want to add the new point
chartInstance.data.datasets[i].push(value);
chartInstance.update();

Cannot read property 'info' of undefined

I am having an issue where I get the error in the title of this question when I create a chart like the one in this fiddle http://jsfiddle.net/w43m47hL/.
I get this problem when selecting a point.
this.select();
The problem occurs when performing these steps.
create the chart
click on a point to select it
destroy the chart
create the chart again
The size of the data set seems to have something to do with the problem. If you change 1500 to 15 you will see that you don't get this problem any more. However the data point that was selected is still selected after the chart is destroyed and created again. I would have thought that the point would not be selected since the chart was destroyed. How is the data point remembering that it was selected?
The issue is caused by keeping reference to "old" data array. During chart initialisation, you set the reference to data array, which is modified. So when you destroy chart, reference still exists. Use the copy of data ($.extend([],data)) in Highcharts objects.
series: [{
data: $.extend([], data)
}],
Example:
http://jsfiddle.net/nazr3det/

HighCharts navigator to keep range after async data load. (LazyLoad)

I am doing something similar to the HighCharts Lazy Loader example. It works, except that when I zoom into a region, I fetch higher resolution data and update via
chart.series[1].setData(data);
This resets the navigator range (extremes?) to the range of new incoming data. I am using almost everything that the lazy load example talks about, but no use.
navigator:{adaptToUpdatedData:false},
scrollbar:{liveRedraw:false}
Thanks.
Why do you use:
chart.series[1].setData(data);
I'm pretty sure there should be:
chart.series[0].setData(data);
Simply, if you have just one series on a chart, then series[0] -> your series, and series[1] is series in navigator. That's most probably reason why you get navigator updated, but you want to update series.
Try using setExtreme function in the callback of the lazyload. http://api.highcharts.com/highstock#xAxis.events.setExtremes
I guess the only way to do this is to make the new data array match to the required range with empty values.
http://forums.highcharts.com/highstock-usage/any-way-to-force-x-axis-extremes-to-match-selected-timeframe-t31154/

D3 graphing selective portions of data set

I have a large time series data set I need to graph, and am trying to use D3 to do it. I plan to have my graph have the x-axis be time, and allow for movement of the graph in the x direction. I want to have the graph only load/display the points that exist in the current time range on the screen.
For example, if my dataset has times 1-100, but the graph starts out with times 1-10 shown, the graph should only graph points 1-10. Then the user may move to the right and see times 5-15 and the graph should update accordingly.
Can anyone explain to me how this might be done via d3? I am having a hard time bridging the understanding from an entire data set being loaded in at once and graphed immediately to selective graphing of subsets of the data.
I think you are looking for the selection.filter() function. For example you can have:
var allNodes = vis.selectAll("Nodes").data(data.nodes);
var validNodes = allNodes.filter(function(d){return (d.time>1 && d.time <10)});
//use normal graph functions on validNodes.
You can also apply filter directly on the array of nodes.

Categories

Resources