问题
I am using flot charts to display ecg signals. The requirement is that the chart background should look exactly like the ecg graph paper.
All the inner grey lines should be lined at precise points to draw perfect squares on the ecg sheet. However, there are some lines which are not spaced evenly (they are closer to each other), making the ecg graph background incorrect.
Here is what my code does :
MARKINGS : I have written a function to generate markings on x and y axis. Markings are the dark pink lines on the graph. These markings will be generated on x and y axis after 4 grey lines (which make up the smaller grey squares inside the bigger dark pink boxes). These seem to be drawn correctly.
TICKS: I have overridden Flot charts native tick generator by writing two functions which generate ticks on x and y axis . On x axis, each 40 ms represents one tick (one grey line) and on y axis 0.1 millivolt represents one grey line. Even though the functions generate correct arrays with correct values for ticks, the tick spacing on flot chart is not even. Some tick lines are more closely spaced which is incorrect.
Not all ticks are drawn incorrectly.However, the ones that have irregular spacing are significant in number and are visible on more careful inspection of the graph. For a start, the 4 th column and row of the graph has unevenly spaced tick lines. (On browser outside of jsfiddle, this becomes 3rd row and 3rd column ). These uneven ticks repeat randomly throughout the graph.
My code is as shown below. It has also been uploaded at JSFiddle
Has anyone gone through similar problem with flot charts while drawing tick lines? Am I using ticks incorrectly? Appreciate your help on this.
JavaScript:
$(function() {
var d2=[];
// Make markings on x and y axis for drawing the more spaced grid lines
function markingsArray(axes) {
var markings = [];
for (var x = 200; x < axes.xaxis.max; x += 200)
markings.push({ xaxis: { from: x, to: x },color: "#EE1983" });
for (var y = -5; y < axes.yaxis.max; y += 0.5)
markings.push({ yaxis: { from: y, to: y },color: "#EE1983" });
return markings;
}
var options = {
series: {
shadowSize: 0, // Drawing is faster without shadows
lines: {
lineWidth: 1,
}
},
yaxis: {
ticks: function(axis){
var res = [];
var tickDrawCounter = 1;
var tickIncrement=0.1;
for(var i=-4.9;i<5;i+=tickIncrement){
if(tickDrawCounter<5){
res.push([parseFloat(i).toFixed(1),""]);
tickDrawCounter++;
}else{
tickDrawCounter=1;
}
}
return res;
},
min: -5,
max: 5
},
xaxis: {
ticks: function(axis) {
var res = [];
var tickDrawCounter = 1;
var tickIncrement=40;
for(var i=tickIncrement;i<8000;i+=tickIncrement){
if(tickDrawCounter<5){
res.push([parseFloat(i),""]);
tickDrawCounter++;
}else
tickDrawCounter=1;
}
return res;
},
min:0,
max:8000,
},
colors: ["#0000A0"], // color of the series plot
grid:{
markings: markingsArray,
backgroundColor:"pink",
markingsLineWidth:1,
}
}
$.plot("#placeholder",[ d2],options);
// Add the Flot version string to the footer
$("#footer").prepend("Flot " + $.plot.version + " – ");
}
);
回答1:
Awesome question.
Here's some of your ticks:
[1] -4.9 -4.8 -4.7 -4.6 -4.4 -4.3 -4.2 -4.1 -3.9 -3.8 -3.7 -3.6 -3.4 -3.3 -3.2
[16] -3.1 -2.9 -2.8 -2.7 -2.6 -2.4 -2.3 -2.2 -2.1 -1.9 -1.8 -1.7 -1.6 -1.4 -1.3
And here's the difference between each of your ticks:
[1] 0.1 0.1 0.1 0.2 0.1 0.1 0.1 0.2 0.1 0.1 0.1 0.2 0.1 0.1 0.1 0.2 0.1 0.1 0.1
[20] 0.2 0.1 0.1 0.1 0.2 0.1 0.1 0.1 0.2 0.1 0.1 0.1 0.2 0.1 0.1 0.1 0.2 0.1 0.1
That looks pretty good, nice and evenly spaced. Internally though flot has to convert these to canvas coordinates. Here they are:
[1] 479.16 474.32 469.48 464.64 454.96 450.12 445.28 440.44 430.76 425.92
[11] 421.08 416.24 406.56 401.72 396.88 392.04 382.36 377.52 372.68 367.84
And the diff:
[1] -4.84 -4.84 -4.84 -9.68 -4.84 -4.84 -4.84 -9.68 -4.84 -4.84 -4.84 -9.68
[13] -4.84 -4.84 -4.84 -9.68 -4.84 -4.84 -4.84 -9.68 -4.84 -4.84 -4.84 -9.68
Again that looks pretty damn good, still nicely spaced.
BUT we got a problem, flot
can't draw a line at 479.16. It has to draw at pixel positions and those are integer values. So, what does flot do? It Math.floors
them. Your "pixel positions" become:
[1] 479 474 469 464 454 450 445 440 430 425 421 416 406 401 396 392 382 377 372
[20] 367 358 353 348 343 333 329 324 319 309 304 300 295 285 280 275 271 261 256
And the diff:
[1] -5 -5 -5 -10 -4 -5 -5 -10 -5 -4 -5 -10 -5 -5 -4 -10 -5 -5 -5
[20] -9 -5 -5 -5 -10 -4 -5 -5 -10 -5 -4 -5 -10 -5 -5 -4 -10 -5 -5
[39] -5 -9 -5 -5 -5 -10 -4 -5 -5 -10 -5 -4 -5 -10 -5 -5 -4 -10 -5
Now we have a problem, no more even spacing.
So, my first instinct is to say, whoa, this is a bug in flot. But I can't see how flot can do the math any better (and still get the same efficiency).
So how do you fix it?
1.) Increase the size of the canvas. More spacing between the ticks and you won't be able to see a pixel off here or there.
2.) Work backworks. Start with pixel positions and calculate your axis positions from them. If I get some time tonight I'll try out that idea. It won't be pretty.
EDITS
Here's an attempt to evenly space ticks. It relies on drawing the plot twice since I need the initial bounds information to start the spacing (is there a margin, tick labels, etc...). It also required me to manually tweak the placeholder div height so all the ticks will fit:
ticks: function(axis){
var startTickPos = -4.9;
var endTickPos = 5;
var tickIncrement = 0.1;
var tickDrawCounter = 2;
if (plot) {
// this is the re-draw
var yaxis = plot.getAxes().yaxis;
// our first tick's pixel position
var currentTickPix = yaxis.p2c(yaxis.ticks[0].v);
var ticks = [[startTickPos,""]];
for(var i=startTickPos + tickIncrement;
i<endTickPos;
i+=tickIncrement){
// we are spacing each tick 5 pixels apart, adjust as needed for get a good plot height
currentTickPix -= 5;
if(tickDrawCounter<5){
// convert the pixel to tick position
ticks.push([yaxis.c2p(currentTickPix),""]);
tickDrawCounter += 1;
} else {
tickDrawCounter = 1;
}
}
return ticks;
} else {
// this is the first time through, we only need the initial tick's starting position
return [startTickPos];
}
},
Here's a fiddle. I remove the xaxis and markings to better visualize.
EDIT 2
So, it turns out the most important part here is the plot height. With your original code and a plot height of 510 pixels, the ticks space evenly all by themselves. Here's the diff:
[1] -5 -5 -5 -10 -5 -5 -5 -10 -5 -5 -5 -10 -5 -5 -5 -10 -5 -5 -5
[20] -10 -5 -5 -5 -10 -5 -5 -5 -10 -5 -5 -5 -10 -5 -5 -5 -10 -5 -5
[39] -5 -10 -5 -5 -5 -10 -5 -5 -5 -10 -5 -5 -5 -10 -5 -5 -5 -10 -5
[58] -5 -5 -10 -5 -5 -5 -10 -5 -5 -5 -10 -5 -5 -5 -10 -5 -5 -5 -10
[77] -5 -5 -5
来源:https://stackoverflow.com/questions/25920108/flot-chart-ticks-lines-not-uniform