Related
I create a high chart using angular 4 and I want to highlight a particular portion of Highchart.
Ex Image :https://www.screencast.com/t/MHxo59j2dM
As per above image if data point value goes below to some limit (like 0) then highlight with "Red" color and if it goes below 8 then highlight with Yellow
I'm not sure whether its possible with Highchart or not but if someone had created this kind of features then please let me know.
Highchart provides Area Chart option - https://www.highcharts.com/demo/area-negative but my chart is normal and I don't want to highlight all series point.
There's no such functionality in Highcharts, but you can mimic it by using polygon series and plot lines:
var chart = Highcharts.chart('container', {
plotOptions: {
polygon: {
showInLegend: false
}
},
yAxis: {
tickInterval: 1,
plotLines: [{
value: 4,
color: 'orange',
width: 2
}, {
value: 3,
color: 'red',
width: 2
}]
},
series: [{
data: [6, 4, 3, 1, 2, 3, 4, 7]
}, {
type: 'polygon',
data: [[1,4], [2, 4], [2,3]],
color: 'orange'
}, {
type: 'polygon',
data: [[5,4], [6, 4], [5,3]],
color: 'orange'
}, {
type: 'polygon',
data: [[2,3], [5, 3], [4,2], [3,1], [2,3]],
color: 'red'
}]
});
Live working example: http://jsfiddle.net/kkulig/fbomb7cf/
It will require some programming to make the process of creating these areas automatic (in my fiddle everything is hard-coded).
To achieve similar styling you can try patter fill Highcharts plugin: https://www.highcharts.com/blog/extension/pattern-fill/
API references:
http://api.highcharts.com/highcharts/series.polygon
http://api.highcharts.com/highcharts/yAxis.plotLines
The goal
What i need is one Flot chart that contains different coloured bars, with different coloured lines over the top.
Many questions answer how to achieve different coloured bars.
And many pages answer how to add bars AND lines.
But i want to combine these two solutions.
An added bonus would be to be able to add custom parameters to each bar / line (see the "testId" example below) - however this is not necessarily required, as a workaround I could create an object on page load that references each bar's position (e.g. the "ticks" array).
My current workaround
I can already achieve this using multiple data sets as seen in this jFiddle, which i have constructed based off this answer's jFiddle, however this requires multiple different data sets per colour variant of each bar / line like so:
var dataBarsRed = {
data: [
[0, 1],
[2, 1.9],
],
color: 'red'
};
var dataBarsOrange = {
data: [
[1, 2],
[3, 3.9],
],
color: 'orange'
};
var dataBarsGreen = {
data: [
[4, 4],
[5, 4.5]
],
color: 'green'
};
var dataLineRed = {
data: [
[0, 2, 2],
[1, 2, 2],
[2, 2, 2],
[3, 2, 2],
[4, 2, 2],
[5, 2, 2],
],
label: '60% efficiency',
color: 'red',
bars: {
barWidth: 1
}
};
var dataLineOrange = {
data: [
[0, 4, 4],
[1, 4, 4],
[2, 4, 4],
[3, 4, 4],
[4, 4, 4],
[5, 4, 4],
],
label: '85% efficency',
color: 'orange',
bars: {
barWidth: 1
}
};
And add them like so:
$.plot("#placeholder", [dataBarsRed, dataBarsOrange, dataBarsGreen, dataLineRed, dataLineOrange],...
From what i can tell, there is no way to add any custom data parameters to this data structure, in which each item has it's own set of custom variables (e.g. object id's to link to the back-end, like "testId" - see "The Rationale").
The rationale
Is there a way to achieve what i need using the same structure for the bar data as the first link:
var data = [
{ data: [[0,1]], color: "red", testId: 30 },
{ data: [[1,2]], color: "yellow", testId: 31 },
{ data: [[2,3]], color: "green", testId: 32 }
];
The reason i'd like to do it this way is that it would be much simpler to build the Flot Data Object on the Java side (return it as JSON from ajax) but also it has the added benefit of adding your own parameters to each bar / line (e.g. "testId" shown above. The id's themselves would be utilised to retrieve more data via ajax on click or hover of the bar.
For Example:
$(container).bind('plothover', function(event, position, item){
console.log(item.series.testId)
});
Final thoughts
I feel like i'm going round in circles with this. I love the Flot charts plugin and it's flexibility, but there are numerous ways to implement the same visual outcome.
Thanks.
- Steve.
The Solution
See this jFiddle for the complete code.
After considering what Raidri is saying regarding it's simplicity, I've taken another stab at it and I've gotten something working as i need it to, with a bit more consistency. I feel a bit silly for not seeing this before (perhaps i did and a syntax error caused me to move on). Anyway, if anyone is interested here's the code:
NOTE: This does feel like a bodge or a hack - i'm not sure if this kind of data structure was ever intended, but it gets the job done for my purposes.
var data = [
{ data: [[0,1]], color: "red", testId: 30, isBar: true },
{ data: [[1,2]], color: "orange", testId: 31, isBar: true },
{ data: [[2,1.9]], color: "red", testId: 32, isBar: true },
{ data: [[3,3.9]], color: "orange", testId: 33, isBar: true },
{ data: [[4,4]], color: "green", testId: 34, isBar: true },
{ data: [[5,4.5]], color: "green", testId: 35, isBar: true },
{ data: [[0, 4, 4],[0.5, 4, 4],[1, 4, 4],[1.5, 4, 4],[2, 4, 4],[2.5, 4, 4],[3, 4, 4],[3.5, 4, 4],[4, 4, 4],[4.5, 4, 4],[5, 4, 4]], shadowSize: 0, color: 'orange', isLine: true, label: '85% efficiency' },
{ data: [[0, 2, 2],[0.5, 2, 2],[1, 2, 2],[1.5, 2, 2],[2, 2, 2],[2.5, 2, 2],[3, 2, 2],[3.5, 2, 2],[4, 2, 2],[4.5, 2, 2],[5, 2, 2]], shadowSize: 0, color: 'red', isLine: true, label: '60% efficiency' },
{ data: [[0, -1, -1]], shadowSize: 0, color: 'green', label: '100% efficiency', isLine: true }
];
var plot = $.plot("#placeholder", data, {
bars: {
show: true,
align: 'center',
barWidth: 0.5
},
lines: {
show: true,
lineWidth: 0.1,
fill: false
},
grid: {
hoverable: true,
autoHighlight: true
},
xaxis: {
ticks: [[0,'Steve'],[1,'Bob'],[2,'Chris'],[3,'Joe'],[4,'Dave'], [5, 'Jon']]
},
yaxis: {
min: 0,
max: 5
},
legend:{
container: '#legend'
}
});
There are some slight nuances, such as the number of line points (data elements per line) need to take into account the bar width. E.g. if my bar width was 1 i'd only need 5 elements, but since i have a width of 0.5 i need 10 line elements per data array (to fill in the gaps). Also, "shadowSize: 0" is required or you'd get a grey shadow in the middle of the line.
I've also added "isBar" and "isLine" to each element so my hover event can distinguish between them so it does not update the info box when the line is hovered. This is because the way I've done this is a bit of a "hack" in the sense that the line is not one line, but a line per column. Without this further distinction of type, hovering over the line would display the bar's name depending on your mouse's x-position.
I've also had to add a "fake" green line for the legend - position 0, referencing start and end positions that are outside the axis range (-1, in this example, 6 would also work). I realise i can probably create a custom legend...but it was simpler to just let flot deal with it itself.
You can simply combine your five data objects into one array of objects und you can also add your own properties to these objects, like this:
var data = [ {
data: [
[0, 1],
[2, 1.9],
],
color: 'red',
testId: 31
}, {
data: [
[1, 2],
[3, 3.9],
],
color: 'orange',
testId: 32
}, {
//...
}];
And using your own properties for example in the hover-event is as simple as
$('#details').html("<span class='detail'>...(testId = " + item.series.testId + ")</span>");
See the updated fiddle for the full example.
PS: For the lines in your chart, maybe markings are a better fit (see the documentation and this fiddle, where one of the lines is replaced by a marking).
$(function () {
$('#container').highcharts({
chart: {
type: 'line'
},
title: {
text: 'Test Progress'
},
xAxis: {
title: {
text: 'Date'
},
type: "datetime"
},
yAxis: {
title: {
text: 'Grade'
}
},
credits: { enabled: false },
series: [{
data: [[1331028000000, 5], [1331031600000, 6], [1331035200000, 4]]
}]
});
});
By following this thread, http://stackoverflow.com/questions/9548326/what-format-does-the-highcharts-js-library-accept-for-dates
it says that i can input the dates in the above way inside data but it shows time instead of date.
Also i tried the first method and still gives me time. How can i display dates?
Also i am trying to get the dates from records and display them there, in what format do i need to convert them to properly show them?
For those wondering here is the query i have come up with
Test.where("user_id = ?", 25).order('created_at DESC').select(:grade,:created_at).map { |g| [ g.created_at.to_i * 1000, g.grade.to_i ] }.inspect
i wrapped this query in a method and called the method in view
series: [{
data: <%= grades %>
}]
this creates this line of code
data: [[1454777030000, 25], [1454598308000, 50], [1454598191000, 75], [1454163373000, 100], [1454163332000, 100], [1454163177000, 100], [1454163000000, 0], [1454096412000, 50], [1454096220000, 50], [1454095875000, 0], [1454095853000, 50], [1454082249000, 22], [1454081128000, 100], [1453037445000, 100]]
which seems to work with highcharts
I am using highstock to show two dimension data of multi series on a chart. But highstock shift bars of series and don't show on one trick!
I used this code:
workData = [
/* 2009-01-01 */
[1262048400000, 6, 10],
[1262134800000, 7.75, 12],
[1262221200000, 7, 16]
];
freeData = [
[1262048400000, 10, 12],
[1262134800000, 13, 16]
];
missionData = [
[1262134800000, 12, 13]
];
$(function() {
$('#container').highcharts('StockChart', {
chart: {
type: 'columnrange'
},
xAxis: {
minTickInterval: 24*3600*1000
},
series: [{
name: 'Work',
data: workData ,
color: 'green'
}, {
name: 'Free',
data: freeData,
color:'blue'
}, {
name: 'Mission',
data: missionData ,
color: 'red'
}]
});
});
in above code I have 3 series whit two dimension data.
You can set grouping: false for series, take a look: http://jsfiddle.net/E83Ef/1/
I am hoping someone out there can tell me if what I am trying to do is even possible with the FLOT Javascript library. I am trying to show a chart (below) with dual axis and three data sets. One data set is on the left axis and two data sets on the right axis. What I really want to be able to do is stack the two data sets on the right axis since they should show cumulatively. Thus far I have been unable to get this chart to respond to the stack: true setting at all.
If anyone could help me out with it I would GREATLY appreciate it. My code and a snapshot of the chart currently. I am trying to stack the blue and green areas which correspond to the right axis (y2).
$(function () {
var previousPoint;
var completes = [[1346954400000, 5], [1346997600000, 5], [1347040800000, 7], [1347084000000, 9], [1347127200000, 12], [1347170400000, 15], [1347213600000, 16], [1347256800000, 20], [1347300000000, 20], [1347343200000, 20], [1347386400000, 25]];
var holds = [[1346954400000, 2], [1346997600000, 2], [1347040800000, 6], [1347084000000, 12], [1347127200000, 12], [1347170400000, 15], [1347213600000, 24], [1347256800000, 24], [1347300000000, 24], [1347343200000, 24], [1347386400000, 25]];
var screeners = [[1346954400000, 10298], [1346997600000, 7624], [1347040800000, 5499], [1347084000000, 2100], [1347127200000, 8075], [1347170400000, 4298], [1347213600000, 1134], [1347256800000, 507], [1347300000000, 0], [1347343200000, 800], [1347386400000, 120]];
var ds = new Array();
ds.push({
data:completes,
label: "Complete",
yaxis: 2,
lines: {
show: true,
fill: true,
order: 2,
}
});
ds.push({
data:screeners,
label: "Pre-Screened",
yaxis: 1,
lines: {
show: true,
fill: true,
order: 1,
}
});
ds.push({
data:holds,
label: "Holds",
yaxis: 2,
lines: {
show: true,
fill: true,
order: 3,
}
});
//tooltip function
function showTooltip(x, y, contents, areAbsoluteXY) {
var rootElt = 'body';
$('<div id="tooltip2" class="tooltip">' + contents + '</div>').css( {
position: 'absolute',
display: 'none',
top: y - 35,
left: x - 5,
border: '1px solid #000',
padding: '1px 5px',
'z-index': '9999',
'background-color': '#202020',
'color': '#fff',
'font-size': '11px',
opacity: 0.8
}).prependTo(rootElt).show();
}
//Display graph
$.plot($("#placeholder1"), ds, {
grid:{
hoverable:true
},
xaxes: [ { mode: 'time', twelveHourClock: true, timeformat: "%m/%d %H:%M" } ],
yaxes: [ { min: 0,
tickFormatter: function numberWithCommas(x)
{
return x.toString().replace(/\B(?=(?:\d{3})+(?!\d))/g, ",");
},
}
],
y2axis: [ ],
legend: { show: true }
});
});
This is very straightforward. The stacking plugin isn't well documented, but in the source code, you can see there are two ways to specify that you want stacking turned on.
Two or more series are stacked when their "stack" attribute is set to
the same key (which can be any number or string or just "true"). To
specify the default stack, you can set
series: {
stack: null or true or key (number/string) }
or specify it for a specific series
$.plot($("#placeholder"), [{ data: [ ... ], stack: true }])
In this case, we want to specify it within the two series objects that we want stacked, which would look like this:
ds.push({
data:completes,
label: "Complete",
yaxis: 2,
stack: true, //added
lines: {
show: true,
fill: true,
order: 2,
}
});
ds.push({
data:screeners,
label: "Pre-Screened",
yaxis: 1,
lines: {
show: true,
fill: true,
order: 1,
}
});
ds.push({
data:holds,
label: "Holds",
yaxis: 2,
stack: true, //added
lines: {
show: true,
fill: true,
order: 3,
}
});
Add those two stack:true bits and include the stack plugin into your javascript sources and that will do it. See it in action here: http://jsfiddle.net/ryleyb/zNXBd/