When Using NVD3 Line Chart Draws Erratically - javascript

I'm wondering if anyone might be able to help with an issue I'm having with NVD3 where the chart occasionally gets drawn erratically. This typically occurs when I leverage the toggle for labels (i.e. where you can show or hide different lines). The result is something that looks like the following image:
Initially the chart looks normal (i.e. a single line). However, after enabling and disable other lines on the chart, the image ends up being drawn in the erratic fashion shown above.
Any help on how to address this would be greatly appreciated. I was not sure what to search for to describe the issue so apologies if the answer was readily available.

In case anyone else runs across this (which is actually unlikely) I tracked down the issue to the following added lines of code to the "mouseover_line" event (commented out below):
function mouseover_line(evt) {
var yaxis = data[evt.seriesIndex].yAxis === 2 ? yAxis2 : yAxis1;
// evt.series.values[evt.pointIndex].x = d3.time.format('%x')(new Date(evt.point.x));
// evt.series.values[evt.pointIndex].y = d3.format(',')(evt.point.y);
evt.value = evt.point.x;
evt.series = {
value: evt.point.y,
color: evt.point.color,
key: evt.series.key
};
tooltip
.duration(0)
.valueFormatter(function(d, i) {
return yaxis.tickFormat()(d, i);
})
.data(evt)
.hidden(false);
}
I had added those lines in to fix the hover over labels for the line graph (my line graphs had a datetime x-axis and comma separated integer y-axis). Upon adding those lines it seems the extra processing time required resulted in the lines drawing eratically whenever you toggle a series on/off.
Not too sure what the mechanism is that causes the issue but those lines were the root cause.

Related

D3 multiline chart on update crosses axis

I am trying to plot a multiline d3 chart. I have created a method which should take a new dataset and try to plot it in the same d3 frame for new data update changes (possibly filters).
The first draw works fine but the next draw (mocked data: which is a slice of the previous data and few manipulated values) is not showing correct is crossing the x axis.
[See Image below]
Also the starting origin is missing a tick which should also be 2010 in this example
I also want to create few more lines if there is more datapoints in the future which should be dynamic. Current model is {date, actual, projected}, More expected is mean or difference which will only be shown on trigger.
Any help would be appreciated.
Here is a Stackblitz https://stackblitz.com/edit/angular-rhr39p
References:
Animated line chart: http://bl.ocks.org/atmccann/8966400
Multiline chart: https://bl.ocks.org/larsenmtl/e3b8b7c2ca4787f77d78f58d41c3da91
Dataset updates: https://bl.ocks.org/d3noob/7030f35b72de721622b8
Please keep just one problem per question here at Stack Overflow. This answer will deal with problem #1, consider asking separate questions for the other problems.
The issue here is just your enter/update methodology, that is not correct and. Stick with the idiomatic D3, which is along these lines:
const update = this.svg.selectAll('.records')
.data(records);
const enter = update.enter().append('g')
.attr('class', 'records');
Then, you append new paths using enter and update those paths using update.
You can also ditch the groups and create enter/update/exit selections for the paths directly. That will make your code simpler.
Here is the forked code: https://stackblitz.com/edit/angular-lyd79t?file=src%2Fapp%2Flinechart%2Flinechart.component.ts

nvd3 multibar chart state incorrectly updating on legend toggle?

TL;DR: Try to figure out what state the radio buttons of this nvd3 multibarchart are in based on the console log - i.e. how can I reliably determine what data streams are currently being shown to the user?
Long version:
I'm trying to figure out which data streams/arrays are displaying in an nvd3 multibar chart so that I can update other DOM nodes with information relevant to those streams. The only trouble is that the chart.state seems to be returning the opposite of what it should: if I toggle a stream "off", chart.state.disabled is true for that stream ... except seemingly the first time something is toggled, when all chart.state.disabled[i] streams is set to false... the entire behaviour of that property seems like it isn't functioning as it should to me. Is it a bug or do I not understand how it's supposed to be used?
Some code to log the state of three streams, for example:
chart.legend.dispatch.on("legendClick", function() {
var state = chart.state;
console.log(state.disabled[0] + ","
+ state.disabled[1] + ","
+ state.disabled[2]);
});
Well, as is typical, I dig around for half an hour, can't get it working, post on SO and then go and try a different approach which immediately works:
chart.dispatch.on("stateChange", function(e){
console.log(JSON.stringify(e.disabled);
}
So I believe it's a bug with the ledgendClick event that doesn't update the chart state correctly.

d3.js Update circle on line chart

I'm posting there because I couldn't find something on other post or on google.
http://jsfiddle.net/CUQaN/9/
As you can see on the JS fiddle, I have a line chart with circle on each point.
I want to update this chart with new data. The problem is that I can receive less or more point than I already have on the graph. For example, I can have 8 point on my line chart and then when I'm updating the chart, I can have just 4, or even 15 point. And my circle are not updating properly because I'm just changing the value of the circle which already exist.
But I really don't know how to update them properly.
I can have that data sometimes :
var data = [
{"date":"4-May-12","close":Math.random()*568.13,"open":Math.random()*35.12},
{"date":"3-May-12","close":Math.random()*568.13,"open":Math.random()*35.12},
{"date":"2-May-12","close":Math.random()*568.13,"open":Math.random()*35.12},
{"date":"1-May-12","close":Math.random()*568.13,"open":Math.random()*35.12},
{"date":"30-Apr-12","close":Math.random()*354.98,"open":Math.random()*424.56},
{"date":"27-Apr-12","close":Math.random()*24.00,"open":Math.random()*253.89},
{"date":"26-Apr-12","close":Math.random()*490.70,"open":Math.random()*215.54},
{"date":"25-Apr-12","close":Math.random()*42.00,"open":Math.random()*351.23},
{"date":"24-Apr-12","close":Math.random()*210.28,"open":Math.random()*20.23},
{"date":"23-Apr-12","close":Math.random()*20.70,"open":Math.random()*368.34},
{"date":"20-Apr-12","close":Math.random()*412.98,"open":Math.random()*42},
{"date":"19-Apr-12","close":Math.random()*26.44,"open":Math.random()*20.56},
{"date":"18-Apr-12","close":Math.random()*48.34,"open":Math.random()*356.45},
{"date":"17-Apr-12","close":Math.random()*26.44,"open":Math.random()*20.56},
{"date":"15-Apr-12","close":Math.random()*48.34,"open":Math.random()*356.45},
];
And just that data other times : (more or less)
var data = [
{"date":"4-May-12","close":Math.random()*568.13,"open":Math.random()*35.12},
{"date":"3-May-12","close":Math.random()*568.13,"open":Math.random()*35.12},
{"date":"2-May-12","close":Math.random()*568.13,"open":Math.random()*35.12},
{"date":"1-May-12","close":Math.random()*568.13,"open":Math.random()*35.12},
{"date":"30-Apr-12","close":Math.random()*354.98,"open":Math.random()*424.56},
];
Is someone can help me please ?
Thanks a lot !
It might be better to remove the old points and add the new ones rather than trying to move them. To do this you can use an id function to make the points unique - see here
A small example:
svg.selectAll("circle")
.data(myData, function(d) { return d.x; })
.enter()
.append("circle");
The important part here is that points are identified by their x-value, rather than their index in the data point array. Infact this might help in your current situation as the points will only move up/down and not side to side.

Flot curved lines/Spline plugin which works with FillBetween plugin?

The Flot FillBetween plugin works nicely with line charts. However I need to smooth out the lines and make them more curvy. I have seen the CurvedLined plugin and the Spline plugin but both do not work properly with the fillbetween plugin.
Is there any way to use a two curved line/Spline series and fill the area between them? Something like the image below. Also fills any enclosed area between the two series any time when one crosses the other.
I am unfamiliar with the FillBetween plug-in. I am going to focus on aswering the smoothing part.
I had a similar problem where those smoothing options did not work for me either. I used an external plug-in to make the smoothing. It's name is smooth.js and it worked for me.
Smooth.js recives the data array and returns a function. To get a "smoothed point", apply the function to any value between 0 and the length of the array. The idea is to obtain more points than the original dataset.
For example, to smooth an array of values named test:
//obtaining smoothing function
var s = Smooth(test, {
method: Smooth.METHOD_CUBIC,
});
//obtaining smoothed data
//asking for 10 "smoothed points" per each point in the original dataset
test_smoothed = [];
for (var i = 0; i <= test.length; i = i + .1) {
test_smoothed.push(s(i));
}
I made a JSFiddle with this example.
You can use this plug-in and pass the smoothed data to flot and then use the FillBetween.

Flot charts: How do you alter styling options after the chart's been rendered (e.g. by means of code injection)?

Is it possible to change the styling of a Flot chart's components on the fly – either via the console or a script – after the fact that the chart has been rendered? I.e from somewhere outside the Flot chart's internal configs (which initially defined the styling of the chart).
To put my question into a simple use case: I have a page containing a Flot chart which has the wrong color on the bars. Using Web Inspector's JS console, I want to alter the bars (lines?) color from blue to, say, brown. (And I don't have any means to edit the configs in jquery.flot.js.) Now I wish to inject code from the console, that might change the color of the bars.
I only wish to be hinted of a basic code structure as I'm stuck (nope, I'm not a particularly intermediate or advanced user).
Screenshot 1 – the rendered chart, unaffected (arrow indicates what I want to change):
… Flot's API says:
$.plot(placeholder, data, options)
But I don't want to set/change the data (which has already been plotted out), I just want to change its color representation from blue to, say, brown. The only effect of changing something, that I managed to achieve, was this (terribly clueless) piece of code:
$.plot("#chart", { series: {color: "#6C564C"} });
Which turned the chart into (Screenshot 2):
I don't know why the chart disappeared, and we don't necessarily need to troubleshoot that. All I'm looking for is the simple structure for altering a Flot chart's options by means of code injection.
You can change the colour of an already-drawn series by changing the data object and using setData(). This is faster than calling $.plot() again but it won't recalculate the grid and ticks. If your actual data points don't change, this isn't an issue.
var data = [
{
label: "Your series",
data: rawData,
color: "#f00"
}
]
// Initial draw:
var flotObject = $.plot("#chart", data, options);
// ...
// Change the colour:
data[0].color = "yellow"; // Change only the colour of the original data object
flotObject.setData(data);
flotObject.draw();

Categories