javascript - 调整组的比例以确保内部形状在 d3 js 中尽可能大

标签 javascript svg d3.js logic

我正在使用类似于此示例的 d3 树布局:http://bl.ocks.org/mbostock/4339083

我实现了一个搜索框,当您输入时,它会将您的屏幕居中于所有适当节点的虚拟“平均”位置。

Searching for a term bolds and centers item

我想调整比例,这样选中的节点就会

  1. 全部可见
  2. 尽可能放大。

如果搜索匹配恰好为 1,则模拟点击节点,否则以该虚拟位置为中心。

    if (matches[0].length === 1) {
        click(matches.datum(), 0, 0, false);
    }
    else {
        var position = GetAveragePosition(matches);

        centerToPosition(position.x, position.y, 1);
    }

这是 centerToPosition 函数的样子:

function centerToPosition(x0, y0, newScale) {

    if (typeof newScale == "undefined") {
        scale = zoomListener.scale();
    }
    else {
        scale = newScale;
    }
    var x = y0 * -1; //not sure why this is.. but it is
    var y = x0 * -1;
    x = x * scale + viewerWidth / 2;
    y = y * scale + viewerHeight / 2;
    d3.select('g').transition()
        .duration(duration)
        .attr("transform", "translate(" + x + "," + y + ")scale(" + scale + ")");
    zoomListener.scale(scale);
    zoomListener.translate([x, y]);
}

那么我该如何计算新比例呢?我通过获取数据点的范围尝试了不同的变体

        var xExtent = d3.extent(matches.data(), function (d) {
            return d.x0;
        });
        var yExtent = d3.extent(matches.data(), function (d) {
            return d.y0;
        });

还尝试在将屏幕居中之前查看组的变换属性。

var components = d3.transform(svgGroup.attr("transform"));

我会尽快添加一个 js fiddle ! 编辑:这是:http://jsfiddle.net/7SJqC/

最佳答案

有趣的项目。

确定适合点集合的适当比例的方法相当简单,尽管我花了很长时间才弄清楚为什么它对我不起作用——我没有意识到这个事实(因为你是水平绘制树)树布局中的“x”代表垂直位置,“y”代表水平位置,所以我得到的结果显然是任意的。

清除后,要确定缩放比例,您只需找到要显示的区域的高度和宽度(以数据坐标表示),并将其与视口(viewport)(或其他任何内容)的高度和宽度进行比较你原来的最大和最小尺寸是)。

ScaleFactor = oldDomain / newDomain

一般情况下,您不想扭曲具有不同水平和垂直比例的图像,因此您分别计算出宽度和高度的比例因子并取最小值(因此整个区域将适合视口(viewport))。

可以使用d3数组函数算出每个方向的位置范围,然后找到范围的中间加上最大值和最小值并除以二。

        var matches = d3.selectAll(".selected");

        /*...*/

        if ( matches.empty() ) { 
            centerToPosition(0, 0, 1); //reset
        }
        else if (matches.size() === 1) {
            click(matches.datum(), 0, 0, false);
        }
        else {
            var xExtent = d3.extent(matches.data(), function (d) {
                return d.x0;
            });
            var yExtent = d3.extent(matches.data(), function (d) {
                return d.y0;
            });

            //note: the "x" values are used to set VERTICAL position,
            //while the "y" values are setting the HORIZONTAL position

            var potentialXZoom = viewerHeight/(xExtent[1] - xExtent[0] + 20);
            var potentialYZoom = viewerWidth/(yExtent[1] - yExtent[0] + 150);
            //The "20" and "150" are for height and width of the labels
            //You could (should) replace with calculated values 
            //or values stored in variables

            centerToPosition( (xExtent[0] + xExtent[1])/2,
                              (yExtent[0] + yExtent[1])/2,
                             Math.min(potentialXZoom, potentialYZoom)
            );
        }

http://jsfiddle.net/7SJqC/2/

关于javascript - 调整组的比例以确保内部形状在 d3 js 中尽可能大,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22391074/

相关文章:

html - CSS HTML 将 div 固定在父图像中的某个点上

javascript - 如何通过从下拉列表中进行选择来启动 Sunburst 中的可缩放性

javascript - d3 可重复使用的直方图

如果再次单击,javascript 不会 .toggleClass() 吗?

html - 如何填充SVG图像

jquery - SVG 路径悬停填充背景。领土计划非常先进

d3.js - 我如何格式化d3图中显示的值

javascript - 在嵌套对象上设置属性时设置空对象并返回空对象

javascript - 是否可以将过滤器应用于特定维度?

javascript - 父级 div 阻碍了子级的焦点