最小化/限制d3库中的动画功能

时间:2017-09-20 10:15:17

标签: javascript animation d3.js

我一直在尝试减少我正在处理的d3项目中的动画量。

到目前为止,我尝试使用各种内置函数来抑制动画的力量。例如alpha(.1) gravity(1) charge(-1000)虽然其中一些功能似乎没有产生巨大的差异。

最终结果: 我想尝试消除动画开始时的巨大反弹。这可能吗?

这是我的完整js功能:

// return data for relationships between database tables
returnTableRelationshipData = function(){

    data = {  
       "nodes":[  
          {  
             "platform":"Source DB",
             "description":"RELATIONSHIPS BETWEEN BUSINESS REFERENCES",
             "ingested":"No",
             "tableId":"RELAC_REFER",
             "level1":"DAEG",
             "level2":"url",
             "nodeId":0
          },
          {  
             "platform":"Source DB",
             // see jsfiddle for full data
       ]
    };

    //find the node index
    function find(f){
      var i = -1
        data.nodes.forEach(function(node, index){
            if(node.nodeId == f)
                i = index;
        });
        return i;
    }

    //set the source and target index
    data.links.forEach(function(d){
        d.source = find(d.source);
        d.target = find(d.target);
    })
    // used to store the number of links between two nodes. 
    var mLinkNum = {};

    // sort links first
    sortLinks();                                

    // set up linkIndex and linkNumer, because it may possible multiple links share the same source and target node
    setLinkIndexAndNum();

    // check that we don't have empty or null values
    checkDataNotEmpty();

    var w = 600,
        h = 500;

    var force = d3.layout.force()
        .nodes(data.nodes)
        .links(data.links)
        .alpha(.1)
        .gravity(1)
        //.distance(150)
        .charge(-1000)
        .size([w, h])
        .start();

    var svg = d3.select(".graphContainer").append("svg:svg")
        .attr("width", w)
        .attr("height", h);

    var path = svg.append("svg:g")
        .selectAll("path")
        .data(force.links())
        .enter().append("line")
        .attr("class", "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;
        });

    var node_drag = d3.behavior.drag()
        .on("dragstart", dragstart)
        .on("drag", dragmove)
        .on("dragend", dragend);

    var circle = svg.append("svg:g")
        .selectAll("circle")
        .data(force.nodes())
        .enter().append("svg:circle")
        .attr("r", 6)
        .call(node_drag);

    var text = svg.append("svg:g")                                
        .selectAll("g")
        .data(force.nodes())
        .enter().append("svg:g");

    text.append("svg:text")
        .text(function(d){ return d.description; });

    /*circle.on("mousedown", function(d) { d.fixed = true; });*/

    force.on("tick", tick);

    function tick() {

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

        circle.attr("transform", function(d){
            return "translate(" + d.x + "," + d.y + ")";
        });

        text.attr("transform", function(d){
            return "translate(" + d.x + "," + d.y + ")";
        });
    }

    function dragstart(d, i) {
        force.stop(); // stops the force auto positioning before you start dragging
    }

    function dragmove(d, i) {
        d.px += d3.event.dx;
        d.py += d3.event.dy;
        d.x += d3.event.dx;
        d.y += d3.event.dy;
        tick();
    }

    function dragend(d, i) {
        //nodes.fixed = true; // fix all nodes after single drag
        d.fixed = true; // of course set the node to fixed so the force doesn't include the node in its auto positioning stuff
        tick();
        force.resume();
    }

    // sort the links by source, then target
    function sortLinks(){
        if(data.links != null){                         
            data.links.sort(function(a,b){
                if(a.source > b.source){
                    return 1;
                }else if(a.source < b.source){
                    return -1;
                }else{
                    if(a.target > b.target){
                        return 1;
                    }if(a.target < b.target){
                        return -1;
                    }else{
                        return 0;
                    }
                }
            });
        }
    }

    //any links with duplicate source and target get an incremented 'linknum'
    function setLinkIndexAndNum(){                              
        for(var i = 0; i < data.links.length; i++){
            if(i != 0 &&
                data.links[i].source == data.links[i-1].source &&
                data.links[i].target == data.links[i-1].target){
                data.links[i].linkindex = data.links[i-1].linkindex + 1;
            }else{
                data.links[i].linkindex = 1;
            }// save the total number of links between two nodes
            if(mLinkNum[data.links[i].target + "," + data.links[i].source] !== undefined){
                mLinkNum[data.links[i].target + "," + data.links[i].source] = data.links[i].linkindex;
            }else{
                mLinkNum[data.links[i].source + "," + data.links[i].target] = data.links[i].linkindex;
            }
        }
    }

    function checkDataNotEmpty(){
        data.links.forEach(function(link, index, list) {
            if (typeof link.source === 'undefined') {
                console.log('undefined link', data.nodes[link.source]);
            }
            if (typeof link.target === 'undefined') {
                console.log('undefined source', data.nodes[link.target]);
            }
        });
    }
}

returnTableRelationshipData();

链接到jsfiddle

我尝试将原始代码与SO问题here合并,并链接了jsbin here

我设法将未分类的库发布到pastebin,然后将其链接到jsfiddle,以供参考,这里是完整的js库:Unminified d3 Library v3

看起来好像动画功能从第5807行开始

var d3_ease_default = function() { return d3_identity; };

我已经尝试评论了很多这些功能,动画似乎没有变化。

我意识到这不是最好的问题,但如果有人有这方面的经验,我会非常感激。

此外,我很高兴使用固定节点,但我认为它们只能在强制动画完成后修复。

2 个答案:

答案 0 :(得分:3)

这种巨大反弹的原因之一是所有节点都在同一位置开始模拟。

尝试传播它们:

data.nodes.forEach(function(node){
    node.x = 200 + Math.random()*200;
    node.y = 150 + Math.random()*200;
}

此处,幻数200150只是w/2h/2减去100

这是更新的小提琴:https://jsfiddle.net/nd8e5m9s/

答案 1 :(得分:1)

你强制dgendlay在dragend上强制到某个坐标点并让它反弹,为什么不删除

function dragend(d, i) {
    //nodes.fixed = true; // fix all nodes after single drag
    d.fixed = true; // of course set the node to fixed so the force doesn't include the node in its auto positioning stuff
    tick();
    //force.resume();
}