I created an array that contains all of the flot objects on the screen. Using the selection plugin, I am implementing a zoom feature.
Unfortunately, the code below does not work as expected. I can confirm with console.log that the options change. The clearSelection() also works but the graph never redraws.
Also, I don't think it matters but I'm using a time-based x-axis.
$(".flot").bind("plotselected", function (event, ranges) {
var plot = flots['#'+event.target.id];
plot.getOptions().xaxis.min = ranges.xaxis.from;
plot.getOptions().xaxis.max = ranges.xaxis.to;
plot.setupGrid();
plot.clearSelection();
plot.draw();
});
I figured it out. For some reason I had to change the axes min and max using the xaxes[0].min and yaxes[0].min.
$(".flot").bind("plotselected", function (event, ranges) {
var plot = flots['#'+event.target.id];
plot.getOptions().xaxes[0].min = ranges.xaxis.from;
plot.getOptions().xaxes[0].max = ranges.xaxis.to;
plot.setupGrid();
plot.clearSelection();
plot.draw();
});
Related
I am trying to make amCharts V4 to show tooltip for the data item most close to the cursor.
The problem is that my chart is mostly oriented vertically. I was able to break amCharts V4 sample by updating the sample data to get a vertical chart: https://codepen.io/fvnever/pen/jOwyQEE
Here, the data tooltips aren't changing as I move my cursor over the Y axis, and I want them to be updated. I.e. on the following image, it should show the tooltip closest to the cursor from series 1, and it instead shows some item from the beginning of said series.
I've tried various suggestions from the documentation: setting and not setting chart.cursor.xAxis, chart.cursor.yAxis, chart.cursor.snapToSeries. Nothing seems to work.
There's no such feature out of the box, but it's possible to implement one. Two steps:
Make sure to disable the default tooltip behavior:
chart.cursor.snapToSeries = [];
Now, handle the 'cursorpositionchanged' event and control the tooltip there, something like the following.
Please note that this examples is very inefficient (it will iterate over all the chart nodes on every mouse move), so for any practical use, it would be better to store the data points in some sort of precalculated k-d tree.
chart.cursor.events.on('cursorpositionchanged', (e) => {
const cursor = e.target;
const cursorPoint = cursor.point;
let closestSeries = null;
let closestItem = null;
let minimalDistance = null;
for (const series of chart.series) {
for (const dataItem of series.dataItems) {
const dataPoint = dataItem.point;
const distance = Math.sqrt(Math.pow(cursorPoint.x - dataPoint.x, 2) + Math.pow(cursorPoint.y - dataPoint.y, 2));
if (minimalDistance === null || distance < minimalDistance) {
minimalDistance = distance;
closestItem = dataItem;
closestSeries = series;
}
}
}
for (const series of chart.series)
series.tooltip.disabled = series !== closestSeries;
if (closestItem)
closestSeries.showTooltipAtDataItem(closestItem);
});
Full example for testing: https://codepen.io/fvnever/pen/yLXbEKG
I have a set of interconnected charts with Highcharts and callback functions. Specifically, put together a scatter plot with an x-axis range selection, which connects to a bar chart that reflects the average y-value of the points selected, by category.
It uses the 'events' key when creating the chart to call a function that edits and redraws the bar chart.
Please click on this sandbox link to see the example that I have put together: https://codesandbox.io/s/youthful-browser-mid8x?file=/index.html
I would like to know if the code can be written any better with improvements. If anyone can please review and let me know. Thanks.
You don't need to call redraw after setData:
function update_chart2(xmin, xmax) {
...
chart2.series[0].setData(new_data);
// chart2.redraw(); - redraw is called in setData
}
You can update xAxis with plot-band options instead of removing and adding it.
events: {
selection: function (event) {
...
if (event.xAxis) {
xmin = event.xAxis[0].min;
xmax = event.xAxis[0].max;
this.xAxis[0].update(
{
plotBands: [
{
from: xmin,
to: xmax
}
]
},
false
);
}
update_chart2(Math.floor(xmin) + 1, Math.floor(xmax) + 1);
},
...
}
API Reference:
https://api.highcharts.com/class-reference/Highcharts.Series#setData
https://api.highcharts.com/class-reference/Highcharts.Axis#update
I'm trying to draw an area chart using dc.js, and the end date (i.e. far right) of the chart is based on the current date, not the last date in the dataset. In cases where there's a date gap between data points, I want the area to extend from one point to the next, not draw at 0.
Given this data:
var data = [
{domain: "foo.com", project: "pdp", repo: "myrepo", commit_date: "6/1/2014", lines_added: 100, lines_deleted: 50},
{domain: "foo.com", project: "pdp", repo: "myrepo", commit_date: "7/1/2014", lines_added: 100, lines_deleted: 50}
];
var ndx = crossfilter(data);
The chart's line/area currently ends at the "7/1/2014" data point, but I want it to stretch the entire length of the chart.
The relevant code for drawing the chart is:
var dateDim = ndx.dimension(function(d) {return d.commit_date;});
var minDate = dateDim.bottom(1)[0].commit_date;
var maxDate = new Date();
var domainGroup = dateDim.group().reduceSum(function(d) {return d.cumulative_lines;});
unshippedlineChart
.width(500).height(200)
.dimension(dateDim)
.group(domainGroup)
.renderArea(true)
.x(d3.time.scale().domain([minDate,maxDate]))
.brushOn(false)
.interpolate('step-after')
.yAxisLabel("Unshipped Value");
Full example is at http://jsfiddle.net/xayhkcvn/1/
You didn't actually ask a question :-), but I think you may be looking for ways to prefilter your data so that it gets extended to today, and to remove any zeros.
This stuff isn't built into dc.js, but there is some example code in the FAQ which may help. Specifically, there is a function remove_empty_bins which adapts a group to remove any zeros.
You could similarly define a function to add a final point (untested):
function duplicate_final_bin(source_group, key) {
return {
all:function () {
var ret = Array.prototype.slice.call(source_group.all()); // copy array
if(!ret.length) return ret;
ret.push({key: key, value: ret[ret.length-1].value});
return ret;
}
};
}
You can compose this with remove_empty_bins:
var super_group = duplicate_final_bin(remove_empty_bins(domainGroup), maxDate);
The idea is to create a wrapper object which dynamically adds or remove stuff from the (always changing) source_group.all() on demand. dc.js will call group.all() whenever it is redrawing, and these wrappers intercept that call and adapt the data the crossfilter group returns.
I am using Highcharts and I would like this chart to update each second. This is what I have now: JSFiddle
I have timer window.setInterval(updateChart, 1000); and it works properly actualizing data each second.
But I have no idea how to actualize the view. It is important that I don't want to draw chart again and again each second. I only want to shift points and add new ones. Do anyone know how to do that?
Look at the the series.addPoint method.
Your updateChart function becomes:
function updateChart()
{
for (var source = 1; source <=3; source++)
{
var point = [
23,
Math.floor((Math.random() * 10*source) + 5+source*2),
source
];
Highcharts.charts[0].series[0].addPoint(point, false, true); // add the point, don't redraw and shift off a point
}
Highcharts.charts[0].redraw(); // 3 points added, now redraw
}
Update fiddle.
I need to animate a real time graph with flot so that each new data point will transition smooth into the data set etc.
I've made a plunker with the basic flow:
http://plnkr.co/edit/oPahmS?p=preview
But I would like to make it more like highcharts
http://www.highcharts.com/demo/dynamic-update
Does anyone know a plugin or a way to do this with flot?
I don't believe either of the flot animation plugins provide this ability. Instead, it can be done with a little bit of jquery animate magic.
addPointAnimate = function(){
var series = somePlot.getData()[0]; // first series
var lastX = series.data[series.data.length-1][0]; // last x value
var opts = somePlot.getOptions();
opts.xaxes[0].max += 1; // adjust xaxis to make room for new point
somePlot.setupGrid();
$('#placeholder').animate( { 1:1 }, {
duration: 1000,
step: function ( now, fx ) {
series.data.push([lastX+fx.pos, Math.sin(lastX+fx.pos)]); // for each step of animation, push on an intermediate value
somePlot.setData( [series] );
somePlot.draw(); // redraw with intermediate value
}
});
return true;
}
Here's a working fiddle.