Highstock graph showing data outside selected range - javascript

I have an implementation of a Highstock graph where the chart is narrowed in width in order to fit two of them side by side. A consequence of this seems to be some data bleeding over from the left graph to the right. Even when there is only one graph narrowed in width by itself it seems to still happen.
The data that bleeds over cannot be seen unless you hover over it. The halo and tooltip appear for the data point despite being outside of the selected range in the navigator.
Hovering over a point outside of the graph
JSFiddle: http://jsfiddle.net/7dk6g6rh/
var stockChart = Highcharts.stockChart('container', {
xAxis: {
width: '500',
type: 'datetime'
},
series: [{
data: [1, 2, 3, 4, 5, 3, 4, 6, 3, 8],
pointStart: Date.UTC(2004, 3, 1),
pointInterval: 3600 * 1000
}]
});
stockChart.xAxis[0].setExtremes(1080777600000, 1080806400000);
<div id="container" style="height: 400px; min-width: 600px"></div>
<script src="https://code.highcharts.com/stock/highstock.js"></script>
<script src="https://code.highcharts.com/stock/modules/exporting.js"></script>
<script type="text/javascript" src="https://www.highcharts.com/samples/data/usdeur.js"></script>

I solved this problem by extending Highcharts to behave how I wanted it to. I wrapped the Tooltip, Point, and Axis functions (refresh, setState, and drawCrosshair respectively) to make some checks before proceeding to normal operation.
Here is the JSFiddle with the correct behavior: http://jsfiddle.net/7dk6g6rh/7/
(function (H) {
H.wrap(H.Tooltip.prototype, 'refresh', function(proceed, points) {
for(var i=0; i<points.length; i++) {
if(!points[i].isInside) {
this.hide();
return;
}
}
proceed.apply(this, Array.prototype.slice.call(arguments, 1));
});
H.wrap(H.Point.prototype, 'setState', function(proceed, state) {
if(this.isInside || state !== 'hover') {
proceed.apply(this, Array.prototype.slice.call(arguments, 1));
}
});
H.wrap(H.Axis.prototype, 'drawCrosshair', function(proceed) {
var hoverPoint = this.chart.hoverPoint;
if(hoverPoint && hoverPoint.isInside) {
proceed.apply(this, Array.prototype.slice.call(arguments, 1));
} else {
this.hideCrosshair();
}
});
}(Highcharts));
var stockChart = Highcharts.stockChart('container', {
xAxis: {
width: '500',
type: 'datetime'
},
series: [{
data: [1, 2, 3, 4, 5, 3, 4, 6, 3, 8],
pointStart: Date.UTC(2004, 3, 1),
pointInterval: 3600 * 1000
}]
});
stockChart.xAxis[0].setExtremes(1080777600000, 1080806400000);
<div id="container" style="height: 400px; min-width: 600px"></div>
<script src="https://code.highcharts.com/stock/highstock.js"></script>
<script src="https://code.highcharts.com/stock/modules/exporting.js"></script>
<script type="text/javascript" src="https://www.highcharts.com/samples/data/usdeur.js"></script>

Related

Plotly Hides Markers on Line Chart

I'm trying to create a line chart with markers for about 30 data points using Plotly. For some reason Plotly decides to hide the markers when the data points goes above a certain threshold such as 15. There is no reason to hide them as there is more than adequate space available. See below:
var trace1 = {
x: [1, 2, 3, 4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20],
y: [1, 2, 3, 4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20],
type: 'line',
marker: {
size: 10,
},
};
var data = [trace1];
Plotly.newPlot('myDiv', data);
https://codepen.io/ceds/pen/OJMOjjB
Any idea how to disable this?
I am not getting the exact problem why its not showing when more than 15 data points, But i have a solution using mode: 'lines+markers' property for marker and lines, as below,
var trace1 = {
x: [1, 2, 3, 4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20],
y: [1, 2, 3, 4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20],
type: 'line',
mode: 'lines+markers',
marker: {
size: 10,
},
};
var data = [trace1];
Plotly.newPlot('myDiv', data);
<head>
<!-- Load plotly.js into the DOM -->
<script src='https://cdn.plot.ly/plotly-latest.min.js'></script>
</head>
<body>
<div id='myDiv'><!-- Plotly chart will be drawn inside this DIV --></div>
</body>
Hope this help.

Highcharts multiple series combined with linkedTo hover issue

I'm using linkedTo option to link multiple additional graphs (let's call them childs) to one main graph in order to get one group of graphs.
My issue is about hover highlighting. When I hover main graph all childs are highlighted as well as main graph itself. But when I hover any child graph only this one and main are highlighted, and other childs become blurred, that is not what I want.
Highcharts.chart('container', {
series: [{
id: 'main',
color: 'black',
name: 'Main',
type: 'line',
data: [[1, 3], [1.5, 2.5], [2, 2], [2.5, 1.5], [3, 1]]
}, {
linkedTo: 'main',
color: 'black',
name: 'Child 1',
type: 'line',
data: [[2, 3], [3, 2], [4, 1]]
}, {
linkedTo: 'main',
color: 'black',
name: 'Child 2',
type: 'line',
data: [[3, 3], [4, 2], [5, 1]]
}, {
linkedTo: 'main',
color: 'black',
name: 'Child 3',
type: 'line',
data: [[4, 3], [5, 2], [6, 1]]
}]
});
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/exporting.js"></script>
<div id="container"/>
Is there any workaround for this case?
That issue is reported here: https://github.com/highcharts/highcharts/issues/11810 and marked as an enhancement. Currently, as a workaround you can link sibling series in afterLinkSeries event:
(function(H) {
H.addEvent(H.Chart, 'afterLinkSeries', function(e) {
this.series.forEach(function(s) {
if (s.linkedParent) {
s.linkedParent.linkedSeries.forEach(function(linkedS) {
if (linkedS !== s) {
s.linkedSeries.push(linkedS);
}
});
}
});
});
}(Highcharts));
Live demo: http://jsfiddle.net/BlackLabel/6m4e8x0y/4972/
Docs: https://www.highcharts.com/docs/extending-highcharts/extending-highcharts
EDIT:
Due to the problem with legend item click, a better solution is to overwrite Pointer.prototype.applyInactiveState method.
Highcharts.Pointer.prototype.applyInactiveState = function(points) {
var activeSeries = [],
series;
// Get all active series from the hovered points
(points || []).forEach(function(item) {
series = item.series;
// Include itself
activeSeries.push(series);
// Include parent series
if (series.linkedParent) {
activeSeries.push(series.linkedParent);
// CHANGE
series.linkedParent.linkedSeries.forEach(function(linkedS) {
activeSeries.push(linkedS);
});
// END CHANGE
}
// Include all child series
if (series.linkedSeries) {
activeSeries = activeSeries.concat(series.linkedSeries);
}
// Include navigator series
if (series.navigatorSeries) {
activeSeries.push(series.navigatorSeries);
}
});
// Now loop over all series, filtering out active series
this.chart.series.forEach(function(inactiveSeries) {
if (activeSeries.indexOf(inactiveSeries) === -1) {
// Inactive series
inactiveSeries.setState('inactive', true);
} else if (inactiveSeries.options.inactiveOtherPoints) {
// Active series, but other points should be inactivated
inactiveSeries.setAllPointsToState('inactive');
}
});
};
Live demo: http://jsfiddle.net/BlackLabel/6m4e8x0y/4974/

How to draw a google column chart in angular 6 project?

I'm using angular 6 and I want to draw a column chart of Google. I found below codes from documantation but I don't know how to use it in my app?
html
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<div id="top_x_div" style="width: 800px; height: 600px;"></div>
js
google.charts.load('current', {'packages':['bar']});
google.charts.setOnLoadCallback(drawStuff);
function drawStuff() {
var data = new google.visualization.arrayToDataTable([
['Move', 'Percentage'],
["King's pawn (e4)", 44],
["Queen's pawn (d4)", 31],
["Knight to King 3 (Nf3)", 12],
["Queen's bishop pawn (c4)", 10],
['Other', 3]
]);
var options = {
width: 800,
legend: { position: 'none' },
chart: {
title: 'Chess opening moves',
subtitle: 'popularity by percentage' },
axes: {
x: {
0: { side: 'top', label: 'White to move'} // Top x-axis.
}
},
bar: { groupWidth: "90%" }
};
var chart = new google.charts.Bar(document.getElementById('top_x_div'));
// Convert the Classic options to Material options.
chart.draw(data, google.charts.Bar.convertOptions(options));
};
You need to first declare in your component like this:
declare var google:any;
then your component will know what your are refering to when you call
google.charts.load..
Everything else looks good..

Show a "Bar" for zero results with morris.js

I'm using Morris.js to display data in charts, Id like to show a bar for every option, even if its zero, currently I get this:
As you can see the values for 'HIV Instant' for age group 21-25 and 26-30 are 0, how would I show a line (just a thin one) for each result? is this possible with Morris? I've searched the docs for bar charts & searched google & SO but cant find anything? Any help is appreciated. Cheers
Here is the code for generating said chart:
// break up the object
var age_barParts = [];
$.each( results_by_age_chart, function(key , val){
age_barParts.push({
'test': key,
'u16': val['u16'],
'16-20': val['16-20'],
'21-25': val['21-25'],
'26-30': val['26-30'],
'31-49': val['31-49'],
'50+': val['50+']
});
});
//build the graph
var age_bar = Morris.Bar({
element: 'age_bar',
data: age_barParts,
xkey: ['test'],
ykeys: ['u16', '16-20', '21-25', '26-30', '31-49', '50+'],
labels: ["Under 16s", "16 to 20", "21 to 25", "26 to 30", "31 to 49", "Over 50s"],
barColors: color_array,
hideHover: 'auto',
resize: 'true',
gridTextSize: 16,
gridTextColor: '#5cb85c',
xLabelAngle: '70',
resize: true,
padding: 40
});
In Morris.js there is no option to force drawing of a line for zero values, but you can set them to a very low non-zero value, for example 0.05.
Below an example with Morris:
var age_barParts = [];
age_barParts.push({
'test': 'HIV',
'u16': 3,
'16-20': 5,
'21-25': 1,
'26-30': 2,
'31-49': 8,
'50+': 2
});
age_barParts.push({
'test': 'HIV Instant',
'u16': 1,
'16-20': 4,
'21-25': 0.05,
'26-30': 0.05,
'31-49': 7,
'50+': 3
});
var age_bar = Morris.Bar({
element: 'age_bar',
data: age_barParts,
xkey: ['test'],
ykeys: ['u16', '16-20', '21-25', '26-30', '31-49', '50+'],
labels: ["Under 16s", "16 to 20", "21 to 25", "26 to 30", "31 to 49", "Over 50s"],
hideHover: 'auto',
resize: 'true',
gridTextSize: 16,
gridTextColor: '#5cb85c',
xLabelAngle: '70',
resize: true,
padding: 40
});
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/morris.js/0.5.1/morris.css">
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/raphael/2.1.0/raphael-min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/morris.js/0.5.1/morris.min.js"></script>
<div id="age_bar" style="height: 450px;"></div>
As alternative you can adopt Highcharts which has a specific plotOption.
Below an example with Highcharts:
$(function () {
$('#age_bar').highcharts({
chart: {
type: 'column'
},
title: {
text: 'HIV stats'
},
xAxis: {
categories: ['HIV', 'HIV Instant']
},
yAxis: {
title: {
text: '#'
}
},
plotOptions: {
column: {
minPointLength: 3
}
},
colors: ["#0b62a4","#7a92a3","#4da74d","#afd8f8","#edc240","#cb4b4b","#9440ed"],
series: [{
name: 'u16',
data: [1, 0]
}, {
name: '16-20',
data: [5, 4]
}, {
name: '21-25',
data: [1, 0]
}, {
name: '26-30',
data: [2, 0]
}, {
name: '31-49',
data: [8, 7]
}, {
name: '50+',
data: [2, 3]
}],
});
});
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
<script src="//code.highcharts.com/highcharts.js"></script>
<div id="age_bar" style="height: 450px;"></div>
Update:
Here is a jsfiddle (for Morris) which modifies the hover legend replacing 0.05 with 0. You can improve this approach editing the hoverCallback function:
https://jsfiddle.net/beaver71/zm8wt4pj/
If you compile from coffee script files, just add after lastTop += size in morris.bar.coffee
if size == 0 then size = 1
Otherwise, if you just want to modify the javascript file, just add after lastTop += size; in morris.js
if (size === 0) { size = 1; }

Using different symbols for plotting data not working

I am attempting to use a different symbol for one of my data series on my flot graph as it is at a much larger scale then the rest of the data. I am using this example as reference: http://www.flotcharts.org/flot/examples/symbols/index.html
Here is what I have so far:
My includes:
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="jquery.flot.js"></script>
<script type="text/javascript" src="jquery.flot.symbol.js"></script>
I then configure my flot options like so:
var options = {
grid: {hoverable : true},
xaxis: { mode: "time", timeformat: "%H:%M", tickLength: 1},
series: { points : { show: true } }
};
I then actually plot the data:
$.plot('#placeholder', [{
data: my_data,
lines: { show : true},
points: { symbol: "square"},
color: '#CB4B4B',
label: 'My Data'
}], options);
}
However, flot is still graphing the points as the default circle. I get no error messages in firebug and I have even tried adding a logging message in the jquery.flot.symbol.js library itself to see if the "square" handler is even being called like so:
var handlers = {
square: function (ctx, x, y, radius, shadow) {
console.log("Square handler was called");
// pi * r^2 = (2s)^2 => s = r * sqrt(pi)/2
var size = radius * Math.sqrt(Math.PI) / 2;
ctx.rect(x - size, y - size, size + size, size + size);
},
I am getting no console messages so I am assuming the handler is not getting called correctly. Am I missing something here?
EDIT:
Example of data I am trying to plot:
var d1 = [
[1364342400000, 208],
[1364346000000, 107],
[1364353200000, 42],
[1364371200000, 1680],
[1364360400000, 52],
[1364349600000, 67],
[1364385600000, 1118],
[1364367600000, 163],
[1364382000000, 1359],
[1364378400000, 1468],
[1364389200000, 1023],
[1364356800000, 63],
[1364374800000, 1601],
[1364392800000, 556],
[1364364000000, 84],
],
d2 = [
[1364342400000, 86],
[1364346000000, 42],
[1364353200000, 13],
[1364371200000, 458],
[1364360400000, 10],
[1364349600000, 22],
[1364385600000, 453],
[1364367600000, 45],
[1364382000000, 369],
[1364378400000, 379],
[1364389200000, 358],
[1364356800000, 17],
[1364374800000, 471],
[1364392800000, 147],
[1364364000000, 16],
],
d3 = [
[1364342400000, 7],
[1364346000000, 5],
[1364382000000, 11709],
[1364371200000, 58336],
[1364360400000, 1],
[1364349600000, 1],
[1364367600000, 2],
[1364389200000, 1191],
[1364378400000, 9085],
[1364385600000, 4688],
[1364374800000, 9386],
[1364392800000, 1140],
[1364364000000, 1],
];
I have also edited my options parameter and how the plot function is called:
var options = {
grid: {hoverable : true},
xaxis: { mode: "time", timeformat: "%H:%M", tickLength: 1}
};
$.plot("#placeholder", [{
data: d1,
lines: { show : true },
points: { show: true},
color: '#EDC240',
label: "d1"
}, {
data: d2,
lines: { show : true },
points: { show : true},
color: '#AFD8F8',
label: "d2"
}, {
data: d3,
yaxis: 2,
lines: { show : true},
points: { show: true, symbol: "square"},
color: '#CB4B4B',
label: "d3"
}], options);
I am also sure that the symbol library is being included because I have added some logging itself to the library and that is showing up fine.
I see no issue with what you've done. I made a quick working example here: http://jsfiddle.net/ryleyb/shLtU/1/
I would guess that you haven't included the symbol library (even though you say you have).
Or show your data, might somehow be an issue there (doubtful?).
This is the full flot code I ran to make a working example (plus including flot and the symbol library):
$.plot('#placeholder', [{
data: [
[1, 1],
[2, 3],
[4, 4],
[5, 9]
],
lines: {
show: true
},
points: {
show: true,
symbol: "square"
},
color: '#CB4B4B',
label: 'My Data'
}]);

Categories

Resources