Scenario:
I am able to get a status graph with Zingchart, using a stacked hbar and plotting data intervals where the status of an element doesn't change:
However, I would like to have more resolution in the axis that provides the time.
Problem:
I am not able to increase the number of ticks in the y-axis (this is an stacked hbar graph, so the usual x-axis is actually the y-axis).
If I introduce step:"1hour", in the scaleY field I get back to epoch 0 and this is what I obtain:
Question:
What am I doing wrong? I would like either:
To have more time references in the axis of the time.
Or (and this may be another question) to be able to know on mouse over (in the tooltip?) at what time I am. Since I am plotting time increments I lost the actual time on where the change of status happens. Is there a direct way to do this in this particular situation? Or do I have to carry another data-customValue for the actual date of the start / end of the interval?
In the code, I jump from epoch 0 to the time I start having data, and define minValue to plot as the first epoch I have data minus one second.
This is the working code (no step attribute defined):
<!DOCTYPE html>
<html>
<head>
<script src="/home/eballes/Work/backup/zingchart_test/zingchart_2.3.3/zingchart.min.js"></script>
<script>
zingchart.MODULESDIR = "/home/eballes/Work/backup/zingchart_test/zingchart_2.3.3/modules/";
</script>
<style></style>
</head>
<body>
<div id='myChart'></div>
<script>
var myConfig = {
type: "hbar",
utc:true,
title: {
text: 'Status'
},
scaleY:{
transform:{
type:'date',
all:"%d/%M/%Y\n%H:%i:%s",
},
minValue:1456693864000,
zooming:true,
label:{
"text": "Time",
},
tick:{
"line-color":"black",
"line-width":"2px",
"size":8,
},
maxItems:10,
itemsOverlap:true,
item:{
"font-size":10
},
},
scaleX:{
label:{
"text": "Item",
},
},
plot:{
stacked:true,
exact:false,
barWidth:10,
rules:[
{
rule:'%data-customValue == 0',
alpha:0, // Transparent
},
{
rule:'%data-customValue == 1',
backgroundColor:'#0000FF' // Dark Blue
},
{
rule:'%data-customValue == 2',
backgroundColor:'#00FFFF' // Light Blue
},
{
rule:'%data-customValue == 3',
backgroundColor:'#FF7F50' // Orange
},
{
rule:'%data-customValue == 4',
backgroundColor:'#FFFF00' // Yellow
},
{
rule:'%data-customValue == 5',
backgroundColor:'#EE82EE' // Purple
},
{
rule:'%data-customValue == 6',
backgroundColor:'#00FF00' // Green
},
{
rule:'%data-customValue == 7',
backgroundColor:'#FF0000' // Red
},
]
},
tooltip:{
jsRule:"CustomFn.formatTooltip()",
},
series : [
{
values : [
[1,1456693864000],
[2,1456693864000],
.... // From 1 to 36
[36,1456693864000],
],
'data-customValue':[0,0,0,0,0,0,
0,0,0,0,0,0,
0,0,0,0,0,0,
0,0,0,0,0,0,
0,0,0,0,0,0,
0,0,0,0,0,0],
},
{
values : [
[11, 32000], [12, 10270000], [14, 5033000], [18, 79000], [20, 43000], [24, 76000], [26, 4043000], [8, 33000], [9, 63000],
],
'data-customValue':[2, 6, 6, 0, 1, 2, 6, 1, 0, ],
},
{
values : [
[14, 3000], [19, 20000], [26, 1000], [8, 86000], [9, 13000],
],
'data-customValue':[2, 2, 2, 0, 1, ],
},
// All intervals
]
};
CustomFn = {};
CustomFn.formatTooltip = function(p){
var hours = Math.floor(p.value / 3600000);
var minutes = Math.floor((p.value % 3600000) / 60000);
var seconds = (p.value % 60000)/1000;
var tooltipText = "Item: " + p.scaletext + "\nDuration: ";
var hoursText = (hours == 0) ? "" : (hours + "h ");
var minutesText = (minutes == 0) ? "" : (minutes + "m");
var secondsText = (seconds == 0) ? "" : (seconds + "s");
tooltipText = tooltipText + hoursText + minutesText + secondsText + "\n";
tooltipText = tooltipText + "Value: " + p['data-customValue'];
var alpha = 70;
// We don't want any tooltip for the time-jump
if (hours > 300000) {
tooltipText = "";
alpha = 0;
}
return {
text : tooltipText,
backgroundColor : "#222",
alpha: alpha,
}
};
zingchart.render({
id : 'myChart',
data : myConfig,
height: 670,
width: '100%'
});
</script>
</body>
</html>
This is the link to the Plunker with the whole example, not working. If you remove the line step:"1hour", it will work.
Funny enough, step:20 works fine. But I would prefer to have my steps in a normal way, like hourly.
Note: Just to provide some more context, this question is the continuation of this other previous question.
Full Disclosure, I'm a member of the ZingChart team.
The first problem being
step:'1hour'
That string value is being interpreted by our library as the value 0. This is because the string '1hour' does not match any of our keywords nor does it evaluate to a Number type. We are not simply using parseInt so it does not evaluate to 1.
If you want an hourly step you would do the step count in milliseconds. This is documented in our scales page.
step:3600000
For display the scale value we do have a tokens list which allows you to add values from your scale to your tooltip. In your customFn.formatTooltip you would add this line.
...
tooltipText = tooltipText + "Value: " + p['data-customValue'];
tooltipText += '<br> %vv'
The %vv is in our tokens list and will grab the transformed value off the y-axis. If you did %vt it would give you the millisecond value.
I have a jqplot chart that has two lines. I'm using tooltipContentEditor to modify the text displayed in the tooltip. Prior to adding the second line, the tooltips displayed the values fine. Now that I have added another line, the tooltips always show the data for the second line (thus incorrectly for the first). How do I have the correct values displayed?
Blue line tooltip shows yellow line value:
Chart initialization (tooltipContentEditor function inside):
$.jqplot('mychart', [coords, paidCoords], {
//title:'Sales for ' + name,
animate: !$.jqplot.use_excanvas,
axesDefaults: {
tickRenderer: $.jqplot.CanvasAxisTickRenderer ,
},
axes:{
xaxis:{
renderer:$.jqplot.DateAxisRenderer,
tickInterval: tickInterval,
tickOptions: { formatString: formatString, angle: -30 }
},
yaxis:{
min:0
}
},
highlighter: {
show: true,
sizeAdjust: 7.5,
tooltipContentEditor: function(str, pointIndex, index, plot){
console.log('logging in tooltipeditor');
console.log(str);
console.log(pointIndex);
console.log(index);
console.log(plot);
var splitted = plot._plotData[1][index];
var x = splitted[0];
var y = splitted[1];
x = new Date(x);
x = x.toString();
return x + "<br/>$" + y;
}
},
cursor:{
show: true,
zoom:true,
showTooltip:false
}
});
Nevermind! I figured it out! In the tooltipContentEditor function I needed to do this:
var splitted = str.split(",");
Instead of this:
var splitted = plot._plotData[1][index];
The Goal
I'm attempting to render a long series of data (around 200 ticks, from small float values like 1.3223) into a line chart.
The Issue
When I use a series of data that changes only a small amount (around 0.0001 every tick), the chart is rendered as very jagged (scissor like). I would like to somehow fix it to have a "saner" radius between each point on the graph.
A Good Example
On the other hand, when rendering higher values (around 1382.21) with bigger difference between ticks (from 0.01 to 0.05 +/-) the graph is rendered more smooth and aesthetically pleasing.
Edit: As user Arie Shaw pointed out, the actual low or high values don't make a difference and it remains an issue of representing small "monotonous" changes is a less jagged form.
The Code
var initChart = function(data, container) {
new Highcharts.Chart({
chart: {
type: "area",
renderTo: container,
zoomType: 'x'
},
title: {
text: ''
},
xAxis: {
labels: {
enabled: false
}
},
yAxis: {
title: {
text: ''
}
},
legend: {
enabled: false
},
color: '#A3D8FF',
plotOptions: {
area: {
fillColor: '#C6E5F4',
lineWidth: 1,
marker: {
enabled: false
},
shadow: false,
states: {
hover: {
lineWidth: 1
}
},
threshold: null
}
},
exporting: {
enabled: false
},
series: [{
name: "TEST",
data: data
}]
});
};
Both graphs, and sample data sets are presented in the following fiddle:
http://jsfiddle.net/YKbxy/2/
The problem you're experiencing is unavoidable: If you have a lot of small variations over time, the graph is going to appear jagged provided that you show each data point.
The key point is that last phrase.
One way to 'smooth out' the rough parts would be to average the data. For example:
var myData = []; //... Some array of data; assuming just numbers
var averageData = function (data, factor) {
var i, j, results = [], sum = 0, length = data.length, avgWindow;
if (!factor || factor <= 0) {
factor = 1;
}
// Create a sliding window of averages
for(i = 0; i < length; i+= factor) {
// Slice from i to factor
avgWindow = data.slice(i, i+factor);
for (j = 0; j < avgWindow.length; j++) {
sum += avgWindow[j];
}
results.push(sum / avgWindow.length)
sum = 0;
}
return results;
};
var var initChart = function(data, container) {
new Highcharts.Chart({
series: [{
name: "TEST",
data: averageData(myData, 2)
}]
});
});
This method also has the advantage that you could (potentially) reuse the function to compare the averaged data to the regular data, or even toggle between how much to average the data.
You can always use areaspline instead of area, see: http://jsfiddle.net/YKbxy/3/
why dont you treat you .00001 data as 1, so times 10000, and then write it in your legend like that.
You should even do that as a test, since if the chart looks fine then, it means there is a problem in the dataset numbers when you return it to normal, since high charts takes the difference between high and low...
Either you must approximate your data by only using a few decimal places or you must average out the values using something like:
var data = new Array(200);
var smallArray = new Array(5);
var averagedData = new Array(20);
for (var index=0; index<=averagedData.length; index++){
for(var i = 0; i<=smallArray.length; i++){
smallArray[i] = data[i + index * 5];
}
averagedData[index] = (smallArray[1] + smallArray[2] + smallArray[3] + smallArray[4] + smallArray[5])/smallArray.length;
}
Then you will only need to plot 20 averaged points on an array of 200 data points. You can change the values for what you need.
In the end the issue is in the frequency of the points or their plotting on yAxis.
When I provide more realistic positioning (e.g timestamp) it will look good.
Meaning that jaggedness is a result of the small changes over constant yAxis progression, which is most similar to nt3rp's answer
I have this y axis labels formatter
yAxis: {
title: {
text: null
},
labels: {
formatter: function(){
return (Math.abs(this.value) / 1000000) + 'M';
}
}
},
but I need the formater to check if the values is more than million 1000000 then format it accordingly..
I've tried this but it didn't work properly
yAxis: {
title: {
text: null
},
labels: {
formatter: function(){
if (this.value > 999999) {
return (Math.abs(this.value) / 1000000) + 'M';};
}
}
},
it displayed the labels on one side only..
I'm using the Stacked bar chart pyramid
here is it on JSFiddle
http://jsfiddle.net/chGkK/
The issue is the formatter function only returns a label if the value is greater or equal to 1 million. You need to use the absolute value in this comparison and move the return statement outside the if block:
var absValue = Math.abs(this.value);
if (absValue >= 1000000) {
absValue = (absValue / 1000000) + 'M';
};
return absValue;
I'm trying to limit the number of ticks on a dynamic jqplot I'm setting up. Unfortunately, when I do it, the points do not look accurate. Here's what it looks like:
As you can see, the point on 10/05/12, for example, is not on it's correct axis. I realize that now these points are estimated, but the points must look accurate on the graph -- especially when hovering over the points gives you their correct date and y-axis value.
Here's my code for this intilization, if that helps:
var datepickerBegin = $("#datepicker_start").datepicker({dateFormat: "dd/mm/yyyy"}).val();
var datepickerEnd = $("#datepicker_to").datepicker({dateFormat: "dd/mm/yyyy"}).val();
var startDiff = $("#datepicker_start").datepicker("getDate");
var endDiff = $("#datepicker_to").datepicker("getDate");
alert(startDiff)
alert(endDiff)
// Check if dates are more than a week apart
if(endDiff - startDiff >= 15 * 86400 * 1000) {
var plot2 = $.jqplot('chart2', jsonurl,{
title: "Storage Space",
dataRenderer: ajaxDataRenderer,
dataRendererOptions: {unusedOptionalUrl: jsonurl},
axes: {
xaxis: {
'numberTicks' : 15,
min: datepickerBegin,
max: datepickerEnd,
renderer:$.jqplot.DateAxisRenderer,
rendererOptions:{tickRenderer:$.jqplot.CanvasAxisTickRenderer},
tickInterval: '1 day',
tickOptions:{formatString:'%#m/%#d/%Y'
}
},
yaxis: {
label: "MB",
tickOptions:{formatString:'%d '},
min: 0
}
},
highlighter: {
show: true,
sizeAdjust: 7.5
}
});
// Somehow fix the line?
plot2.redraw({});
}
Anyone out there have a fix for this? Thanks!