flot chart ticks lines not uniform

回眸只為那壹抹淺笑 提交于 2019-12-12 12:13:39

问题


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 + " &ndash; ");
}   


);

回答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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!