d3.js 有没有一种方法可以在保留工具提示显示的“实际”值的同时,在轴的最大/最小值处限制“显示”值?

lkaoscv7  于 2023-04-30  发布在  其他
关注(0)|答案(2)|浏览(75)

你们中的大多数人可能不记得我之前的问题了,Circles not updating correctly for multiline charts with two-level nested data。我设法解决了我的问题(尽管我仍然不相信我提出的是100%正确的);不过,我现在有另一个问题。
我的数据有极端的离群值。结果,我的图表被压缩了,有相当多的空白空间。例如,请参见JSFiddle中的“现金流”图表:https://jsfiddle.net/etonblue/a98m52k4/3/。我尝试了各种组合的中位数,平均值,平均值,标准差,等等。,尝试设置域,但还没有找到一个对我的所有数据都一致有效的解决方案。所以我采取了硬编码我的域:

if (val == 1) {ydom = [-2,20]}
        else if (val == 2) {ydom = [-40,240]}
        else if (val == 3) {ydom = [-.5,1.5]}
        else if (val == 4) {ydom =  [-.6,.9]}
        else if (val == 5) {ydom = [-.6,.6]}
        else if (val == 6) {ydom = [-.16,.16]}
        else if (val == 7) {ydom = [-.5,3]}
        else if (val == 8) {ydom = [-1000000,2000000]}
        else if (val == 9) {ydom = [-1000000,2000000]}
        else if (val == 10) {ydom = [-4,10]}

这不仅是丑陋的,它还意味着任何极端值现在要么远高于或远低于我显示的y轴。
我的问题是,有没有一种方法可以使用D3将显示的值限制在域的最大值/最小值,同时保留实际值(以便工具提示显示实际值而不是显示值)?
我现在正在使用d3。v4。

更新根据下面的答案,我修改了我的线函数(和我的“cy”属性函数的圆圈):

var line = d3.line()
    .x(d => x(d.year))
    .y(function(d) {
        val = document.querySelector('input[name="button"]:checked').value;
        if (val == 1) { if (d.mval < -2) {return y(-2)} else if (d.mval > 20) {return y(20)} else {return y(d.mval)}}
        else if (val == 2) { if (d.mval < -40) {return y(-40)} else if (d.mval > 240) {return y(240)} else {return y(d.mval)}}
        else if (val == 3) { if (d.mval < -.5) {return y(-.5)} else if (d.mval > 1.5) {return y(1.5)} else {return y(d.mval)}}
        else if (val == 4) { if (d.mval < -.6) {return y(-.6)} else if (d.mval > .9) {return y(.9)} else {return y(d.mval)}}
        else if (val == 5) { if (d.mval < -.6) {return y(-.6)} else if (d.mval > .6) {return y(.6)} else {return y(d.mval)}}
        else if (val == 6) { if (d.mval < -.16) {return y(-.16)} else if (d.mval > .16) {return y(.16)} else {return y(d.mval)}}
        else if (val == 7) { if (d.mval < -.5) {return y(-.5)} else if (d.mval > 3) {return y(3)} else {return y(d.mval)}}
        else if (val == 8) { if (d.mval < -1000000) {return y(-1000000)} else if (d.mval > 2000000) {return y(2000000)} else {return y(d.mval)}}
        else if (val == 9) { if (d.mval < -1000000) {return y(-1000000)} else if (d.mval > 2000000) {return y(2000000)} else {return y(d.mval)}}
        else if (val == 10) { if (d.mval < -4) {return y(-4)} else if (d.mval > 10) {return y(10)} else {return y(d.mval)}}
    })

Fiddle更新:https://jsfiddle.net/etonblue/xwbkz98m/23/。在更新后的fiddle中可以看到,有9个单选按钮。变量“瓦尔”标识活动单选按钮,该按钮确定当前活动的域,从而确定要检查的限制。
如果我理解正确的话,我认为你的更新答案会导致更干净的代码。我会努力把它纳入。
然而,我现在注意到另一个问题,可能需要一个单独的问题,因为我怀疑它与我的更新功能有关。如果您点击“年度入学率变化%”功能,您可以在图表底部看到两条绿色线(没有圆点),这两条绿线显然是“流动比率”图表遗留下来的。总是有事。

yhxst69z

yhxst69z1#

您提供的代码与解决方案不太相关。从你的小提琴上工作,解决方案是在你的线和圆的y位置回调。对于您的产品线:

var line = d3.line()
    .x(d => x(d.year))
    .y(d =>  d.mval > 240 ? y(240) : y(d.mval)) //If mval is over 240 plot 240

同样对于你的圈子cy:

.attr('cy', d =>  d.mval > 240 ? y(240) : y(d.mval))

一般来说,你可以使用callback:

d => d.mval > y.domain()[1] ? y(y.domain()[1]) : y(d.mval)

我不明白你的安排,

ego6inou

ego6inou2#

d3刻度不只是clamp()选项吗?这将停止domain --〉range转换超过范围的最小值/最大值。
https://github.com/d3/d3-scale#continuous_clamp

相关问题