【问题标题】:Animate DOM movement of SVG groupingsSVG 分组的动画 DOM 移动
【发布时间】:2015-10-30 19:45:18
【问题描述】:

我有 10 个节点的 d3 布局,结构如下...

<body>
    <svg id="mainSvg" style="position: relative" width="1200" height = "1200">
        <g>
            <svg width = "800" height="800>
                <g class="nodeGroupSVG" transform=translate(someXValue,someYValue) scale(someScaleValue)
                    <g class="node" transform=translate(someXValue,someYValue)>
                        <circle>
                        <text>
                    </g>
                    //9 more of these individual node groupings
                </g>
            </svg>
        </g>
        <g class="gToMoveTo">
            //starts off empty
        </g>
    <svg>
</body> 

我想将节点移动到一个新的容器中,这可以很容易地在 jquery 中使用...

$('.gToMoveTo').append($('.node'));

但是,当涉及到动画过渡到新的 DOM 位置时,我在实施 SO 答案中的想法时遇到了麻烦:JQuery - animate moving DOM element to new parent?

使用该函数对我来说与简单的 jquery 行具有完全相同的效果(加上更新的轻微延迟,我假设这是由于调用了动画函数 - 即使没有逐渐过渡到新位置) .

要问是否有人知道为什么我列出的函数不适合为 SVG 组元素的过渡设置动画,这是一个很长的路要走?如果是这样,是否有任何想法可以将其调整为与 SVG 一起使用。

【问题讨论】:

    标签: javascript jquery dom d3.js svg


    【解决方案1】:

    这是一个常见的算法:

    代码如下:

    <html>
    <head>
    <script src="d3.v3.min.js"></script>
    <script src="jquery-2.1.0.min.js"></script>
    
    <style>
    .svg_contariner {
        background-color:#CCCCCC;
    }
    #origin {
        width:200px;
        height:200px;
        margin:5px; 
    }
    #target {
        width:200px;
        height:200px;
        margin:5px; 
    }
    circle {
        fill:#e72;
    }
    text {
        font-family:Tahoma, Geneva, sans-serif;
        font-size:10px;
    }
    .clone {
        margin:0;
        padding:0;
        width:20px;
        height:20px;
        position:absolute;
    }
    </style>
    </head>
    <body>
    <div id="data"></div>
    
    <script>
    var data_text = "", data = [], r = 10;
    /* --- add some random data --- */
    for (i = 0; i < 10; i++) {
        data.push( {
            "x": Math.round(Math.random() * 180)+10,
            "y": Math.round(Math.random() * 180)+10,
            "text": i
        });  
        data_text += "x:" + data[i].x + " y:" + data[i].y + " text:" + data[i].text + "<br>";
    }
    /* --- create 2 containers --- */
    var svgContainerTar = d3.select("body").append("svg")
            .attr("id","target")
            .attr("class","svg_contariner");
    
    var svgContainerOrg = d3.select("body").append("svg")
            .attr("id","origin")
            .attr("class","svg_contariner");
    
    /* --- add g node to origin --- */
    var ele = svgContainerOrg.selectAll("g")
            .data(data)
            .enter()
            .append("g")
            .attr("class", "node")
            .on("click", function (d) {     /* --- bind onClick to every g --- */
                d3.select(this).remove();   /* --- remove origin element --- */
                moveCircle(d);              /* --- create, animate ghost --- */
            });
    
    /* --- add circle to g --- */       
    var circles = ele.append("circle")
                 .attr("cx", function (d) { return d.x; })
                 .attr("cy", function (d) { return d.y; })
                 .attr("r", r+"px");
    /* --- add text to g --- */
    var labels = ele.append("text")
                    .attr("dx", function(d) {return d.x - 2})
                    .attr("dy", function(d) {return d.y + 3})
                    .text(function (d) {return d.text});
    
    function moveCircle(d) {
        ori_x = d.x;
        ori_y = d.y;
        ori_tex = d.text;
        ori_pos = $("#origin").position();
        tar_pos = $("#target").position();
        /* --- create ghost using jQuery --- */
        $("body").append("<div id='ghost' class='clone' style='left:"+(ori_x - r/2+ori_pos.left)+";top:"+(ori_y - r/2+ori_pos.top)+"';>"+
                            "<svg width='20px' height='20px'>"+
                                "<circle cx='"+r+"' cy='"+r+"' r='"+r+"px'></circle>"+
                                "<text x='"+(r - 2)+"' y='"+(r+3)+"'>"+ori_tex+"</text>"+
                            "</svg></div>");
        /* --- animate ghost --- */
        $("#ghost").animate({
            "left" : tar_pos.left + ori_x,
            "top" : tar_pos.top + ori_y
            },100,"swing",
                function () {
                    time = setTimeout(function () {             /* --- when animation ends create target element --- */
                        var new_node = d3.select("#target")
                                        .append ("g")
                                            .attr("class", "node");
                            new_node.append("circle")
                                    .attr("cx", ori_x+r/2+"px")
                                    .attr("cy", ori_y+r/2+"px")
                                    .attr("r", r+"px")
                            new_node.append("text")
                                    .attr("dx", ori_x+r/2-2)
                                    .attr("dy", ori_y+r/2+3)
                                    .text(ori_tex);
                        $("#ghost").remove();                   /* --- remove ghost --- */
                    },100)
                });
    }
    
    </script>
    
    </body></html>
    

    希望有帮助

    【讨论】:

    • 谢谢克劳杰西。但我认为这就是我引用的函数应该做的事情 - 如果动画似乎无法应用于 svg-grouping,我正在努力回答这个问题。
    • 你的意思是,直接为 svg 元素设置动画?为什么要走最长的路?你的方案是什么?
    • 是的,我正在使用 d3 并且有许多嵌入的 svg 元素 - 所以我不能使用 div。我只是想知道为什么当我传递函数引用一个 svg 元素(例如我上面的“节点”g 元素)时,新状态没有动画。一定是我在功能上缺少的东西,但我不确定是什么。例如,我知道 z-index 不适用于 SVG - 但不清楚这是否会导致缺少动画?
    • 是的,要在 SVG 上制作动画,您必须使用“d3.transition”更改“transform(traslate, scale, rotation)”属性。 bost.ocks.org/mike/transition
    • 啊,好的,再次感谢 Klaujesi - 那么您知道我如何获取在引用的函数中创建的“temp”对象并对其应用 d3 转换吗?例如,我不能只说 temp.transition() 或 temp.selectAll('node') 或者我在控制台中收到“不是函数”错误
    猜你喜欢
    • 2018-08-01
    • 1970-01-01
    • 2015-11-04
    • 1970-01-01
    • 2017-03-30
    • 2011-07-01
    • 2021-10-16
    • 2021-09-26
    • 1970-01-01
    相关资源
    最近更新 更多