【问题标题】:flot chart ticks lines not uniform浮动图表刻度线不均匀
【发布时间】:2026-02-09 00:30:01
【问题描述】:

我正在使用 flot 图表来显示心电图信号。要求是图表背景应该看起来与心电图纸完全一样。

所有内部灰色线应在精确点上排列,以便在心电图表上绘制完美的正方形。但是,有些线的间距不均匀(它们彼此更接近),导致心电图背景不正确。

这是我的代码的作用:

标记: 我编写了一个函数来在 x 和 y 轴上生成标记。标记是图表上的深粉色线条。这些标记将在 4 条灰色线之后在 x 和 y 轴上生成(构成较大的深粉色框内的较小灰色方块)。这些似乎是正确绘制的。

蜱: 我通过编写两个在 x 和 y 轴上生成刻度的函数来覆盖 Flot 图表本地刻度生成器。在 x 轴上,每 40 ms 代表一个刻度(一条灰线),在 y 轴上,0.1 毫伏代表一条灰线。即使函数生成具有正确刻度值的正确数组,flot 图表上的刻度间距也不均匀。一些刻度线间隔更近,这是不正确的。

并非所有刻度都绘制不正确。但是,间距不规则的刻度数量很多,并且在更仔细地检查图表时可见。首先,图表的第 4 列和第 4 行有不均匀间隔的刻度线。 (在 jsfiddle 之外的浏览器上,这变成了第 3 行和第 3 列)。这些不均匀的刻度在整个图表中随机重复。

我的代码如下所示。也已上传至JSFiddle

有没有人在绘制刻度线时遇到过类似的浮动图表问题?我是否错误地使用了刻度?感谢您在这方面的帮助。

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


);

【问题讨论】:

    标签: flot


    【解决方案1】:

    很棒的问题。

    这是您的一些蜱:

     [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
    

    以下是您的每个刻度之间的区别:

     [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
    

    这看起来相当不错,漂亮且间隔均匀。在内部,虽然 flot 必须将这些转换为画布坐标。他们在这里:

     [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
    

    还有区别:

     [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
    

    再一次,它看起来非常好,间距仍然很好。

    但是我们遇到了问题,flot 无法在 479.16 处画线。它必须在像素位置绘制,这些是整数值。那么,flot 是做什么的呢?它Math.floors他们。您的“像素位置”变为:

     [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
    

    还有区别:

     [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
    

    现在我们遇到了一个问题,间距不再均匀。

    所以,我的第一反应是,哇哦,这是flot 中的一个错误。但我看不出 flot 如何更好地完成数学运算(并且仍然获得相同的效率)。

    那你怎么解决呢?

    1.) 增加画布的大小。刻度之间的间距更大,您将看不到这里或那里的像素。

    2.) 后勤工作。从像素位置开始并从中计算您的轴位置。如果今晚我有时间,我会尝试这个想法。不会很漂亮。

    编辑

    这是一个均匀间隔刻度的尝试。它依赖于两次绘制绘图,因为我需要初始边界信息来开始间距(是否有边距、刻度标签等......)。它还需要我手动调整占位符 div 的高度,以便所有刻度都适合:

    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];
        }
    },
    

    这是fiddle。我删除了 xaxis 和标记以更好地可视化。

    编辑 2

    所以,这里最重要的部分是地块高度。使用您的原始代码和 510 像素的绘图高度,刻度本身均匀分布。这是差异:

    [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
    

    【讨论】:

    • 嗨,马克,感谢您提供详细且非常合乎逻辑的回复。现在这一切对我来说都是有意义的。你是如何得到画布坐标值的?你能指导我吗?
    • @user3855126,请参阅更新的答案和小提琴。您可以使用轴的 p2c 方法获取画布坐标。相反,c2p 将坐标转换为像素。
    • 非常感谢马克。这是一个很大的帮助。