I tried to add flags for loading dynamical data that worked at first when I used the continuous update charts as follows https://www.highcharts.com/stock/demo/dynamic-update and then the flags as follows https://www.highcharts.com/stock/demo/flags-shapes.
Can you please give me some solution for adding flags for continuous data? Also, I would want that if the continuous data exceeds some limit, the flags should appear on that series. And i want flags on continuous data also
Similar to adding points for the basic series, you should also add flag series points:
events: {
load: function () {
var series = this.series[0],
flagSeries = this.series[1];
setInterval(function () {
var x = (new Date()).getTime(), // current time
y = Math.round(Math.random() * 100);
series.addPoint([x, y], true, true);
flagSeries.addPoint({
x: x,
title: y
});
}, 1000);
}
}
Live demo: https://jsfiddle.net/BlackLabel/rh8jug5d/
API: https://api.highcharts.com/class-reference/Highcharts.Series#addPoint
Related
I am developing in Javascript to render a table using a DataTables (Table plug-in for jQuery). I am also using Bootstrap Multiselect (https://github.com/davidstutz/bootstrap-multiselect) to filter the table. I would like to re-render my BokehJS plot everytime the table is re-drawn. I have hooked up the correct calls but I am also calling Bokeh.Plotting.show to re-render the graph. This forces me to remove the last created div to avoid multiple graphs plotted. I am new to the JS side of Bokeh and wanted to understand if there is a cleaner method to update the plot in JS?
var eventFired = function ( type ) {
//var n = $('#demo_info')[0];
//n.innerHTML += '<div>'+type+' event - '+new Date().getTime()+'</div>';
//n.scrollTop = n.scrollHeight;
var plt = Bokeh.Plotting;
// set up some data
var M = 25;
var xx = [];
var yy = [];
var colors = [];
var radii = [];
for (var y = 0; y <= M; y += 4) {
for (var x = 0; x <= M; x += 4) {
xx.push(x * (Math.random() +0.5));
yy.push(y * (Math.random() +0.5));
colors.push(plt.color(50+8*x, 30+8*y, 150));
radii.push(Math.random() * 0.4 + 1.7)
}
}
// create a data source
var source = new Bokeh.ColumnDataSource({
data: { x: xx, y: yy, radius: radii, colors: colors }
});
// make the plot and add some tools
var tools = "pan,crosshair,wheel_zoom,box_zoom,reset,save";
var p = plt.figure({ title: type+' event - '+new Date().getTime(),
height: 300,
width: 300,
tools: tools });
// call the circle glyph method to add some circle glyphs
var circles = p.circle({ field: "x" }, { field: "y" }, {
source: source,
radius: radii,
fill_color: colors,
fill_alpha: 0.6,
line_color: null
});
//remove old plot on update conditions
$('.bk-root').remove();
// Show the plot, appending it to the end of the current
// section of the document we are in.
Bokeh.Plotting.show(p, document.getElementById('myplot'));
//To Do: add in transition to improve the UI appearance
}
And here is the the datatable setting up the call back to the BokehJS script.
</script>
$('#table').DataTable({
responsive: {
details: {
display: $.fn.dataTable.Responsive.display.modal( {
header: function ( row ) {
var data = row.data();
return 'Details for '+data[0]+' '+data[1];
}
} ),
renderer: $.fn.dataTable.Responsive.renderer.tableAll( {
tableClass: 'table'
} )
}
},
paginate: false,
info: false,
paging: true,
autoWidth: true,
dom: '<"dt-buttons">Bf<"clear">lirtp',
"buttons": [ 'copy', 'csv', 'excel' ],
}).on( 'draw.dt', function () { eventFired( 'Draw' ); } );
Lastly, is there a good method to update the plot via a transition effect to improve the appearance of the re-plotting?
I eventually figured out all of the components in the process in a modified use case compared to the one shown above. In my present approach I needed to utilize my source data and emit a 'change' trigger.
source.data.factors = [my new factor list]
source.trigger('change');
The new factor list based on the jQuery datatable can be obtained as followed.
$('mytable').DataTable().columns(0, {search: 'applied'}).data()[0]
Also in my use case I am working with a categorical axis. In my specific use case, my factors will dynamically change upon redraw of the graph. This can be achieved using the plot's attributes.
p.attributes.x_range.factors = [ my new factor list from my updated source data]
There is also no need to remove the old plot, and the added plus is the redraw is very fast for my simple plots.
I'm trying to have my Highstock chart update every minute, by replacing its existing data set with one that is extracted from a url request (which would have different data at different times).
So far I'm not even able to get the data to refresh based on manual changes.
Work so far: https://jsfiddle.net/Lz8gLw8j/
I'm trying to test changing data and then updating it with:
varData = [[0,0],[1,2]]
$('#chart2').highcharts().redraw();
Which does nothing.
You can set the new data to highchart in following way:
var newData = [
[1251763200000, 23.61],
[1251849600000, 23.60],
[1251936000000, 23.79]
]
var chart = $('#chart2').highcharts();
chart.series[0].setData(newData);
$('#chart2').highcharts().redraw();
Updated fiddler:
https://jsfiddle.net/Lz8gLw8j/5/
It looks like there is a load event that you can use
chart : {
events : {
load : function () {
// set up the updating of the chart each second
var series = this.series[0];
setInterval(function () {
var x = (new Date()).getTime(), // current time
y = Math.round(Math.random() * 100);
series.addPoint([x, y], true, true);
}, 1000);
}
}
}
Here's a fiddle: https://jsfiddle.net/jjwilly16/Lz8gLw8j/6/
FYI: I pulled this from an example off of the Highcharts website: http://jsfiddle.net/gh/get/jquery/1.9.1/highslide-software/highcharts.com/tree/master/samples/stock/demo/dynamic-update/
You can add data to the existing series using the addPoint method and replace the dataset using the setData method. The second option argument for both of the methods allows you to redraw the chart. The data should be an array of arrays. The nested array contains the actual data that is plotted. The first elements of the inner, nested array is the epoch (x) while the second is the actual value (y). The epoch is the number of seconds since January 1, 1970 Midnight GMT/UTC. I have updated the fiddle to allow you to add data points as well as reset the data.
The main change are these lines:
$('#updateButton').click(function() {
var date = $('#newDate').val();
var epoch = Math.round(new Date(date).getTime());
var value = parseInt($('#newValue').val());
var chart = $('#chart2').highcharts();
chart.series[0].addPoint([epoch, value], true);
});
$('#resetChart').click(function() {
var chart = $('#chart2').highcharts();
chart.series[0].setData(null, true);
});
https://jsfiddle.net/Lz8gLw8j/7/
On a Highcharts chart with datetime axis, I am trying to highlight weeks. First, I had the idea to use the grid and to set tickInterval to 7*24*60*60*1000 and minorTickInterval to 24*60*60*1000. With the option gridLineWidth set to 2, the result is almost perfect.
The problem is when zooming: minor ticks appears but without label. I can not find how to add it. And the labels are not dynamic.
You can try this demo: https://jsfiddle.net/gdebrion/19x4nmp5/19/
First chart is the basic one. When you zoom you can see the changes in x-axis.
Second chart is mine. The weeks are visible but when zooming in until having a day display on the full width, and the only ticks visible are the minor one, without label…
Please tell me if you have an idea. Thanks!
The API does not provide a way to display labels on minor ticks.
http://www.highcharts.com/docs/chart-concepts/axes
MINOR TICKS
If the minorTickInterval option is set, minor ticks are laid out between the major ones. This includes minor tick marks, and minor grid lines, which have their own options for look and feel, but excludes labels.
Having a peek at the source code for Highcharts, I also do not see any label representation for minor ticks as there are for the major ticks (axis.labelEdge = [];) .
https://github.com/highcharts/highcharts/blob/b6bc666da00d37c5c4e3c0d7fe238b8526e583ea/js/parts/Axis.js
...
// Major ticks
axis.ticks = {};
axis.labelEdge = [];
// Minor ticks
axis.minorTicks = {};
// List of plotLines/Bands
...
UPDATE:
Here is a slightly rough solution to enable minor tick labels for highcharts:
http://jsfiddle.net/strince/deuez7gk/
The code doesn't handle overlapping labels when the zoom is far out so you'll need to zoom in a bit to see it work.
The chart code was updated with:
// Keep track of elements created.
var minorTickLabels = new Array();
...
events: {
load: function() { addMinorTickLabels(this); },
redraw: function() { addMinorTickLabels(this); }
}
...
function addMinorTickLabels(chart) {
// The elements need to be destroyed, otherwise a dictionary
// internal to highcharts will accumulate and pollute the chart.
for (var i = 0; i < minorTickLabels.length; i++) {
var textItem = minorTickLabels[i];
textItem.destroy();
}
minorTickLabels = new Array();
var axis0 = chart.xAxis[0];
var lastIndexFound = 0;
for (var tick in axis0.minorTicks) {
var el = axis0.minorTicks[tick];
// Skip double labels on major ticks.
var index = axis0.tickPositions.indexOf(el.pos, lastIndexFound);
if (index >= 0) {
listIndexFound = index;
continue;
}
var xPos = el.mark.getBBox().x;
var yPos = el.mark.getBBox().y;
var labelText = 0;
// The formatting parameters below should be passed in.
var textItem = chart.renderer.text(Highcharts.dateFormat("%d. %b", el.pos), xPos, yPos)
.css({
color: '#101010',
fontSize: '8px'
})
.attr({
rotation: -25,
zIndex: 6
});
// Add the tick label to the chart.
textItem.add();
minorTickLabels.push(textItem);
}
};
I am trying to create a plugin for our chart that shows a marker on the last data in the series of a data streams. The symbol should show on the newest data only. I learnt here that i can extend the prototypes and create my chart Here like
(function (H) {
H.wrap(H.Chart.prototype, 'init', function(proceed) {
proceed.apply(this, Array.prototype.slice.call(arguments, 1));
};
H.wrap(H.Chart.prototype, 'redraw', function(proceed, points) {
proceed.apply(this, Array.prototype.slice.call(arguments, 1));
//Add my marker symbol here
});
}(Highcharts));
I tested the two events above, they start add the right time. However, my points is a boolean value which is not what i was expecting. I read the api docs Here yet couldn't understand how to proceed. Please if some has a better example or guidance on how to use the extension and achieve this would highly be appreciated. My data is a stream and continuos data and need to show the the marker symbol on top of the newest data only.
Update
Thanks for the response sir. We are using react-highcharts and i noticed i don't have access to the chart load event. Nonetheless, i noticed i can extend my H.Series prototype as explained Here and my event is fired on every new tick paint. I now update my code to
H.wrap(H.Series.prototype, 'drawGraph', function (proceed) {
proceed.apply(this, Array.prototype.slice.call(arguments, 1));
const { chart } = this;
renderSpotIndicator(chart);
});
function renderSpotIndicator(chart){
const series = chart.series[0],
len = series.data.length - 1,
lastPoint = series.data[len];
if(lastPoint){
lastPoint.update({
marker: {
enabled: true
}
});
}
}
When i run , then i noticed my marker property does not exist in my lastPoint as hence its throwing errors. I was not able to use that. I was advised to paint the marker instead. following the example Here . I changed my code to
function renderSpotIndicator(chart){
const series = chart.series[0],
len = series.data.length - 1,
lastPoint = series.data[len];
if(lastPoint){
chart.renderer.circle(lastPoint.pointX, lastPoint.pointY, 5).attr({
fill: lastPoint.color,
padding: 10,
r: 5,
stroke: 'white',
'stroke-width': 1,
zIndex: 5
}).add();
}
}
The above is throwing errors as well. When i checked, i noticed the property circled it self is not available on my lastPoint. My lastPoint is returning correct but i am not able to set the marker on the specific point for the property was not available on the lastPoint. Please any help would be appreciated sir.
You can edit the load event and extract last point of series. Then call update to show the marker. Each time when your chart is refreshed (by add point) you need to do the same steps. Extract last point, update marker (hide), add point and show last marker.
var series = this.series[0],
len = series.data.length - 1,
lastPoint = series.data[len];
lastPoint.update({
marker: {
enabled: true
}
});
setInterval(function() {
var x = (new Date()).getTime(), // current time
y = Math.random();
len = series.data.length - 1;
series.data[len].update({
marker: {
enabled: false
}
}, false);
series.addPoint([x, y], true, true);
len = series.data.length - 1;
series.data[len].update({
marker: {
enabled: true
}
}, true);
}, 1000);
Example:
- http://jsfiddle.net/ga2sym0v/
I was reading a bit about the high charts addPoint() function here:
http://api.highcharts.com/highcharts#Series.addPoint()
I'm quite taken the idea of creating a chart like this one:
http://www.highcharts.com/demo/dynamic-click-to-add
...but where I have a fixed x and y scale, and where the user can only place a point on the scale in multiple of 5.. such as a point at x=10 and y=20...
Has this been attempted, and/or is it feasible given the options provided in the API?
Thanks
You can modify this behavior in your click handler - you get the exact click values there, and you can simply round it to the next interval you like:
events: {
click: function(e) {
// find the clicked values and the series
var x = e.xAxis[0].value,
y = e.yAxis[0].value,
series = this.series[0];
// round given click point to intervals
x = Math.ceil(x / 5) * 5;
y = Math.ceil(y / 5) * 5;
// Add it
series.addPoint([x, y]);
}
}
The Demo of this example will give you a starting point.