When I zooming first time when graph is loaded, data is missing in angular dygraph. Here are screenshots
after zooming
Here is my code
function getPopUpGraph() {
$scope.currentZoom = 1;
$scope.popUpGraph = {};
$scope.popUpGraph = {
data: [],
options: {
labels: ["Date", $scope.selectedDataPoint.LegendName, "TrendLine"],
showPopover: false,
//customBars: true,
legend: "onmouseover",
highlightSeriesOpts: {
strokeWidth: 2,
strokeBorderWidth: 1
},
animatedZooms: true,
interactionModel: Dygraph.defaultInteractionModel,
showRangeSelector: true,
rangeSelectorPlotLineWidth: 1,
rangeSelectorPlotStrokeColor: 'gray',
rangeSelectorPlotFillColor: 'gray',
highlightCircleSize: 4,
rangeSelectorAlpha: 0.9,
rangeSelectorForegroundLineWidth: 1.25,
rangeSelectorForegroundStrokeColor: 'dark gray',
visibility: [true, false],
series: {
'TrendLine': {
strokePattern: [3, 2, 3, 2]
},
},
//xlabel: 'Date',
ylabel: $scope.selectedDataPoint.Unit,
title: $scope.selectedDataPoint.LegendName,
legendEnabled: false,
colors: ["#ff0000"],
valueRange: null,
height: 300,
resizeEnabled: true,
strokeWidth: 2,
axes: {
x: {
axisLabelFormatter: function (d, gran) {
if ($scope.currentZoomLevel.name == '12h') {
return $filter('date')(d, 'h:mm a');
}
else
return $filter('date')(d, 'MMM dd h:mm');
},
valueFormatter: function (ms) {
return $filter('date')(ms, 'M/d/yy h:mm a');
}
}
},
drawCallback: function (g, is_initial) {
if (g.dateWindow_)
myPopUpRange(g.dateWindow_)
}
}
}
$scope.getPopGraphData($scope.currentZoom, 0);
}
Data is fetching from $scope.getPopGraphData function.
Iam calling some other functions in this main function. I think this is not a problem. In angular dygraph's demo , after zooming , range selector also changing. So data is showing correctly. In my case range selector is not changing on first time zooming.
Any solution? Thanks in advance...
I found the solution. In getPopUpGraph() function , there is a drawback function is calling. On disable the myPopUpRange() function, it is now working properly. myPopUpRange() is used for resetting the x axis value. But there is no need, as dygraph automatically assign the x axis range.
Related
please take a look at this jsfiddle first
jsfiddle example of sparkline
Highcharts.SparkLine = function (a, b, c) {
var hasRenderToArg = typeof a === 'string' || a.nodeName,
options = arguments[hasRenderToArg ? 1 : 0],
defaultOptions = {
chart: {
renderTo: (options.chart && options.chart.renderTo) || this,
backgroundColor: null,
borderWidth: 0,
type: 'area',
margin: [2, 0, 2, 0],
width: 120,
height: 20,
style: {
overflow: 'visible'
},
// small optimalization, saves 1-2 ms each sparkline
skipClone: true
},
title: {
text: ''
},
credits: {
enabled: false
},
xAxis: {
labels: {
enabled: false
},
title: {
text: null
},
startOnTick: false,
endOnTick: false,
tickPositions: []
},
yAxis: {
endOnTick: false,
startOnTick: false,
labels: {
enabled: false
},
title: {
text: null
},
tickPositions: [0]
},
legend: {
enabled: false
},
tooltip: {
hideDelay: 0,
outside: true,
shared: true
},
plotOptions: {
series: {
animation: false,
lineWidth: 1,
shadow: false,
states: {
hover: {
lineWidth: 1
}
},
marker: {
radius: 1,
states: {
hover: {
radius: 2
}
}
},
fillOpacity: 0.25
},
column: {
negativeColor: '#910000',
borderColor: 'silver'
}
}
};
options = Highcharts.merge(defaultOptions, options);
return hasRenderToArg ?
new Highcharts.Chart(a, options, c) :
new Highcharts.Chart(options, b);
};
i try to use the concept of having those sparkline between table tags and achieve a chart with more than 2 column on left and right , however instead of sparkline i need bar chart like a picture below
please help me on this problem ...
Update :
thanks to ppotaczek and his suggestion on changing to bar type i had another problem on the way
updated jsfiddle with bar type
well now i don't know how to make every row to adopt xrow size of 115 . at this moment all bar chart draw the entire cell but 20 from 115 must have different view via 71 from 115 ...
any suggestion to how to put 0 to 115 on the top of the table and adjust the bar charts with that ?
You need to change chart.type to 'bar' and adapt data in the HTML table.
chart: {
type: 'bar',
...
}
Live demo: https://jsfiddle.net/BlackLabel/cyuvws37/
API Reference: https://api.highcharts.com/highcharts/chart.type
We use the bar chart capabilities of c3 charts library in an environment where live data is floating in. This did lead to a problem where if a user hovers over a bar the bar itself did update but not the tooltip that was shown. Is there a way to update/reload the tooltip?
#Update 1:
Sorry for the delayed response. Basically we have an observer listening for data changes. This will trigger a method called reload which has the following lines (how the data looks like is shown in the comments):
chart.load({
xs: xs, // AmberViolation:"facilityId",BlueViolation:"facilityId",RedViolation:"facilityId"
columns: columns, // [["facilityId", "SUB-GTW"],["RedViolation", 0],["BlueViolation", 2],["AmberViolation", 0]]
unload: _.difference(drawnChartYCols, nextDrawColumns),
types: types, // AmberViolation:"bar",BlueViolation:"bar",RedViolation:"bar"
colors: colors,
done: function () {
if (columns.length && columns[0].length > 10) {
chart.zoom([0, 11]);
d3.select(element[0]).selectAll('svg > g').filter(function(d, i) { return i === 1 }).attr('display', null);
chart.resize({width: $scope.width, height: $scope.height});
d3.select(element[0]).select('.extent').attr('x', 0);
} else {
chart.unzoom();
d3.select(element[0]).selectAll('svg > g').filter(function(d, i) { return i === 1 }).attr('display', 'none');
chart.resize({width: $scope.width, height: $scope.height + 70});
}
}
});
chart.groups([groups]);// ["RedViolation","BlueViolation","AmberViolation"]
#Update 2:
You can even see that behavior on http://c3js.org/samples/chart_bar_stacked.html. Just hover over one of the bars while data is being updated and let the mouse stay there. The tooltip will not update. Only if you move the mouse again it will refresh.
#Update 3: Since this happens even on examples of c3 charts I created a bug on Github: https://github.com/c3js/c3/issues/2307
You don't provide any code snippet so it's hard to answer. I guess you don't update your data properly. According to the documentation:
If you call load API soon after/before unload, unload param of load
should be used. Otherwise chart will not be rendered properly because
of cancel of animation.
Something like this, to unload the old values, could solve your problem:
chart.load({
unload: true,
columns: ['data1', 100]
});
Check out this previous answer on SO.
My current solution is to hide and show the tooltip once the data gets updated in order to refresh it. Its ugly since the user can see the position of the tooltip jumping.
var currentIndex = null;
var chart = c3.generate({
data: {
columns: [
['data1', 20],
['data2', 30],
['data3', 40]
],
type: 'bar',
groups: [
['data1', 'data2', 'data3']
],
onmouseover: function(e) {
currentIndex = e.index;
},
onmouseout: function(e) {
currentIndex = null;
}
},
axis: {
y: {
show: true,
},
x: {
show: true,
type: ({
NUMERIC: 'indexed',
TEXT: 'category',
DATE: 'timeseries'
})['TEXT']
}
},
bar: {
width: {
ratio: 0.9,
max: 100
}
},
padding: {
top: 25,
right: 25
},
zoom: {enabled: false},
subchart: {
show: true,
axis: {
x: {
show: false
}
}
},
legend: {
show: false
},
line: {
connectNull: true
},
transition: {
duration: null
},
grid: {
y: {
show: true
}
}
});
setTimeout(function () {
chart.load({
columns: [['data1', 30],
['data2', 10],
['data3', 10]]
});
if (currentIndex != null) {
chart.tooltip.hide();
chart.tooltip.show({x: currentIndex});
}
}, 3000);
<link href="https://rawgit.com/masayuki0812/c3/master/c3.css" rel="stylesheet"/>
<script src="https://rawgit.com/masayuki0812/c3/master/c3.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div id="chart"></div>
I added a hover listener where I get the currentHoverIndex and a onmouseout listener to set currentHoverIndex to null so we don't accidently show a tooltip if user doesn't hover on a bar at that time.
I'm using this data:
{
label: 'Payments',
// data: this.getFlotPaymentData(),
data: [
[Moment().subtract(6, 'days').valueOf(), 0],
[Moment().subtract(5, 'days').valueOf(), 0],
[Moment().subtract(4, 'days').valueOf(), 0],
[Moment().subtract(3, 'days').valueOf(), 0],
[Moment().subtract(2, 'days').valueOf(), 168.50],
[Moment().subtract(1, 'days').valueOf(), 200.00],
[Moment().valueOf(), 200.00]
],
last: false
}
and for some reason, my graph goes into negative values. I'm expecting it to be zero until 2 days ago then suddenly jump to 168.50.
I don't want to set the min value of the graph to 0 because I have another data set being introduced which goes into negative values (expenses).
It's producing this:
I'm initialising flot like so:
// Chart options
var chart = $('#flot-visitors')
var labelColor = chart.css('color')
var options = {
colors: chart.data('color').split(','),
series: {
shadowSize: 0,
lines: {
show: true,
lineWidth: false,
fill: true
},
curvedLines: {
apply: true,
active: true,
monotonicFit: false
}
},
legend: {
container: $('#flot-visitors-legend')
},
xaxis: {
mode: 'time',
timeformat: '%d %b',
font: {color: labelColor}
},
yaxis: {
font: {color: labelColor}
},
grid: {
borderWidth: 0,
color: labelColor,
hoverable: true
}
}
chart.width('100%')
// Create chart
$.plot(chart, data, options)
According to Documentation, you could set
monotonicFit: true
parameter type effect
------------ ---- -----------------------------------------------------------------
monotonicFit bool true => uses monotone cubic interpolation (preserve monotonicity)
I'm rewriting a site that I made purely in PHP to a straight Javascript implementation. I moved all of my dygraphs code over, and the graph doesn't seem to show the value that you're hovering on anymore. The only thing that I can think of that is different, is that in the previous version, I used a PHP array, made a string out of it, and echo'ed it into a tag within my dygraph data declaration. In the new version, I'm using a native array call for the data. Might the formatters be screwing up here? The graph itself shows up, so it seems like the data is working.
I also noticed that the dygraphs Titles and Axes labels aren't showing up in the new one, despite the same code.
Old implementation:
g = new Dygraph(
document.getElementById("graphdiv"),
[[],[],[]....], //The whole array declaration couldn't be pasted here. Too big.
{
labels: labels.slice(),
title: 'cFIREsim Simulation Cycles',
ylabel: 'Portfolio ($)',
xlabel: 'Year',
labelsDivStyles: { 'textAlign': 'right' },
labelsDivWidth: 500,
labelsDiv: 'labelsdiv',
digitsAfterDecimal: 0,
yAxisLabelWidth: 100,
axes: {
y: {
labelsKMB: false,
maxNumberWidth: 11,
valueFormatter: function numberWithCommas(x) {
return 'Portfolio: $' + x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
},
axisLabelFormatter: function numberWithCommas(x) {
return '$' + x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
},
x: {
valueFormatter: function numberWithCommas(x) {
return 'Selected Year: ' + x;
},
},
},
showLabelsOnHighlight: true,
highlightCircleSize: 3,
strokeWidth: 1.5,
strokeBorderWidth: 0,
highlightSeriesBackgroundAlpha: 1.0,
highlightSeriesOpts: {
strokeWidth: 4,
strokeBorderWidth: 2,
highlightCircleSize: 5,
},
}
);
New Implementation:
Simulation.g.push(new Dygraph(
// containing div
document.getElementById("graph" + Simulation.tabs), //graph div has dynamic name for multiple graphs.
chartData, {
labels: labels.slice(),
title: 'cFIREsim Simulation Cycles',
ylabel: 'Portfolio ($)',
xlabel: 'Year',
labelsDivStyles: {
'textAlign': 'right'
},
labelsDivWidth: 500,
labelsDiv: 'labels' + this.tabs, //same dynamic names as graphdiv
digitsAfterDecimal: 0,
axes: {
y: {
axisLabelWidth: 100,
labelsKMB: false,
maxNumberWidth: 11,
valueFormatter: function numberWithCommas(x) {
return 'Spending: $' + x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
},
axisLabelFormatter: function numberWithCommas(x) {
return '$' + x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
},
x: {
valueFormatter: function numberWithCommas(x) {
return 'Year: ' + x;
},
},
},
showLabelsOnHighlight: true,
highlightCircleSize: 3,
strokeWidth: 1.5,
strokeBorderWidth: 0,
highlightSeriesBackgroundAlpha: 1.0,
highlightSeriesOpts: {
strokeWidth: 4,
strokeBorderWidth: 2,
highlightCircleSize: 5,
},
}
));
This ended up being a silly CSS issue. The labels div needed a CSS class so that I could actually SEE the labels on my black background.
.labels { color: black; }
I a trying to plot some information using a flot graph but I can not get the values to appear on the graph. This code was part of a demo file included in a template and so i have modified it to plot the data rather than using a randomise for the values, i am getting no errors but the chart isn't working and was hoping somebody could point me in the right direction.
My code is here:
init: function()
{
// apply styling
charts.utility.applyStyle(this);
this.plot = $.plot(
$("#chart_simple"),
[{
label: "Jobs",
data: this.data.d1,
lines: {fillColor: "#dd3333"},
points: {fillColor: "#dd3333"}
},
{
label: "Resumes",
data: this.data.d2,
lines: {fillColor: "#282b30"},
points: {fillColor: "#282b30"}
}], this.options);
}
},
// lines chart with fill & without points
chart_lines_fill_nopoints:
{
// chart data
data:
{
d1: [[1,100], [2,150], [3,100]],
d2: [[1,100], [2,150], [3,100]]
},
// will hold the chart object
plot: null,
// chart options
options:
{
grid: {
show: true,
aboveData: true,
color: "#3f3f3f",
labelMargin: 5,
axisMargin: 0,
borderWidth: 0,
borderColor:null,
minBorderMargin: 5 ,
clickable: true,
hoverable: true,
autoHighlight: true,
mouseActiveRadius: 20,
backgroundColor : { }
},
series: {
grow: {active:false},
lines: {
show: true,
fill: true,
lineWidth: 2,
steps: false
},
points: {show:false}
},
legend: { position: "nw" },
yaxis: { min: 0 },
xaxis: {ticks:11, tickDecimals: 0},
colors: [],
shadowSize:1,
tooltip: true,
tooltipOpts: {
content: "%s : %y.0",
shifts: {
x: -30,
y: -50
},
defaultTheme: false
}
},
So, digging a bit, I see you are using javascript from here. Looking at a working example here, you've broken their code in the following ways:
1.) You no longer seem to have a parent charts object, so
charts.utility.applyStyle(this);
isn't going to work.
2.) The init function is part of the chart_lines_fill_nopoints object, in your cut/paste code it isn't anymore.
3.) In your sample code you never actually call the init function to draw the plot.
4.) In the options backgroundColor : { } is invalid for flot (maybe this is part of the missing charts.utility.applyStyle).
Taking all this into account here's a fiddle which makes this code work.
Generating flot plots with the above code feels unnecessarily convoluted. Perhaps it makes sense when using these templates, but if you just using this as an example of how to call flot it's not very straightforward.
Also, please next time you post a question, include all relevant information (like where you found this code and how you changed it). Taken out of context this code makes little sense.
This code is working
//Defining data for the chart
var data=
{
d1: [[1,100], [2,150], [3,100]],
d2: [[1,100], [2,150], [3,100]]
};
//Defining options for the chart
var options=
{
grid: {
show: true,
aboveData: true,
color: "#3f3f3f",
labelMargin: 5,
axisMargin: 0,
borderWidth: 0,
borderColor:null,
minBorderMargin: 5 ,
clickable: true,
hoverable: true,
autoHighlight: true,
mouseActiveRadius: 20,
backgroundColor : { }
},
series: {
grow: {active:false},
lines: {
show: true,
fill: true,
lineWidth: 2,
steps: false
},
points: {show:false}
},
legend: { position: "nw" },
yaxis: { min: 0 },
xaxis: {ticks:11, tickDecimals: 0},
colors: [],
shadowSize:1,
tooltip: true,
tooltipOpts: {
content: "%s : %y.0",
shifts: {
x: -30,
y: -50
},
defaultTheme: false
}};
// shorthand for document.ready
$(function(){
this.plot = $.plot(
$("#chart_simple"),
[{
label: "Jobs",
data: data.d1,
lines: {fillColor: "#dd3333"},
points: {fillColor: "#dd3333"}
},
{
label: "Resumes",
data: data.d2,
lines: {fillColor: "#282b30"},
points: {fillColor: "#282b30"}
}], this.options);
});
Check out the working example here on jsfiddle.