I use chart.js to display live data...
var doAjax = function() {
$.ajax({
url: url,
success: function(){
var currentTime = ++time
var currentValue = Math.random()*1000;
liveChart.data.labels.push(currentTime);
liveChart.data.datasets[0].data.push(currentValue);
liveChart.update();
},
complete: function () {
// Schedule the next
setTimeout(doAjax, interval);
}
});
};
doAjax();
...but at the beginning of the update, the first point is displayed in the center of the chart but its label is in the axes origin. How can I align first point and its label? Here is a jsfiddle to see the problem in action https://jsfiddle.net/uue7am8z/4/
After digging into the chart.js source, I can confirm that this is in fact a chart.js bug. When a line chart is created with a single label and single point, it incorrectly positions the rendering of the point.
I'm working on a fix for this, but in the mean time an official bug has been reported (#4037)
Related
I would like to fetch data for example from this website: https://www.highcharts.com/stock/demo/lazy-loading
To get the data with high resolution, I have to set the min max to small value and then I have to go over the complete diagram.
It is possible to get data from the website with "Highcharts.charts[0].series[0]"
But I didn't find a possibility to programable changing the navigators, to get other data ranges.
Is it possible to move the navigator to a specific position?
You can use Axis.setExtremes function for this.
Live demo: http://jsfiddle.net/kkulig/am3cgo5w/
API reference: https://api.highcharts.com/class-reference/Highcharts.Axis#setExtremes
Thank you for your answear. Here is my code if somebody needs:
I saw, that the redraw event will be called 5 times till the diagram is finishd redrawn
counter = 1
// Get chart
chart = $('#highcharts-graph').highcharts()
// add event
Highcharts.addEvent(chart, 'redraw', function (e) {
console.log(counter);
counter = counter+1;
if(counter>5){
console.log('finish loaded')
function2()
}
})
var newSelectedMin = 0
var newSelectedMax = 10
chart.xAxis[0].setExtremes(newSelectedMin, newSelectedMax);
So I have this chart built out and it works except it keeps throwing the error Cannot read property 'chart' of undefined. I am reloading the chart on window resize so that the html labels reload in correct positions.
It's a double donut chart and shows/hides content based on the selected slice.
Any help would be greatly appreciated.
First of all, you define var chart variable in createChart function, so it always will be undefined - use only one definition (the one on top), later just assign chart to that variable. Anyway, I see two solutions:
use setTimeout() in resize event, to render chart with a delay. Not a reliable solution, because user can play around with width of the browser and something may be broken again
wrap initReflow method to check if chart exists, like this:
(function(H, HA) {
H.wrap(H.Chart.prototype.initReflow = function () {
var chart = this,
reflow = function (e) {
if(chart && chart.options) {
chart.reflow(e);
}
};
HA.addEvent(window, 'resize', reflow);
HA.addEvent(chart, 'destroy', function () {
HA.removeEvent(window, 'resize', reflow);
});
});
})(Highcharts, HighchartsAdapter)
Working demo: https://jsfiddle.net/dpsn9gx8/7/
Edit:
Since Highcharts 4.1.10 Highcharts adapter is built-in, so remove it and use Highcharts: https://jsfiddle.net/dpsn9gx8/11/
I am plotting a point graph and the graph should get update with new data for every 5 secs. Here min and max range are always fixed
Currently, when I get new data from server, I do merge the new data to the existing source.data and plotting the complete graph.
So, I dont want to redraw the complete data again and again. As the length of the source.data is increasing, performance is going down . So instead of redraw complete data, can I add only the new data to the existing graph
Please find the source code here
var source = [
{
data: [],
show: true,
label: "Constellation",
name: "Constellation",
color: "#0000FF",
points: {
show: true,
radius: 2,
fillColor: '#0000FF'
},
lines: {
show: false
}
}
]
var options = {...}
$.getJSON(URL , function(data) {
...
$.merge(source[0].data, new_data);
plotObj = $.plot("#placeholder", source, options);
}
Follow this steps:
plotObj.setData(newData);
plotObj.setupGrid(); //if you also need to update axis.
plotObj.draw(); //to redraw data
Another usefull method is getData(). With this method you can get the current data.
var data = plotObj.getData();
Your method of calling $.plot over and over should be avoided. It used to leak memory (not sure if it still does).
That said, #Luis is close, but let's put it all together. To add data to an existing plot do this:
var allData = plotObj.getData(); // allData is an array of series objects
allData[seriesIndex].data.push([newXPoint,newYPoint]);
plotObj.setData(allData);
plotObj.setupGrid(); // if axis have changed
plotObj.draw();
It should be noted that this does redraw the entire plot. This is unavoidable with HTML5 canvas. BUT flot draws extremely fast, you'll barely notice it.
EDIT:
Solved the issue: .useInteractiveGuideline(true) changed to .useInteractiveGuideline(false)
ORIGINAL:
I am trying to modify the custom output binding example using an NVD3 line chart with attaching a click event listener to the NVD3 chart. I modified the linechart-bindings.js file as follows. The only modification is this part of the code (the whole file is also copied below so you can see there i added the snippet):
chart.lines.dispatch.on("elementClick", function( e ) {
console.log(e);
});
The app starts without problem, but there is no console log printout when i click the chart. Probably my approach is too simplistic and there is some obvious part missing. Any idea how to solve this?
The full linechar-bindings.js file:
// Put code in an Immediately Invoked Function Expression (IIFE).
// This isn't strictly necessary, but it's good JavaScript hygiene.
(function() {
// See http://rstudio.github.io/shiny/tutorial/#building-outputs for
// more information on creating output bindings.
// First create a generic output binding instance, then overwrite
// specific methods whose behavior we want to change.
var binding = new Shiny.OutputBinding();
binding.find = function(scope) {
// For the given scope, return the set of elements that belong to
// this binding.
return $(scope).find(".nvd3-linechart");
};
binding.renderValue = function(el, data) {
// This function will be called every time we receive new output
// values for a line chart from Shiny. The "el" argument is the
// div for this particular chart.
var $el = $(el);
// The first time we render a value for a particular element, we
// need to initialize the nvd3 line chart and d3 selection. We'll
// store these on $el as a data value called "state".
if (!$el.data("state")) {
var chart = nv.models.lineChart()
.margin({left: 100})
.useInteractiveGuideline(true)
.transitionDuration(350)
.showLegend(true)
.showYAxis(true)
.showXAxis(true);
chart.xAxis //Chart x-axis settings
.axisLabel('Time (ms)')
.tickFormat(d3.format(',r'));
chart.yAxis //Chart y-axis settings
.axisLabel('Voltage (v)')
.tickFormat(d3.format('.02f'));
chart.lines.dispatch.on("elementClick", function( e ) {
console.log(e);
});
nv.utils.windowResize(chart.update);
var selection = d3.select(el).select("svg");
// Store the chart object on el so we can get it next time
$el.data("state", {
chart: chart,
selection: selection
});
}
// Now, the code that'll run every time a value is rendered...
// Retrieve the chart and selection we created earlier
var state = $el.data("state");
// Schedule some work with nvd3
nv.addGraph(function() {
// Update the chart
state.selection
.datum(data)
.transition(500)
.call(state.chart);
return state.chart;
});
};
// Tell Shiny about our new output binding
Shiny.outputBindings.register(binding, "shinyjsexamples.nvd3-linechart");
})();
Not a solution but a workaround:
.useInteractiveGuideline(true) changed to .useInteractiveGuideline(false)
In my code I'm initializing the chart like this...
<script type="text/javascript">
var chart = null,
defaultOptions = {
chart: etc etc
};
function drawDefaultChart() {
chart = new Highcharts.Chart(defaultOptions);
}
$(function() {
$(document).ready(function() {
drawDefaultChart();
});
});
</script>
then in the body I have
Reset
but when you click the link, all it does is redraw the graph with the settings from the previous state... I'm not quite sure what is going on. If I add chart.destroy(); the chart doesn't work at all...
function drawDefaultChart() {
chart.destroy(); //this makes the chart not work at all
chart = new Highcharts.Chart(defaultOptions);
}
You can clearly see that I 'm pasing default options to the chart that is suppose to get redrawn.... I don't understand why it uses the old filter settings, i'm about to jump off a bridge, can somebody PLEASE HELP?
my live example is here http://goo.gl/sGu0M
//////// UPDATE
I was able to do it with a lot of blood, sweat, and tears. I ended up putting the data into a php variable on another page (to save real estate), and then calling it using php variables, and then I just call it everytime someone clicks a link. I figured out that in order to redraw the graph, you have to reload ALL the data in each time. The PHP makes this easier in terms of amount of data on the screen.
this was the link that eventually helped me figure it out. http://jsfiddle.net/dane/YUa3R/34/
Always it's recommend to refer API documentation.
use following snippet to destroy the chart $('#container').highcharts().destroy();
Click here for a working solution.
First off, I know NOTHING about highcharts, but it would seem you need: (from your actual page)
function drawDefaultChart() {
$("#container").empty();
chart = new Highcharts.Chart(defaultOptions);
}
to be
function drawDefaultChart() {
$("#container").empty().highcharts(defaultOptions);
}
OR perhaps:
function drawDefaultChart() {
$("#container").highcharts(defaultOptions);
}