动画SVG分组的DOM运动

时间:2015-08-07 11:17:59

标签: javascript jquery dom d3.js svg

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

<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位置的过渡动画时,我在解决这个问题时遇到了麻烦:JQuery - animate moving DOM element to new parent?

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

所有这些都是很长的问题,是否有人知道为什么我列出的函数不适合动画SVG组元素的转换?如果是这样,是否有任何想法可以使其适应SVG。

1 个答案:

答案 0 :(得分:2)

这是一种常见的算法:

enter image description here

以下是代码:

<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>

希望这个帮助