Javascript D3 v6:如何按所选线段缩放堆叠条以仅拉伸所选线段并收缩其余线段(并保持初始图表宽度)?

Javascript D3 v6:如何按所选线段缩放堆叠条以仅拉伸所选线段并收缩其余线段(并保持初始图表宽度)?,javascript,d3.js,Javascript,D3.js,我的水平堆叠条有问题 问题:有时我得到的值非常小,所以其中一个频带段(子频带?)的宽度非常小。(请看下面的图片,我称之为每种颜色的矩形部分): 在某些情况下,我甚至看不到图表上的这一部分。将来,我希望在每个段上显示文本(百分比值)。但由于段的宽度可能太小,我需要一个显示文本的解决方案 可能的解决方案:首先,我想设置最小段宽度。但在这之后,这张图表看起来就不好了。我还试着玩xScale: const maxX = 1.4; // this value selected experimentall

我的水平堆叠条有问题

问题:有时我得到的值非常小,所以其中一个频带段(子频带?)的宽度非常小。(请看下面的图片,我称之为每种颜色的矩形部分):

在某些情况下,我甚至看不到图表上的这一部分。将来,我希望在每个段上显示文本(百分比值)。但由于段的宽度可能太小,我需要一个显示文本的解决方案

可能的解决方案:首先,我想设置最小段宽度。但在这之后,这张图表看起来就不好了。我还试着玩xScale:

const maxX = 1.4; // this value selected experimentally
const xScale = d3.scaleLinear().range([ 0, width ]).domain([ 0, maxX ]);
但对于某些情况,段仍然太小(请看第三段,我用蓝色标记了它)

所以现在我选择的解决方案是按选定的线段缩放堆叠的条形图。例如,我想缩放红色部分,图表上的所有红色部分都应该拉伸,其余部分应该收缩。和带的总宽度应相同(与初始宽度相同)。所以图表的宽度应该是相同的

这是我的代码示例:

这里的问题是我不能正确地只缩放选定的线段。我尝试检测当前的一组段:

const currentNode = d3.select(event.sourceEvent.target).node();
const currentGroup = d3.select(currentNode.parentNode).node();
然后我尝试只重新缩放与
currentGroup
相关的部分:

group.selectAll("rect.segment")
                // .attr("transform", event.transform.toString())
                .attr("x", (d, i, n) => {
                    if (n[i].parentNode === currentGroup) {
                        return xScale(d[0]) + PADDING_TO_SHOW_TEXT;
                    }
                    return xScale2(d[0]) + PADDING_TO_SHOW_TEXT;
                })
                .attr("width", (d, i, n) => {
                    if (n[i].parentNode === currentGroup) {
                        return xScale(d[1]) - xScale(d[0])
                    }

                    return xScale2(d[1]) - xScale2(d[0])
                });
但实际上,并非来自
currentGroup
的所有段都保持其宽度,并且所选组拉伸过多,因此它移到了轴的外部(实际上在这之后,我改变了图表的宽度)

问题:如何修正缩放以只允许选定的组拉伸和组的其余部分收缩(并保持图表的初始宽度)

额外问题:是否存在其他方法来按比例显示分段,即使某些分段的值太小


更新:我在typescript上的初始项目,所以我忘了删除一些ts提示,这是一个稍微更新的示例:(从注释代码中删除了ts)

好吧,最后我实现了我想要的

结果:

详细信息:首先,我决定删除第二个刻度,因为我只在运行时需要它。因此,我的缩放功能更改为:

d3.zoom().scaleExtent([ 1, 10 ])
        // I am not sure if I need the line below since code works same without it
        // I think below is default value

        //.translateExtent([ [ 0, 0 ], [ width, height ] ])
        .on("zoom", (event) => {

            const transform = event.transform;

            // the new scale I use for runtime
            // the important part here is clamp method. It prevents from moving
            // segments outside of axis
            const newScaleX = transform.rescaleX(xScale).clamp(true);

            // so I just applied new scale to current axis
            xAxis.scale(newScaleX)
            svg.select("g.axis-x").call(xAxis);

            svg.selectAll("rect.segment")
                .attr("x", (d) => newScaleX(d[0]))
                .attr("width", (d) => newScaleX(d[1]) - newScaleX(d[0]));
        })

    svg.call(zoom);

我还从css中删除了
rect
transform,并在代码中添加了剩余的边距。但我认为我会把它归还,因为原生CSS速度更快。

尽管文章的年龄,效果仍然很酷:-也许有些事情要考虑。FYI,Calk(True)也应该设置在原点XStand上: