如何在 D3.js 中创建一个刻度间隔不相等的轴

How do I create an axis with non-equal tick intervals in D3.js

目前,我有一个带有线性 x 和 y 尺度的基本散点图,用于创建轴,即使用

d3.scaleLinear().domain([0.65, 0.78]).range([0, width])

d3.scaleLinear().domain([0, 1]).range([height, 0])

d3.axisBottom()d3.axisLeft() 一起创建情节。结果图是

我想修改 y 轴,使刻度线之间的间隔不相等,例如[0.01, 0.05, 0.4, 0.5, 0.9, 0.95, 0.99] 同时仍然保持地块的整体大小(高度没有变化)。理想情况下,情节最终应该看起来像这样(忽略最佳拟合线):

我尝试使用 piecewise plotting 将域值映射到特定范围(高度),但这并不完全有效,因为图的高度被修改了。

有没有办法创建一个具有不相等刻度间隔的轴并仍然保持 svg 的原始形状?

根据要求,这是绘图 (x, y) 的数据:

[
    [0.651325, 0.00135],
    [0.763999, 0.99865],
    [0.663976, 0.01],
    [0.669095, 0.02],
    [0.672343, 0.03],
    [0.674786, 0.04],
    [0.676773, 0.05],
    [0.678465, 0.06],
    [0.679948, 0.07],
    [0.681276, 0.08],
    [0.682484, 0.09],
    [0.683596, 0.1],
    [0.684629, 0.11],
    [0.685597, 0.12],
    [0.68651, 0.13],
    [0.687375, 0.14],
    [0.688199, 0.15],
    [0.688987, 0.16],
    [0.689744, 0.17],
    [0.690472, 0.18],
    [0.691176, 0.19],
    [0.691857, 0.2],
    [0.692518, 0.21],
    [0.693161, 0.22],
    [0.693787, 0.23],
    [0.694398, 0.24],
    [0.694996, 0.25],
    [0.695581, 0.26],
    [0.696154, 0.27],
    [0.696717, 0.28],
    [0.69727, 0.29],
    [0.697814, 0.3],
    [0.69835, 0.31],
    [0.698879, 0.32],
    [0.699401, 0.33],
    [0.699916, 0.34],
    [0.700426, 0.35],
    [0.700931, 0.36],
    [0.70143, 0.37],
    [0.701925, 0.38],
    [0.702417, 0.39],
    [0.702904, 0.4],
    [0.703389, 0.41],
    [0.703871, 0.42],
    [0.70435, 0.43],
    [0.704827, 0.44],
    [0.705302, 0.45],
    [0.705776, 0.46],
    [0.706249, 0.47],
    [0.70672, 0.48],
    [0.707191, 0.49],
    [0.707662, 0.5],
    [0.708133, 0.51],
    [0.708604, 0.52],
    [0.709075, 0.53],
    [0.709548, 0.54],
    [0.710022, 0.55],
    [0.710497, 0.56],
    [0.710974, 0.57],
    [0.711453, 0.58],
    [0.711935, 0.59],
    [0.71242, 0.6],
    [0.712907, 0.61],
    [0.713399, 0.62],
    [0.713894, 0.63],
    [0.714393, 0.64],
    [0.714898, 0.65],
    [0.715408, 0.66],
    [0.715923, 0.67],
    [0.716445, 0.68],
    [0.716974, 0.69],
    [0.71751, 0.7],
    [0.718054, 0.71],
    [0.718607, 0.72],
    [0.71917, 0.73],
    [0.719743, 0.74],
    [0.720328, 0.75],
    [0.720926, 0.76],
    [0.721537, 0.77],
    [0.722163, 0.78],
    [0.722806, 0.79],
    [0.723467, 0.8],
    [0.724148, 0.81],
    [0.724852, 0.82],
    [0.72558, 0.83],
    [0.726337, 0.84],
    [0.727125, 0.85],
    [0.727949, 0.86],
    [0.728814, 0.87],
    [0.729727, 0.88],
    [0.730695, 0.89],
    [0.731728, 0.9],
    [0.73284, 0.91],
    [0.734048, 0.92],
    [0.735376, 0.93],
    [0.736859, 0.94],
    [0.738551, 0.95],
    [0.740538, 0.96],
    [0.742981, 0.97],
    [0.746229, 0.98],
    [0.751348, 0.99]
]

我设法找到了某种程度上可行的方法。本质上,我们需要创建一个包含所需刻度值的域,然后手动绘制范围。

例如,想要的地块有域

    [0,
     0.01,
     0.02,
     0.05,
     0.1,
     0.25,
     0.5,
     0.75,
     0.9,
     0.95,
     0.98,
     0.99,
     1] 

我们可以通过遍历域来手动设置我们希望每个刻度线映射到的 y 范围(高度)。

function getYRange(distributionType, yDomain, height) {
    let yRange = [];
    let pointHeight = height; //height of the svg group

    for (let i = 0; i < yDomain.length; i++) {
        yRange.push(pointHeight);
        if (yDomain[i] >= 0.1 && yDomain[i] <= 0.80) {
            delta = 25 + height / yDomain.length;
        } else {
            delta = -10 + height / yDomain.length;
        }
        pointHeight -= delta;
    }

    return yRange;
}

之后,我们只用这个域和范围创建一个刻度,然后用这个域设置的刻度值创建一个轴

const yScale = d3.scaleLinear().domain(yDomain).range(yRange)

const yAxis = d3.axisLeft(yScale).tickValues(yDomain).tickFormat(d3.format('.3f'))

然后调用组元素上的轴,如 g.append("g").call(yAxis)

这具有相应地间隔刻度线并使绘图相对直的预期效果。