Code: http://codepen.io/anon/pen/pEBKOY

var gId = 1; $(document).ready(function(){ $('circle').live('click', function(){ var svg = d3.select('svg'); var el = d3.select("g[data-id='"+$(this).data('id')+"']"); addChildren($(this), el); }); $('circle').live('mousedown', function(event) { if (event.which === 3) { delAll($(this)); } }); }); // Функция добавления нового элемента function addChildren(parent, el){ var row = parent.data('row')+1; var cy = parseInt(parent.attr('cy'))+50; el.append("circle") .attr("data-row", row) .attr("r", "16") .attr("cx", "50%") .attr("cy", cy) .attr("data-id", ++gId); el.append("text") .attr("x", "50%") .attr("y", cy+5) .attr("data-row", row) .attr("data-id", gId); el.append("line") .attr("data-row", row) .attr("x1", parent.attr('cx')) .attr("y1", parseInt(parent.attr('cy'))+8) .attr("x2", "50%") .attr("y2", cy-8) .attr("data-id", gId); el.append("g").attr("data-id", gId); recalcX(row); numbering(); } // Функция пересчета координат function recalcX(row){ var count = $('circle[data-row='+row+']').length; // Количество элементов в строке var a = 100/(count+1); var b = 0; $('circle[data-row='+row+']').each(function(){ b+=a; d3.select(this).transition() .duration(1000) .attr("cx", b+'%'); var id = d3.select(this).attr('data-id'); $('g[data-id='+id+'] > line').each(function(){ // Пересчет линий, которые НИЖЕ данной строки d3.select(this).transition() .duration(1000) .attr("x1", b+'%'); }); }); b = 0; $('line[data-row='+row+']').each(function(){ // Пересчет координат линий b+=a; d3.select(this).transition() .duration(1000) .attr("x2", b+'%'); }); b = 0; $('text[data-row='+row+']').each(function(){ // Пересчет координат текста b+=a; d3.select(this).transition() .duration(1000) .attr("x", b-1.5+'%'); }); } // Функция нумерации function numbering(svg){ d3.selectAll('svg text').text(function(d,i){return i+1}); } // Функция удаления без сохранения связей function delAll(element){ var id = element.data('id'); var row = element.data('row'); d3.select('circle[data-id="'+id+'"]').remove(); d3.select('line[data-id="'+id+'"]').remove(); d3.select('text[data-id="'+id+'"]').remove(); d3.select('g[data-id="'+id+'"]').remove(); while ($('circle[data-row="' + row + '"]').length > 0) { recalcX(row); row++; } } 
  svg{ border: 1px solid black; } line{ stroke: black; } text{ fill: white; } circle{ cursor: pointer; } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script> <body> <script src="d3.v3.min.js"></script> <svg width="700" height="500" > <circle data-row="1" r="16" cx="50%" cy="20" data-id="1"></circle> <text x="49%" y="25">1</text> <g data-id="1"></g> </svg> </body> 

Clicking with the left mouse button adds a child element. Pressing right - removes the element and all elements that are below it.

If you make just such a thing, as in the screenshot Tree

And then delete point 2, then the line that goes from 5 to 6 and 7 is rendered incorrectly. How can this be fixed?

If 58 term to remove

 .transition() .duration(1000) 

then everything will work, but without animation. And it is necessary that the animation remains.

Or if after 69 lines (where "Recalculation of coordinates of lines") add .delay(1000) , then everything will also work as it should. but the animation will turn out to be a curve. I can not understand why it works like this and how to fix it.

    0