在 Cytoscape.js 中动画构建图表

Animate building a graph in Cytoscape.js

您好,我想学习如何在 Cytoscape.js 中制作图表动画。对我来说,这意味着,用户会选择一种布局算法,然后从根节点开始,一条边会从该节点开始生长,最终指向图中下一个节点的方向,然后该节点将从一个小节点开始生长点,这个过程会重复。这最终将最终为正在构建的整个图形设置动画。我认为这与Images and Breadthfirst Layout Demo正好相反。

谁能帮我想出一个策略来做到这一点?我在想我需要用我的节点列表布置一个无头图,并使用这些位置来显示 html 容器中显示的主图中的动画。

感谢您的帮助

如果你在初始化时拥有所有元素,只需将它们全部放入图中即可。您可以让它们最初隐藏在您的样式表中,您可以用动画一个一个地显示它们。

我会使用 .animation() 而不是 .animate(),因为您随后可以使用返回的 animation 对象及其播放承诺。您可以创建一个承诺链作为您的时间线。

这是我最终使用的方法,按照 maxkfranz 的建议使用 play promise,而不是延迟会更好。

/****************************************************************************************************    
 * https://gist.github.com/maxkfranz/aedff159b0df05ccfaa5
 * method will animate the graph building, from parent to child
 * 
 */
animateGraphBuilding = function(nodes){

    var delay = 0;      
    var size = nodes.length;
    var duration = (200000 / size);
    mod = $('#animationSpeed').val()/2;
    if(mod < 1){ 
        mod = 1; 
        $('#animationSpeed').val(mod);
    }else if(mod > 100){
        mod = 100;
        $('#animationSpeed').val(mod);

    }

    duration /= mod;

    var visitedMap = {};//used to ensure nodes are only animated once

    for(var index = 0; index < size; ++index){
        visitedMap[nodes[index].data('id')] = 0;
    }
    var nodesCopy = nodes.clone();//store original rendered positions

    //loop through the list of nodes and then,
    //Find connected nodes and then,
    //loop through connected nodes and animated from parent to original position
    for( var i = 0; i < nodes.length; ++i ){ 
        var cNode = nodes[i];                   
        var nextNodes = cNode.connectedEdges(
                function(){
                    return this.source().same(cNode);
                }
            ).targets();                                                                        

        for (var index = 0; index < nextNodes.length; ++index){
            var nNode = nextNodes[index];

            (function(currentNode, x, copyNode, nextNode){          

                if(nextNode != null && x != 0 && visitedMap[nextNode.data('id')] < 1){
                    ++visitedMap[nextNode.data('id')];
                    //console.log('currentNode: ' + currentNode.data('id')+ ', x: ' + x + ', nextNode: ' + nextNode.data('id') );

                    var position = nextNode.renderedPosition();                 
                    nextNode.renderedPosition(copyNode.renderedPosition());         

                    nextNode.delay( delay, function(){
                        nextNode.style("visibility", "visible");                        
                    } ).animate(    {                   
                            renderedPosition: position //to this position                               
                        }, {
                            duration: duration,
                            complete: function(){/*do nothiing*/}
                        }                                                                   
                    );                  
                }else if (nextNode != null && visitedMap[nextNode.data('id')] < 1){ 

                    ++visitedMap[nextNode.data('id')];
                    var position = nextNode.renderedPosition();                 
                    nextNode.renderedPosition(copyNode.renderedPosition());         

                    nextNode.delay( delay, function(){
                        currentNode.style("visibility", "visible"); //show the root node
                        nextNode.style('visibility', 'visible');                    
                    } ).animate(    {                   
                            renderedPosition: position,//to this position                               
                        }, {
                            duration: duration,
                            complete: function(){/*do nothing*/}                    
                        }                                       
                    );                                          
                }           

                delay += duration;

            })(cNode, i, nodesCopy[i], nNode);                      
        } //end inner for, iterates through children nodes
    } // end of outter for, iterates through all nodes                  
};