javascript - d3 : rotations and force directed layouts

标签 javascript d3.js rotation force-layout

当我在 d3 应用程序中使用旋转勾选功能时,整个应用程序速度慢得像爬行一样。

举个例子:如果取消注释行//var angle = 0;在下面jsfiddle它的运行速度快了 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; });
}

注意:我修改了原来的jsfiddle发现here

最佳答案

为了找出问题的根源,我尝试使文本的各个方面相同/不同。请参阅this version of your fiddle 。请注意,每个文本元素的文本不同, Angular 也不同(因此不可能进行优化)每个元素的 Angular 是恒定的 - 它不会在每次刻度时发生变化。

结果呢?一开始有点迟缓(当图形中有很多重叠时),但很快就可以在 30fps 下实现平滑的动画。

即使文本内容每次都发生变化,情况也是如此(最终帧速率略高于 30fps),如 this version 所示。 .

这与the usual rule of optimizing animation相矛盾,改变转换应该比改变内容更有效。

根据 Chrome 帧速率检查器,大部分时间都消耗在 your original fiddle 的每次重绘上。 (在我的计算机上时钟约为 4fps)由“绘画设置”步骤占用 - 即计算图像的每个“层”。

This blog has a quick-and-easy recap of the different steps of a repaint 。引用:

The following steps render the elements in the DOM into images on your screen:

  1. Trigger - Elements are loaded into the DOM, or are modified in some way

  2. Recalculate Styles - Styles are applied to elements (or re-calculated)

  3. Layout - Elements are laid out geometrically, according to their positions on the screen

  4. Paint Setup - The DOM is split up into render layers, which will be used to fill out the pixels for each element

  5. Paint - Each layer is painted into a bitmap and is uploaded to the GPU as a texture by a software rasterizer

  6. Composite Layers - The layers are composited together by the GPU and drawn to a final screen image

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

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

无论幕后发生了什么,最终结果都是您的 CPU(而不是 GPU)每次都计算旋转并将文本分层在一起,而这效率不高。

那么,你能做些什么呢?

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

不幸的是,看起来你真的不得不以某种方式做出妥协。一些选项:

  • 隐藏文本,直到力布局停止,然后才计算旋转。 Working example

    关键代码(Javascript):

    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);
    });
    

    CSS:

    .running text {
        display:none;
    }
    
  • 显示文本,但不旋转它(可以选择在强制布局停止时将其旋转到位,如上所述)。

关于javascript - d3 : rotations and force directed layouts,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23430115/

相关文章:

javascript - Ember CLI + Ember 数据 + 简单验证 : authorize gets not called

php - 使用 JS 和 PHP 裁剪和旋转图像

c - 是否有一个用于 3d 旋转且舍入误差最小的简单 C 库?

d3.js - 读取d3文本元素的宽度

ios - 强制单个 View 处于不同的方向以设置设备方向

javascript - 将 JSON 传递给 Backbone.Marionette View 的模板

javascript - 在 Internet Explorer 中播放 HTML 音频?

javascript - Crockford 原型(prototype)继承

d3.js - 用d3和Leaflet实现动画缩放

javascript - 力向图 - 为什么指针会随着链接宽度的变化而改变大小