Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/392.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何使用d3.js检查元素是否在视点中(在可见区域中)_Javascript_Html_D3.js_Dom - Fatal编程技术网

Javascript 如何使用d3.js检查元素是否在视点中(在可见区域中)

Javascript 如何使用d3.js检查元素是否在视点中(在可见区域中),javascript,html,d3.js,dom,Javascript,Html,D3.js,Dom,我画了大量的元素,在很多情况下,大多数元素都在视点之外 我希望避免在隐藏元素上处理昂贵的旋转变换 下面是一个例子: 此图形中的许多元素都是隐藏的(请尝试缩小以查看)。但目前我必须在每个刻度上渲染每个元素,而且速度慢得令人痛苦 这是我的密码: function transformLinks(svgLinks, nodeRadius, arrowSize) { if (svgLinks) { var link = svgLinks.selectAll('.link').fi

我画了大量的元素,在很多情况下,大多数元素都在视点之外

我希望避免在隐藏元素上处理昂贵的旋转变换

下面是一个例子:

此图形中的许多元素都是隐藏的(请尝试缩小以查看)。但目前我必须在每个刻度上渲染每个元素,而且速度慢得令人痛苦

这是我的密码:

function transformLinks(svgLinks, nodeRadius, arrowSize) {
    if (svgLinks) {
        var link = svgLinks.selectAll('.link').filter(needRedraw);
        //console.log("total:", svgLinks.selectAll('.link').size(), ',needRedraw:', link.size());
        transformLinksLines(link);
        transformLinksTexts(link.selectAll('.text'));
        transformLinksOutlines(link, nodeRadius, arrowSize);
        transformLinksOverlays(link.selectAll('.overlay'));
        link.each(function (n) {
            n.source.lx = n.source.x;
            n.source.ly = n.source.y;
            n.target.lx = n.target.x;
            n.target.ly = n.target.y;
        });
    }
}

function needRedraw(link) {
    if (!link.source) {
        link = link.parentNode;
    }
    return nodeMoved(link.source) || nodeMoved(link.target);
}

var minDistToRedraw = 0.8;
function nodeMoved(n) {
    return utils.isNumber(n.x) && utils.isNumber(n.y)
            && !(utils.isNumber(n.lx) && Math.abs(n.x - n.lx) <= minDistToRedraw && Math.abs(n.y - n.ly) <= minDistToRedraw);
}
函数转换链接(svgLinks、nodeRadius、arrowSize){
如果(svgLinks){
var link=svgLinks.selectAll('.link').filter(needRedraw);
//console.log(“total:”,svgLinks.selectAll('.link').size(),',needRedraw:',link.size());
转换链接线(链接);
transformLinksTexts(link.selectAll('.text'));
transformLinksOutlines(链接、节点半径、箭头大小);
transformLinksOverlays(link.selectAll('.overlay'));
链接。每个(功能(n){
n、 source.lx=n.source.x;
n、 source.ly=n.source.y;
n、 target.lx=n.target.x;
n、 target.ly=n.target.y;
});
}
}
函数needRedraw(链接){
如果(!link.source){
link=link.parentNode;
}
返回nodeMoved(link.source)| nodeMoved(link.target);
}
var MindistoreDraw=0.8;
函数nodeMoved(n){
返回utils.isNumber(n.x)和&utils.isNumber(n.y)

&&!(utils.isNumber(n.lx)和&Math.abs(n.x-n.lx)因为我没有找到任何现成的解决方案,所以我不得不进入坐标转换的领域

首先,我创建了一个函数,将外部容器坐标转换为SVG内部客户机坐标系-containerToSVG()

然后将其应用于.getBoundingClientRect();以获得SVG坐标空间中的可见区域

然后在过滤器中检查两个节点是否超出可见区域-不要重新绘制链接

当两个节点都超出该区域时,可能会出现这种情况,但链路仍然可以穿过该区域。但只要用户看不到链路分离,这并不是什么大问题

代码如下:

function transformLinks(svgLinks, nodeRadius, arrowSize) {
    if (svgLinks) {
        var containerRect = container.node().getBoundingClientRect();
        var p = containerToSVG(-nodeRadius, -nodeRadius);
        var r = containerToSVG(containerRect.width + nodeRadius, containerRect.height + nodeRadius);
        svgVisibleRect = {left: p.x, top: p.y, right: r.x, bottom: r.y};
        minDistToRedraw = (svgVisibleRect.right - svgVisibleRect.left) / (containerRect.width + nodeRadius * 2);
        var link = svgLinks.selectAll('.link').filter(needRedraw);
        transformLinksLines(link);
        transformLinksTexts(link.selectAll('.text'));
        transformLinksOutlines(link, nodeRadius, arrowSize);
        transformLinksOverlays(link.selectAll('.overlay'));
        link.each(function (n) {
            updateLastCoord(n.source);
            updateLastCoord(n.target);
        });
    }
}

function needRedraw(link) {
    if (!nodeMoved(link.source) && !nodeMoved(link.target)) {
        return false;
    }
    return isVisible(link.source) || isVisible(link.target);
}

function nodeMoved(n) {
    return utils.isNumber(n.x) && utils.isNumber(n.y) &&
            !(utils.isNumber(n.lx) && Math.abs(n.x - n.lx) <= minDistToRedraw && Math.abs(n.y - n.ly) <= minDistToRedraw);
}

function isVisible(n) {
    var result = n.x > svgVisibleRect.left && n.x < svgVisibleRect.right &&
            n.y > svgVisibleRect.top && n.y < svgVisibleRect.bottom;
    return result;
}

function updateLastCoord(n) {
    n.lx = n.x;
    n.ly = n.y;
}

function containerToSVG(containerX, containerY) {
    var svgPount = svgNode.createSVGPoint();
    svgPount.x = containerX;
    svgPount.y = containerY;
    return svgPount.matrixTransform(document.getElementById("links-svg").getScreenCTM().inverse());
}

function transformLinksLines(link) {
    link.attr('transform', function (d) {
        var angle = rotation(d.source, d.target);
        return 'translate(' + d.source.x + ', ' + d.source.y + ') rotate(' + angle + ')';
    });

}
函数转换链接(svgLinks、nodeRadius、arrowSize){
如果(svgLinks){
var containerRect=container.node().getBoundingClientRect();
var p=容器ToSvg(-nodeRadius,-nodeRadius);
var r=containerToSVG(containerRect.width+节点半径,containerRect.height+节点半径);
svgVisibleRect={left:p.x,top:p.y,right:r.x,bottom:r.y};
MinDistToDraw=(svgVisibleRect.right-svgVisibleRect.left)/(containerRect.width+nodeRadius*2);
var link=svgLinks.selectAll('.link').filter(needRedraw);
转换链接线(链接);
transformLinksTexts(link.selectAll('.text'));
transformLinksOutlines(链接、节点半径、箭头大小);
transformLinksOverlays(link.selectAll('.overlay'));
链接。每个(功能(n){
更新文件(n.来源);
updateLastCoord(n.target);
});
}
}
函数needRedraw(链接){
如果(!nodeMoved(link.source)和&!nodeMoved(link.target)){
返回false;
}
返回isVisible(link.source)| isVisible(link.target);
}
函数nodeMoved(n){
返回utils.isNumber(n.x)和&utils.isNumber(n.y)&&
!(utils.isNumber(n.lx)和Math.abs(n.x-n.lx)svgVisibleRect.top和n.y
也许可以帮助您开始。您需要
输入
退出
d3选择中基于某些条件的数据(可能是它们的坐标是否在当前svg框内)不要在force sim卡的每个刻度上更新,如果(++计数器%10!=0),请保留一个计数器,
return;counter=0;
您可以简化节点创建,一个
圆圈
具有不同的填充和笔划颜色和宽度,并且只有一个工具提示文本,设置一个类以通过CSS控制这一点。对于不同的情况,
*
CSS选择器需要应用于svg元素(在您自己的CSS和引导CSS中)?谢谢@rioV8的建议