I am adding images using chart.renderer.image. I would like the images to line up with the beginning of each plotBand. I have the plotBand from position in axis units. However when I call toValue the images do not line up.
https://jsfiddle.net/uxeL76a9/23/
for (var i = 0; i < plotBands.length; ++i) {
var artist = plotBands[i];
var xPos = chart.xAxis[0].toValue(artist['from'], true);
...
Your chart is inverted, so axes are swapped, and you have small mess with toValue(), see fixed code:
var xPos = chart.xAxis[0].toValue(artist['from'], true);
Should be:
var xPos = chart.yAxis[0].toPixels(artist.from);
Working demo: https://jsfiddle.net/uxeL76a9/40/
Related
I'm using postRender to change the x position of some y axis labels in a couple of DC charts:
function moveLabels() {
var obj = d3.selectAll('text.y-axis-label');
for (var i=0; i<obj[0].length; i++) {
var t = d3.transform(d3.select(obj[0][i]).attr("transform"));
var keepY = t.translate[1];
d3.select(obj[0][i]).attr("transform","translate(18,"+keepY+") rotate(-90)");
}
}
It works fine, but there's an animation applied to the move. Every time I change a dropdown and redraw the chart, the y axis label slides around. Does anyone know how to get rid of it? I've tried:
d3.select(obj[0][i]).transition().attr("delay","0").attr("transform","translate(18,"+keepY+") rotate(-90)");
and
d3.select(obj[0][i]).transition().attr("duration","0").attr("transform","translate(18,"+keepY+") rotate(-90)");
Is there any way to add multiple axis on lineWithFocusChart .
I want to add my y2axis on right side of the graph.
There is a default option in the NVD3 library to draw multiple axis chart. Just look into the example of multichart at the documentation website of the library. And a sample html file is provided on the github repo of nvd3
You can use Barchart, Areachart and line chart for multiple axis.
Just draw the graph with
var chart = nv.models.multiChart()
And change the yAxis variable to draw the graph on left yaxis or right yaxis like this.
testdata[0].type = "area";
testdata[0].yAxis = 1;
testdata[1].type = "area";
testdata[1].yAxis = 1;
testdata[2].type = "line";
testdata[2].yAxis = 1;
testdata[3].type = "line";
testdata[3].yAxis = 2;
testdata[4].type = "bar";
testdata[4].yAxis = 2;
testdata[5].type = "bar";
testdata[5].yAxis = 2;
testdata[6].type = "bar";
testdata[6].yAxis = 2;
I am using the code snippet from this stackoverflow question to label my flot data points. So far this has served me well, but now I have to label the overall values of stacked bars. There are two data series and so far I've managed to calculate the sums, but I can't seem to work out a proper positioning for my labels. I'd like to place them on top of the stacks, but pointOffset only gives me the offsets based on non-stacked bars.
This is the code I am currently using, it places the labels where the second series' data points would be, if the bars weren't stacked, which puts them somewhere in the top bars.
$.each(p.getData()[1].data, function(i, el){
var series0 = p.getData()[0].data;
sum = el[1] + series0[i][2]
var o = p.pointOffset({x: el[0], y: el[1]});
$('<div class="data-point-label">' + sum + '</div>').css( {
position: 'absolute',
left: o.left - 5,
top: o.top ,
display: 'none'
}).appendTo(p.getPlaceholder()).fadeIn('slow');
});
Edit #1: So far I've tried using c2p/p2c, calculating the top value using the single data points' top values and finding more documentation on the stack plugin. I am afraid none of this has helped me much.
Edit #2: I've also tried the code given in this stackoverflow answer but it doesn't work for me. I suspect the author is using some label plugin ...
The solution to put the labels in the top of the bars in stack usinjg canvas is that you have to calculate the xPoint in base of the sum of the values in the complete stack.
Here is a example of code
var sumaArr = [];
for (var u = 0; u < p.getData().length; u++) {
$.each(p.getData()[u].data, function (i, el) {
sumaArr[i] > 0 ? sumaArr[i] = sumaArr[i] + el[1] : sumaArr[i] = el[1];
});
}
var ctx = p.getCanvas().getContext("2d");
var data = p.getData()[p.getData().length - 1].data;
var xaxis = p.getXAxes()[0];
var yaxis = p.getYAxes()[0];
var offset = p.getPlotOffset();
ctx.font = "12px 'Segoe UI'";
ctx.fillStyle = "gray";
for (var i = 0; i < data.length; i++) {
var text = sumaArr[i];
var metrics = ctx.measureText(text);
var xPos = (xaxis.p2c(data[i][0]) + offset.left) - metrics.width / 2;
var yPos = yaxis.p2c(sumaArr[i]) + offset.top - 5;
ctx.fillText(text, xPos, yPos);
}
The var yPos use the sume of the values that make the complete stack.
I have just started using jqPlot for a line chart with multiple series. It seems great.
I have added the Cursor plugin with the intention of showing a vertical line on the nearest data point on the x axis. In other words, it snaps to the nearest point. The Cursor plugin, however always shows the vertical cursor right where the mouse is.
It seems like I just want to "override" or replace moveLine to change the current functionality.
What's the most appropriate way of doing so?
It seems a little much to copy/past all of the cursor plugin just to modify a very small subset.
Thanks!
I know I'm a kind of archaeologist by edited this post but I think the following can be useful for someone (I hope).
I've made a piece of code which allow to draw a vertical line following the cursor and displaying a tooltip on the nearest point (according to the cursor). You can find a demo of it on this JSFiddle.
I also post the corresponding code below (only the part which calculate nearest point and display tooltip):
//Show nearest point's tooltip
$("#chart1").bind('jqplotMouseMove', function(ev, gridpos, datapos, neighbor, data){
var c_x = datapos.xaxis;
var index_x = -1;
var pos_index = 0;
var low = 0;
var high = data.data[0].length-1;
while(high - low > 1){
var mid = Math.round((low+high)/2);
var current = data.data[0][mid][0];
if(current <= c_x)
low = mid;
else
high = mid;
}
if(data.data[0][low][0] == c_x){
high = low;
index_x = high;
}else{
var c_low = data.data[0][low][0];
var c_high = data.data[0][high][0];
if(Math.abs(c_low - c_x) < Math.abs(c_high - c_x)){
index_x = low;
}else{
index_x = high;
}
}
//Display marker and tooltip
if(data.series[0].data[index_x]){
var x = data.series[0].gridData[index_x][0];
var y = data.series[0].gridData[index_x][1];
var r = 5;
var highlightCanvas = $(".jqplot-highlight-canvas")[0];
var context = highlightCanvas.getContext('2d');
context.clearRect(0,0,highlightCanvas.width,highlightCanvas.height);
context.strokeStyle = 'rgba(47,164,255,1)';
context.fillStyle = 'rgba(47,164,255,1)';
context.beginPath();
context.arc(x,y,r,0,Math.PI*2,true);
context.closePath();
context.stroke();
context.fill();
//Display tooltip on nearest point
var highlightTooltip = $(".jqplot-highlighter-tooltip");
var val_x = data.data[0][index_x][0];
var val_y = data.data[0][index_x][1];
highlightTooltip.html("X : "+val_x+"<br/>Y : "+val_y);
highlightTooltip.css({'left': x+'px', 'top': (y-10)+'px', 'display': 'block'});
}
});
Feel please to use it and to modify it as you need it.
Try a bar graph series on top of everything else that has alpha set to 0.
I am drawing a set of evenly spaced horizontal lines within the entirety of a bounding box.
The problem I am having is that the lines (when larger than 1px) get drawn beyond the top and bottom edges of my bounds. Half on each side of the top and bottom is missing, to be precise.
Here is some pseudo code that attempts a fix for this, but it didn't work. It should describe what I am trying to do:
var halfline = linewidth / 2.;
var maxheight = boxsize.height - halfline;
var minheight = halfline;
//draw h lines
for(i = 0; i < maxlines; i++)
{
var xloc = 0;
var xfrac = i / maxlines - 1;
var yloc = (xfrac * boxsize.height) + minheight;
move_to(xloc, yloc);
line_to(boxsize.width, yloc);
}
Please keep in mind that the lang is not important here, just the idea of how to offset and scale the lines (that are drawn within the for loop) properly.
Thanks for any tips... It's safe to assume the following:
the line width is in pixels
the coordinate system is pixel-based, from (0,0) to (n,n)
Your question is a little unclear, but I think this might help:
var availablespace = boxsize.height - linewidth;
...
var yloc = (xfrac * availablespace) + minheight;