I need to create different backgrounds for 4 seasons with Highstock plugin.
I managed to display bands with different colors to show where seasons start and end. Then I stumble across this plugin:
http://www.highcharts.com/plugin-registry/single/9/Pattern-Fill
but I'm only able to set recurring pattern to fill the band. Alternatively this could be fixed if something like CSS "no-repeat" would be achievable for SVG patterns.
How do I set an image in the middle of the band so it works as a nicely centered background? I tried markers first but this affects X axis labels. If not with the addBand feature, I think it's smarter to just plot images with highchart image renderer. The only thing is you can use X Y coordinates within the graph, but this is not the case of highstock where you can scroll the whole thing horizontally.
After couple different approaches I ended up using this event for both x axes:
afterSetExtremes : function(e) {
var xMin = e.min;
var xMax = e.max;
var ex = graph.xAxis[1].getExtremes();
if (ex.min != xMin || ex.max != xMax) graph.xAxis[1].setExtremes(xMin, xMax, true, false);
}
( [1] for 2nd axis' event and [0] for the 1st axis' event. )
Unfortunately I couldn't achieve the effect with linkedTo parameter. Maybe I was missing something or it's a feature to be used for a different scenario than mine (highstock, 2 X-axes).
Related
I am using chart.js to try to create a timeline of events relative to current date.
The horizontal bar chart is close but would like to show only the tips of the bars eg as points which would pretty much be a horizontal line chart.
I have shown my horizontal bar chart along with a mock-up of what it would look like as horizontal line chart.
Is this possible with chart.js ?
You first need to know that every information that you can edit about the chart is stored in the variable containing your chart (called myChart usually, but my2Bar in your fiddle).
If you want to globally change the graph, you will need to edit attributes in myChart.config.options.
If you want to change a specific chart, you will need to edit attributes in myChart.config.data.
In this case, you need to change a specific chart (which is the horizontal bar).
If you happen to check the logs of your graph, and go very deep in the config, you will finally see that bars in your chart are drawn using attributes stored in myChart.config.data.datasets[0]._meta[0].data[n]._model (n being the nth rectangle drawn, top to bottom).
Some attributes you can find there :
base : The X position where the rectangle is starting to be drawn (0 in your xAxe for instance).
x : The rectangle is being drawn until this X position.
height : The height of the drawn rectangle.
and so on ...
To edit these values, you just need to loop in your different rectangles (the n in the above path).
But you just can't do it manually on the config of your variable. If you do this, it won't work since your chart is responsive (on resize, it will redraw the chart using the former options).
What you must use are Chart.js plugins.
Plugins let you handle all the events that are triggered while creating, updating, rendering your graph.
Then, in your beforeRender event (triggered after the initialisation, but before the drawing), you need to loop in your different rectangles to edit the values to affect how they will be drawn :
beforeRender: function(chart) {
for (var i = 0; i < chart.config.data.datasets[0]._meta[0].data.length; i++) {
// Change both `3` values to change the height & width of the point
chart.config.data.datasets[0]._meta[0].data[i]._model["base"] = chart.config.data.datasets[0]._meta[0].data[i]._model["x"] + 3;
chart.config.data.datasets[0]._meta[0].data[i]._model["height"] = 3;
}
}
Here is a jsFiddle with the final result.
Unfortunately, I wasn't able to make round dots, instead of squared ones.
Update :
I have also made another jsFiddle where all the dots are linked together which makes it look like it is a horizontal line chart (can be improved of course, but it is a good start).
When using Chart.js i cant find a way to evenly scale the Y axis. Overiding and using manual scaling( scaleOverride: true ) for every chart is not really an option since there are alot of them and they have different data. Some one have an idea how to fix the scaling of the data?
This is the scaling i want:
Sometimes the scaling gets uneven depending on the data.
You can set the options globally - this will apply to every chart instance. For instance
Chart.defaults.global.scaleOverride = true;
...
I am developing a visualisation based on this interactive time-series composed of two plots. I would like to add a set of vertical lines in both plots indicating specific dates like
var labels = [
["Christmas 2011", 2011-12-25],
["Christmas 2012", 2012-12-25],
];
with a vertical axis, which doesn't move in the plot on the bottom and move accordingly with the zoom level in the top plot.
Should I focus.append.line? But then I should I provide the exact coordinates?
To add a line to your particular point:
var xval = x2(new Date('2008-12-25'));
focus.append("line")
.attr({
x1:xval,
x2:xval,
y1:0,
y2:height,
stroke:'black',
'stroke-width':1
});
This is using x2 and height from the code you linked to above.
To add a label:
focus.append("text")
.attr({
x:xval,
y:height/2,
'font-size':'1em',
fill:'red'
})
.text('Christmas 2008');
This doesn't work when you zoom in to a particular date range. I haven't figured out how to do that. I guess there must be a refresh event that I need to hook into or something.
I'm currently using a the NVD3 discreteBarChart but I have a lot of data and the labels on the X axis, which are dates in my application, are encroaching upon each other like this : ). This doesn't happen with a multiBar or a linePlusBar chart, where the labels are automatically adapted :
How can I prevent the lablels on the discreteBar chart to impinge on the others?
Thanks for your answers!
Little late to answer, but to get similar results but using multi-barchart as mentioned by Lars , you can use following command to get a similar graph (i.e hide "stacked" and "grouped", as well as legend buttons).
n1$chart(showControls = FALSE, showLegend = FALSE)
I'm building in some custom functionality where users can click on data points in a line chart to add notes to that date. This is a bit misleading as the notes aren't actually attached to the metrics themselves but rather the date it lands on. In other words, if I have 6 series on one line chart that spans the dates 01/01/12 - 01/08/12, a single note on 01/05/12 will apply to all 6 series. So, as you can imagine clicking on a data point on one of the 6 series or the date 01/05/12 would mislead the user to believe that this note would be applied to that data point, not the entire date and any series that lands on that date.
So, to remedy this usability issue I've decided that the best visual cue would be something like this:
There would be a clickable icon at the top of each xAxis gridLine that would need to scale with the xAxis gridLine (like if a user selects an area to zoom in on).
Suggestions on best way to pull this off? I only need a suggestion for how best to add the icon to every line... I have all post-click functionality already built.
Building on Mark's suggestion using redraw event to position the images and using load event to create them. Adding them on load is necessary to make them available during export and you would not want to create new images on each redraw either.
These chart events are used:
events: {
load: drawImages,
redraw: alignImages
}
In the drawImages function I'm using the inverse translation for the xAxis to position the images on the chart:
x = chart.plotLeft + chart.xAxis[0].translate(i, false) - imageWidth / 2,
y = chart.plotTop - imageWidth / 2;
and then adding them and setting a click handler, zIndex, pointer cursor:
chart.renderer.image('http://highcharts.com/demo/gfx/sun.png', x, y, imageWidth, imageWidth)
.on('click', function() {
location.href = 'http://example.com'
})
.attr({
zIndex: 100
})
.css({
cursor: 'pointer'
})
.add();
In alignImages the attr function is used to set new x and y values for the images which are calculated the in the same way as in drawImages.
Full example on jsfiddle
Screenshot:
Couple of ideas. First, I would use the chart redraw event to know when the chart is being redrawn (say on a zoom). Then second, explicitly place your images at the axis locations of interest. To get those query directly out of the DOM.
Using jQuery:
$('.highcharts-axis') //return an array of the two axis.
They will have svg "text element" children with (x, y) positions.