Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/109.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:旋转和力导向布局_Javascript_D3.js_Rotation_Force Layout - Fatal编程技术网

Javascript d3:旋转和力导向布局

Javascript d3:旋转和力导向布局,javascript,d3.js,rotation,force-layout,Javascript,D3.js,Rotation,Force Layout,当我在d3应用程序中使用旋转勾选功能时,整个应用程序的速度会减慢为爬行 例如:如果取消注释行//var angle=0;在下面的例子中,它的运行速度提高了20倍 为什么会这样?旋转是非常昂贵还是我做错了什么 function tick() { link.attr("x1", function(d) { return d.source.x; }) .attr("y1", function(d) { return d.source.y; }) .attr("x2", fu

当我在d3应用程序中使用旋转勾选功能时,整个应用程序的速度会减慢为爬行

例如:如果取消注释行//var angle=0;在下面的例子中,它的运行速度提高了20倍

为什么会这样?旋转是非常昂贵还是我做错了什么

function tick() {
  link.attr("x1", function(d) { return d.source.x; })
      .attr("y1", function(d) { return d.source.y; })
      .attr("x2", function(d) { return d.target.x; })
      .attr("y2", function(d) { return d.target.y; });

  linktext.attr("transform", function(d) {
      var xDiff = d.source.x - d.target.x; 
      var yDiff = d.source.y - d.target.y; 
      var angle = Math.atan2(yDiff, xDiff) * (180.0 / Math.PI);
      //var angle = 0;

      return "translate(" + (d.source.x + d.target.x) / 2 + ","
      + (d.source.y + d.target.y) / 2 + ")rotate(" + angle + ")"; 
    });

  node.attr("cx", function(d) { return d.x; })
      .attr("cy", function(d) { return d.y; });
}

注意:当您执行
//var angle=0时,我修改了找到的原始JSFIDLE此代码的编译器可能会意识到结果是无意义的,并进行了优化,因为它从未更改。这就解释了为什么它在注释代码时运行速度要快20倍

我怀疑,即使保留了平移部分并删除了旋转,它也会变慢(尽管平移的计算成本明显低于旋转,因为与旋转相比,平移只需要3个加法)


虽然我对d3.js不太熟悉,但您现在似乎正在执行一个函数中的平移和旋转,该函数可能会在cpu上被多次调用。(通常你会希望通过一个着色器在gpu上实现这一点,但我不确定这是否适用于d3.js)。

为了找出问题的根源,我尝试了使文本的各个方面相同/不同。看见请注意,每个文本元素的文本不同,角度也不同(因此不可能进行优化),但每个元素的角度是恒定的——不会在每个刻度上都改变

结果如何?刚开始有点迟钝(当图形中有很多重叠时),但它很快就会在30帧/秒以下平滑动画

即使文本内容在每一个滴答声中都会发生变化,情况也是如此(最终帧速率略高于30fps),如中所示

这与改变转换应该比改变内容更有效这一观点相矛盾

根据Chrome frame rate inspector,每次重新绘制(在我的计算机上时钟为4fps左右)所消耗的大部分时间都被“绘制设置”步骤占用,即计算图像的每个“层”

。引述:

以下步骤将DOM中的元素渲染为屏幕上的图像:

  • 触发器-元素被加载到DOM中,或者以某种方式被修改

  • 重新计算样式-样式应用于图元(或重新计算)

  • 布局-元素根据其在屏幕上的位置进行几何布局

  • 绘制设置-DOM被分割为渲染层,用于填充每个元素的像素

  • 绘制-每一层都被绘制成位图,并通过软件光栅化器作为纹理上传到GPU

  • 合成层-这些层由GPU合成在一起,并绘制成最终屏幕图像

  • 通常,GPU可以在最后的“合成”步骤中高效地完成转换(现代操作系统上的现代浏览器会自动将工作转移到GPU)

    有两个原因导致这种情况可能不会发生。首先,这种优化甚至可能不适用于SVG(尽管我很确定最新Chrome的默认设置是优化SVG转换)。但是,即使浏览器对SVG转换使用了一些GPU优化,您的GPU也只能处理有限数量的层,否则就会耗尽内存。有近200个单独转换的文本元素(以及上面和下面分层的未转换内容),这可能是一个瓶颈。请参阅或,其中给出了一些性能限制的示例,这些限制将抵消独立的层组成

    不管引擎盖下发生了什么,最终的结果是你的CPU,而不是GPU,每次都在计算旋转并将文本分层,这是没有效率的

    那么,你能做些什么呢?

    我尝试通过使用矩阵变换来优化代码,而不是先计算角度,然后让浏览器计算旋转()…但这并没有产生明显的差异。更改为简单的倾斜变换而不是旋转有一点帮助(帧速率高达11fps),但这只是在滞后的动画上添加了难看的文本

    不幸的是,看来你真的要以这种或那种方式妥协了。一些选择:

    • 隐藏文本,直到强制布局停止,然后才计算旋转

      关键代码(Javascript):

      CSS:

    • 显示文本,但不要旋转它(可选地,在强制布局停止时将其旋转到位,如上所述)


    这里没有那么糟糕(Chrome),但有一个明显的区别。但是,你对此无能为力——文本的旋转非常昂贵,因为它不是一个简单的形状。但它似乎与单个文本旋转的处理更相关,因为如果你将角度设置为非零,它仍然非常快。
    var vis = d3.select(".intgraph").append("svg:svg")
        .attr("width", w)
        .attr("height", h)
        .append("svg:g")
       .on("click", function(){
           if ( force.alpha() )
               force.stop();
           else
               force.resume();
       });
    
    force.on("start", function(){
            vis.classed("running", true);
         })
    .on("end", function () {
        linktext.attr("transform", function (d) {
            var xDiff = d.source.x - d.target.x,
                xMid = d.source.x - xDiff / 2;
            var yDiff = d.source.y - d.target.y,
                yMid = d.source.y - yDiff / 2;
            var hyp = Math.sqrt(xDiff * xDiff + yDiff * yDiff),
                cos = xDiff / hyp,
                sin = yDiff / hyp;
            return "matrix(" + 
                [cos, sin, -sin, cos, xMid, yMid] + ")";
        });
        vis.classed("running", false);
    });
    
    .running text {
        display:none;
    }