本文介绍了d3.js网络曲线路径控制的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 29岁程序员,3月因学历无情被辞! //最新小提琴 我正在尝试构建此我可以控制弯曲路径以显示网络的特定图表。两个正确间隔的树干 - 然后是弯曲的树枝,分散给不同的人。 var w = 600; var h = 600; var data = [{userName:You,userImage:https://encrypted-tbn1.gstatic.com/ images?q = tbn:ANd9GcSTzjaQlkAJswpiRZByvgsb3CVrfNNLLwjFHMrkZ_bzdPOWdxDE2Q},{userName:Johnny,userImage:https://crossovercomicblog.files.wordpress.com/2012/ 08 / johnny-depp-sexy.jpg},{userName:Jeri,userImage:https://68.media.tumblr.com/ avatar_3b6d6241698f_128.png},{userName:Charlize,userImage:https://cdn.imza.com/indir/logo/128/charlize- theron.png},{userName:Charlize,userImage:https://cdn.imza.com/indir/logo/128/charlize- theron.png},{userName:Charlize,userImage:https://cdn.imza.com/indir/logo/128/charlize- theron.png},{userName:Charlize,userImage:https://cdn.imza.com/indir/logo/128/charlize- theron.png},{userName:Angelina,userImage:http s://pbs.twimg.com/profile_images/713650489032908800/nO1dMt6M_400x400.jpg},{userName:Them,userImage:https:// 68.media.tumblr.com/avatar_8f199caf2d82_128.png}]; var viz = d3.select(#viz) .append(svg) .attr(width,w) .attr (height,h) .append(g) .attr(transform,translate(40,100)); var patternsSvg = viz.append('g') .attr('class','patterns'); var labelholder = viz.append(g) .attr(class,labelholder); var treeholder = viz.append(g) .attr(class,treeholder); var userholder = viz.append(g) .attr(class,userholder); var smallRadius = 20; var bigRadius = 30; var smallX = smallRadius +(bigRadius / 2); var bigX =(bigRadius * 2)+(smallRadius / 2); var verticalGap =(bigRadius * 2) - 5; var count = data.length; var extendedY =(count-2 *(smallRadius * 2))+((bigRadius * 2)* 2); var arcRadiusLeft =(bigRadius / 2); var arcRadiusRight = - (bigRadius / 2); $ .each(数据,函数(索引,值){ var defs = patternsSvg.append('svg:defs'); //大设计 defs.append('svg:pattern') .attr('id',index + - + value.userName.toLowerCase())。 attr('width',1) .attr('height',1) .append('svg:image') .attr('xlink:href',value.userImage ) .attr('x',0) .attr('y',0) .attr('width',bigRadius * 2) .attr(' height',bigRadius * 2); //小型设计 defs.append('svg:pattern') .attr('id',index + - + value.userName.toLowerCase()) .attr('width',1) .attr('height',1) .append('svg:image') .attr('xlink:href',value.userImage) .attr('x',0) .attr('y',0) .attr('width ',smallRadius * 2) .attr('height',smallRadius * 2); } ); //绘制人圈 var circle = userholder.append(g)。selectAll(circle) .data(数据); circle .enter() .append(svg:circle) .attr(id,function(d){ return d.userName.toLowerCase(); }) .attr(r,function(d,i){ var rad = smallRadius; //第一个和最后一个项目 - 所以你和他们 if(i == 0 || i == count - 1){ rad = bigRadius; } return rad; }) .attr(cx,function(d,i){ var cx; if(i == 0){ cx = 0; //第一个}否则if(i == count - 1){ cx = bigX; // last last } else { cx = smallX; //小的} 返回cx; }) .attr(cy,函数(d,i){ var cy; if(i == 0){ cy = 0; }否则if(i == count - 1){ cy = verticalGap *(i-1)+ extendedY + bigRadius ; }其他{ cy = verticalGap * i } 返回cy; }) .style(填充 ,function(d,i){ var id = i + - + d.userName.toLowerCase(); //小圆圈 //大圆圈 if(i == 0 || i == count - 1){ id = i + - + d .userName.toLowerCase(); } 返回url(#+ id +); }); //绘制人圈 // __标签 var labelholder = d3.select(。labelholder); // __输入 var labels = labelholder.selectAll(text) .data(data); labels.enter() .append(text) .attr(text-anchor,left) / / __ update 标签 .attr(x,函数(d,i){ var displacement =(bigRadius / 2)+ smallRadius; var cx =(smallRadius * 2); if(i == 0){ cx = bigRadius; displacement = bigRadius / 2; } if(i == count - 1){ cx =(bigRadius * 2)+ bigRadius; displacement = bigRadius; } cx + = displacement; 返回cx; }) .attr(y,函数(d,i){ var cy = verticalGap * i; if(i == count - 1){ cy + = extendedY - (bigRadius / 2); } return cy; }) .text(function(d) ){ return d.userName; }); // __ labels var backbone = treeholder.append(g) .append(svg:path); backbone.attr(d,函数(d,i){ var sx =(bigRadius / 2) - (bigRadius / 2); var tx =( bigRadius / 2) - (bigRadius / 2); var r = smallRadius; if(i == 0 || i == count - 1){r = bigRadius ; } var sy =((r / 2)* i)+(r); var ty = verticalGap *(count - 2) - arcRadiusLeft; var dr = 0; 返回M+ sx +,+ sy +A+ dr +,+ dr +0 0,1+ tx + ,+ ty; }); var displaceYBackboneRight =(bigRadius / 2)+ 5; var backbone = treeholder.append(g) .append(svg:path); backbone.attr(d,函数(d,i){ var sx =(bigRadius * 2)+ smallRadius / 2; var tx =(bigRadius * 2)+ smallRadius / 2; var r = smallRadius; if(i == 0 || i == count - 1){r = bigRadius; } var sy =((r / 2)* i)+(r)+ smallRadius + displaceYBackboneRight; var ty = verticalGap *(count - 2)+ extendedY; var dr = 0; 返回M+ sx +,+ sy +A+ dr +,+ dr +0 0,1+ tx +,+ ty; }); //左边的分支 var leftpath = treeholder.append(g)。selectAll(path.leftpath) .data(data ) leftpath .enter()。append(svg:path) .attr(class,function(d){ returnleftpath ; }); leftpath.attr(d,函数(d,i){ var sx = 0; var tx = arcRadiusLeft; var sy = verticalGap * i - arcRadiusLeft; var ty = verticalGap * i; if(i!= 0&& i!= count - 1){ return M+ sx +,+ sy +A+ arcRadiusLeft +,+ arcRadiusLeft +0 0,0+ tx +,+ ty; } }); //左边的分支 var rightpath = treeholder.append(g)。selectAll(path.rightpath) .data(data) rightpath .enter()。append(svg:path) .attr(class,function(d) {返回rightpath; }); rightpath.attr(d,函数(d,i){ var sx =(bigRadius * 2)+(smallRadius / 2); var tx = arcRadiusRight +(bigRadius * 2)+(smallRadius / 2); var sy = verticalGap * i +(bigRadius / 2); var ty = verticalGap * i + arcRadiusRight +(bigRadius / 2); if(i!= 0&& i!= count - 1){ returnM+ sx +,+ sy +A+ arcRadiusLeft +,+ arcRadiusLeft +0 0,0+ tx +,+ ty; } }); // old http://jsfiddle.net/NYEaX/1811/ 所以这里的关键是要创建小弧正确使用数学。 类似于这个 path.attr(d,函数(d,i){ const sx = 0; const sy = height / 2; // width - 从主题a到主题的图表总宽度b const a = width / 2; // a - 主题a和中心之间的距离 const b =(1.5-i)* distanceBetween; // b - 特征1和特征2之间的距离(点之间) const c = Math.sqrt(a * a + b * b); // c - 是主题a和特征之间的对角线距离1 const angle =数学.atan(A / B); //角度 - 在组之间加上 const r = 1/2 * c / Math.cos(angle); // r - 1/2 c的距离除以角度的cos - 将创建一个绘制弧的半径 //也等于c / b *(c / 2) // const r = c / b *(c / 2); 返回M $ {sx},$ {sy} A $ {r},$ {r} 0 0,$ {b> 0?1:0} $ {width},$ {height / 2} `; }); 解决方案 //最新js小提琴 - 稳定控制所有人适当的路径 - 基于blackmiaool的答案。 http ://jsfiddle.net/rbLk2fbe/2/ var w = 600; var h = 600; var data = [{userName:You,userImage:https://encrypted-tbn1.gstatic.com/ images?q = tbn:ANd9GcSTzjaQlkAJswpiRZByvgsb3CVrfNNLLwjFHMrkZ_bzdPOWdxDE2Q},{userName:Johnny,userImage:https://crossovercomicblog.files.wordpress.com/2012/ 08 / johnny-depp-sexy.jpg},{userName:Jeri,userImage:https://68.media.tumblr.com/ avatar_3b6d6241698f_128.png},{userName:Charlize,userImage:https://cdn.imza.com/indir/logo/128/charlize- theron.png},{userName:Charlize,userImage:https://cdn.imza.com/indir/logo/128/charlize- theron.png},{userName:Charlize,userImage:https://cdn.imza.com/indir/logo/128/charlize- theron.png},{userName:Charlize,userImage:https://cdn.imza.com/indir/logo/128/charlize- theron.png},{userName:Angelina,userImage:http s://pbs.twimg.com/profile_images/713650489032908800/nO1dMt6M_400x400.jpg},{userName:Them,userImage:https:// 68.media.tumblr.com/avatar_8f199caf2d82_128.png}]; var viz = d3.select(#viz) .append(svg) .attr(width,w) .attr (height,h) .append(g) .attr(transform,translate(40,100)); var patternsSvg = viz.append('g') .attr('class','patterns'); var labelholder = viz.append(g) .attr(class,labelholder); var treeholder = viz.append(g) .attr(class,treeholder); var userholder = viz.append(g) .attr(class,userholder); var smallRadius = 20; var bigRadius = 30; var smallX = smallRadius +(bigRadius / 2); var bigX =(bigRadius * 2)+(smallRadius / 2); var verticalGap =(bigRadius * 2) - 5; var count = data.length; var extendedY =(count-2 *(smallRadius * 2))+((bigRadius * 2)* 2); var arcRadiusLeft =(bigRadius / 2); var arcRadiusRight = - (bigRadius / 2); $ .each(数据,函数(索引,值){ var defs = patternsSvg.append('svg:defs'); //大设计 defs.append('svg:pattern') .attr('id',index + - + value.userName.toLowerCase())。 attr('width',1) .attr('height',1) .append('svg:image') .attr('xlink:href',value.userImage ) .attr('x',0) .attr('y',0) .attr('width',bigRadius * 2) .attr(' height',bigRadius * 2); //小型设计 defs.append('svg:pattern') .attr('id',index + - + value.userName.toLowerCase()) .attr('width',1) .attr('height',1) .append('svg:image') .attr('xlink:href',value.userImage) .attr('x',0) .attr('y',0) .attr('width ',smallRadius * 2) .attr('height',smallRadius * 2); } ); //绘制人圈 var circle = userholder.append(g)。selectAll(circle) .data(数据); circle .enter() .append(svg:circle) .attr(id,function(d){ return d.userName.toLowerCase(); }) .attr(r,function(d,i){ var rad = smallRadius; //第一个和最后一个项目 - 所以你和他们 if(i == 0 || i == count - 1){ rad = bigRadius; } return rad; }) .attr(cx,function(d,i){ var cx; if(i == 0){ cx = 0; //第一个}否则if(i == count - 1){ cx = bigX; // last last } else { cx = smallX; //小的} 返回cx; }) .attr(cy,函数(d,i){ var cy; if(i == 0){ cy = 0; }否则if(i == count - 1){ cy = verticalGap *(i-1)+ extendedY + bigRadius ; }其他{ cy = verticalGap * i } 返回cy; }) .style(填充 ,function(d,i){ var id = i + - + d.userName.toLowerCase(); //小圆圈 //大圆圈 if(i == 0 || i == count - 1){ id = i + - + d .userName.toLowerCase(); } 返回url(#+ id +); }); //绘制人圈 // __标签 var labelholder = d3.select(。labelholder); // __输入 var labels = labelholder.selectAll(text) .data(data); labels.enter() .append(text) .attr(text-anchor,left) / / __ update 标签 .attr(x,函数(d,i){ var displacement =(bigRadius / 2)+ smallRadius; var cx =(smallRadius * 2); if(i == 0){ cx = bigRadius; displacement = bigRadius / 2; } if(i == count - 1){ cx =(bigRadius * 2)+ bigRadius; displacement = bigRadius; } cx + = displacement; 返回cx; }) .attr(y,函数(d,i){ var cy = verticalGap * i; if(i == count - 1){ cy + = extendedY - (bigRadius / 2); } return cy; }) .text(function(d) ){ return d.userName; }); // __ labels var backbone = treeholder.append(g) .append(svg:path); backbone.attr(d,函数(d,i){ var sx =(bigRadius / 2) - (bigRadius / 2); var tx =( bigRadius / 2) - (bigRadius / 2); var r = smallRadius; if(i == 0 || i == count - 1){r = bigRadius ; } var sy =((r / 2)* i)+(r); var ty = verticalGap *(count - 2) - arcRadiusLeft; var dr = 0; 返回M+ sx +,+ sy +A+ dr +,+ dr +0 0,1+ tx + ,+ ty; }); var displaceYBackboneRight =(bigRadius / 2)+ 5; var backbone = treeholder.append(g) .append(svg:path); backbone.attr(d,函数(d,i){ var sx =(bigRadius * 2)+ smallRadius / 2; var tx =(bigRadius * 2)+ smallRadius / 2; var r = smallRadius; if(i == 0 || i == count - 1){r = bigRadius; } var sy =((r / 2)* i)+(r)+ smallRadius + displaceYBackboneRight; var ty = verticalGap *(count - 2)+ extendedY; var dr = 0; 返回M+ sx +,+ sy +A+ dr +,+ dr +0 0,1+ tx +,+ ty; }); //左边的分支 var leftpath = treeholder.append(g)。selectAll(path.leftpath) .data(data ) leftpath .enter()。append(svg:path) .attr(class,function(d){ returnleftpath ; }); leftpath.attr(d,函数(d,i){ var sx = 0; var tx = arcRadiusLeft; var sy = verticalGap * i - arcRadiusLeft; var ty = verticalGap * i; if(i!= 0&& i!= count - 1){ return M+ sx +,+ sy +A+ arcRadiusLeft +,+ arcRadiusLeft +0 0,0+ tx +,+ ty; } }); //左边的分支 var rightpath = treeholder.append(g)。selectAll(path.rightpath) .data(data) rightpath .enter()。append(svg:path) .attr(class,function(d) {返回rightpath; }); rightpath.attr(d,函数(d,i){ var sx =(bigRadius * 2)+(smallRadius / 2); var tx = arcRadiusRight +(bigRadius * 2)+(smallRadius / 2); var sy = verticalGap * i +(bigRadius / 2); var ty = verticalGap * i + arcRadiusRight +(bigRadius / 2); if(i!= 0&& i!= count - 1){ returnM+ sx +,+ sy +A+ arcRadiusLeft +,+ arcRadiusLeft +0 0,0+ tx +,+ ty; } }); //latest fiddlehttp://jsfiddle.net/rbLk2fbe/2/I am trying to build this particular chart where I can control the curved paths to show a network. Two trunks that are spaced correctly - and then curved branches that leaf off to the various people. var w = 600; var h = 600; var data = [{ "userName": "You", "userImage": "https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcSTzjaQlkAJswpiRZByvgsb3CVrfNNLLwjFHMrkZ_bzdPOWdxDE2Q" }, { "userName": "Johnny", "userImage": "https://crossovercomicblog.files.wordpress.com/2012/08/johnny-depp-sexy.jpg" }, { "userName": "Jeri", "userImage": "https://68.media.tumblr.com/avatar_3b6d6241698f_128.png" }, { "userName": "Charlize", "userImage": "https://cdn.imza.com/indir/logo/128/charlize-theron.png" },{ "userName": "Charlize", "userImage": "https://cdn.imza.com/indir/logo/128/charlize-theron.png" },{ "userName": "Charlize", "userImage": "https://cdn.imza.com/indir/logo/128/charlize-theron.png" },{ "userName": "Charlize", "userImage": "https://cdn.imza.com/indir/logo/128/charlize-theron.png" },{ "userName": "Angelina", "userImage": "https://pbs.twimg.com/profile_images/713650489032908800/nO1dMt6M_400x400.jpg" }, { "userName": "Them", "userImage": "https://68.media.tumblr.com/avatar_8f199caf2d82_128.png" }]; var viz = d3.select("#viz") .append("svg") .attr("width", w) .attr("height", h) .append("g") .attr("transform", "translate(40,100)"); var patternsSvg = viz.append('g') .attr('class', 'patterns'); var labelholder = viz.append("g") .attr("class", "labelholder"); var treeholder = viz.append("g") .attr("class", "treeholder"); var userholder = viz.append("g") .attr("class", "userholder"); var smallRadius = 20; var bigRadius = 30; var smallX = smallRadius + (bigRadius/2); var bigX = (bigRadius*2) + (smallRadius/2); var verticalGap = (bigRadius * 2) - 5; var count = data.length; var extendedY = (count-2 * (smallRadius*2)) + ((bigRadius*2) * 2); var arcRadiusLeft = (bigRadius / 2); var arcRadiusRight = -(bigRadius / 2); $.each(data, function(index, value) { var defs = patternsSvg.append('svg:defs'); //big design defs.append('svg:pattern') .attr('id', index + "--" + value.userName.toLowerCase()) .attr('width', 1) .attr('height', 1) .append('svg:image') .attr('xlink:href', value.userImage) .attr('x', 0) .attr('y', 0) .attr('width', bigRadius * 2) .attr('height', bigRadius * 2); //small design defs.append('svg:pattern') .attr('id', index + "-" + value.userName.toLowerCase()) .attr('width', 1) .attr('height', 1) .append('svg:image') .attr('xlink:href', value.userImage) .attr('x', 0) .attr('y', 0) .attr('width', smallRadius * 2) .attr('height', smallRadius * 2); }); //plot people circles var circle = userholder.append("g").selectAll("circle") .data(data); circle .enter() .append("svg:circle") .attr("id", function(d) { return d.userName.toLowerCase(); }) .attr("r", function(d, i) { var rad = smallRadius; //first and last items -- so you and them if (i == 0 || i == count - 1) { rad = bigRadius; } return rad; }) .attr("cx", function(d, i) { var cx; if (i == 0) { cx = 0; //first one } else if (i == count - 1) { cx = bigX; //last one } else { cx = smallX; //small ones } return cx; }) .attr("cy", function(d, i) { var cy; if (i == 0) { cy = 0; } else if (i == count - 1) { cy = verticalGap * (i-1) + extendedY + bigRadius; } else { cy = verticalGap * i } return cy; }) .style("fill", function(d, i) { var id = i + "-" + d.userName.toLowerCase(); //small circles //large circles if (i == 0 || i == count - 1) { id = i + "--" + d.userName.toLowerCase(); } return "url(#" + id + ")"; }); //plot people circles //__labels var labelholder = d3.select(".labelholder"); //__ enter var labels = labelholder.selectAll("text") .data(data); labels.enter() .append("text") .attr("text-anchor", "left") //__ update labels .attr("x", function(d, i) { var displacement = (bigRadius/2) + smallRadius; var cx = (smallRadius * 2); if (i == 0) { cx = bigRadius; displacement = bigRadius/2; } if (i == count - 1) { cx = (bigRadius * 2) + bigRadius; displacement = bigRadius; } cx += displacement; return cx; }) .attr("y", function(d, i) { var cy = verticalGap * i; if (i == count - 1) { cy += extendedY - (bigRadius/2); } return cy; }) .text(function(d) { return d.userName; }); //__labels var backbone = treeholder.append("g") .append("svg:path"); backbone.attr("d", function(d, i) { var sx = (bigRadius / 2) - (bigRadius / 2); var tx = (bigRadius / 2) - (bigRadius / 2); var r = smallRadius; if (i == 0 || i == count - 1) { r = bigRadius; } var sy = ((r / 2) * i) + (r); var ty = verticalGap * (count - 2) - arcRadiusLeft; var dr = 0; return "M" + sx + "," + sy + "A" + dr + "," + dr + " 0 0,1 " + tx + "," + ty; });var displaceYBackboneRight = (bigRadius / 2) + 5; var backbone = treeholder.append("g") .append("svg:path"); backbone.attr("d", function(d, i) { var sx = (bigRadius * 2) + smallRadius/2; var tx = (bigRadius * 2) + smallRadius/2; var r = smallRadius; if (i == 0 || i == count - 1) { r = bigRadius; } var sy = ((r / 2) * i) + (r) + smallRadius + displaceYBackboneRight; var ty = verticalGap * (count - 2) + extendedY; var dr = 0; return "M" + sx + "," + sy + "A" + dr + "," + dr + " 0 0,1 " + tx + "," + ty; }); //branches on the left var leftpath = treeholder.append("g").selectAll("path.leftpath") .data(data) leftpath .enter().append("svg:path") .attr("class", function(d) { return "leftpath"; }); leftpath.attr("d", function(d, i) { var sx = 0; var tx = arcRadiusLeft; var sy = verticalGap * i - arcRadiusLeft; var ty = verticalGap * i; if (i != 0 && i != count - 1) { return "M" + sx + "," + sy + "A" + arcRadiusLeft + "," + arcRadiusLeft + " 0 0,0 " + tx + "," + ty; } }); //branches on the left var rightpath = treeholder.append("g").selectAll("path.rightpath") .data(data) rightpath .enter().append("svg:path") .attr("class", function(d) { return "rightpath"; }); rightpath.attr("d", function(d, i) { var sx = (bigRadius*2) + (smallRadius/2); var tx = arcRadiusRight + (bigRadius*2) + (smallRadius/2); var sy = verticalGap * i + (bigRadius / 2); var ty = verticalGap * i + arcRadiusRight + (bigRadius / 2); if (i != 0 && i != count - 1) { return "M" + sx + "," + sy + "A" + arcRadiusLeft + "," + arcRadiusLeft + " 0 0,0 " + tx + "," + ty; } });//oldhttp://jsfiddle.net/NYEaX/1811/So the key here is to create the small arcs correctly using maths.Something like thispath.attr("d", function (d, i) { const sx = 0; const sy = height/2; //width - total width of chart from subject a to subject b const a = width/2; //a - distance between subject a and center const b = (1.5-i)*distanceBetween; //b - distance between trait 1 and trait 2 (between the dots) const c = Math.sqrt(a * a + b * b); //c - is the diagonal distance between subject a and trait 1 const angle=Math.atan(a/b); //angle - between group to subject a const r=1/2*c/Math.cos(angle); //r - 1/2 the distance of c -- divided by cos of angle -- will create a radius to draw the arc //also equals c/b*(c/2)// const r=c/b*(c/2); return `M${sx},${sy} A${r},${r} 0 0,${b>0?1:0} ${width},${height/2}`;}); 解决方案 //latest js fiddle - stable with control for all paths in place - based on blackmiaool's answer.http://jsfiddle.net/rbLk2fbe/2/ var w = 600; var h = 600; var data = [{ "userName": "You", "userImage": "https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcSTzjaQlkAJswpiRZByvgsb3CVrfNNLLwjFHMrkZ_bzdPOWdxDE2Q" }, { "userName": "Johnny", "userImage": "https://crossovercomicblog.files.wordpress.com/2012/08/johnny-depp-sexy.jpg" }, { "userName": "Jeri", "userImage": "https://68.media.tumblr.com/avatar_3b6d6241698f_128.png" }, { "userName": "Charlize", "userImage": "https://cdn.imza.com/indir/logo/128/charlize-theron.png" },{ "userName": "Charlize", "userImage": "https://cdn.imza.com/indir/logo/128/charlize-theron.png" },{ "userName": "Charlize", "userImage": "https://cdn.imza.com/indir/logo/128/charlize-theron.png" },{ "userName": "Charlize", "userImage": "https://cdn.imza.com/indir/logo/128/charlize-theron.png" },{ "userName": "Angelina", "userImage": "https://pbs.twimg.com/profile_images/713650489032908800/nO1dMt6M_400x400.jpg" }, { "userName": "Them", "userImage": "https://68.media.tumblr.com/avatar_8f199caf2d82_128.png" }]; var viz = d3.select("#viz") .append("svg") .attr("width", w) .attr("height", h) .append("g") .attr("transform", "translate(40,100)"); var patternsSvg = viz.append('g') .attr('class', 'patterns'); var labelholder = viz.append("g") .attr("class", "labelholder"); var treeholder = viz.append("g") .attr("class", "treeholder"); var userholder = viz.append("g") .attr("class", "userholder"); var smallRadius = 20; var bigRadius = 30; var smallX = smallRadius + (bigRadius/2); var bigX = (bigRadius*2) + (smallRadius/2); var verticalGap = (bigRadius * 2) - 5; var count = data.length; var extendedY = (count-2 * (smallRadius*2)) + ((bigRadius*2) * 2); var arcRadiusLeft = (bigRadius / 2); var arcRadiusRight = -(bigRadius / 2); $.each(data, function(index, value) { var defs = patternsSvg.append('svg:defs'); //big design defs.append('svg:pattern') .attr('id', index + "--" + value.userName.toLowerCase()) .attr('width', 1) .attr('height', 1) .append('svg:image') .attr('xlink:href', value.userImage) .attr('x', 0) .attr('y', 0) .attr('width', bigRadius * 2) .attr('height', bigRadius * 2); //small design defs.append('svg:pattern') .attr('id', index + "-" + value.userName.toLowerCase()) .attr('width', 1) .attr('height', 1) .append('svg:image') .attr('xlink:href', value.userImage) .attr('x', 0) .attr('y', 0) .attr('width', smallRadius * 2) .attr('height', smallRadius * 2); }); //plot people circles var circle = userholder.append("g").selectAll("circle") .data(data); circle .enter() .append("svg:circle") .attr("id", function(d) { return d.userName.toLowerCase(); }) .attr("r", function(d, i) { var rad = smallRadius; //first and last items -- so you and them if (i == 0 || i == count - 1) { rad = bigRadius; } return rad; }) .attr("cx", function(d, i) { var cx; if (i == 0) { cx = 0; //first one } else if (i == count - 1) { cx = bigX; //last one } else { cx = smallX; //small ones } return cx; }) .attr("cy", function(d, i) { var cy; if (i == 0) { cy = 0; } else if (i == count - 1) { cy = verticalGap * (i-1) + extendedY + bigRadius; } else { cy = verticalGap * i } return cy; }) .style("fill", function(d, i) { var id = i + "-" + d.userName.toLowerCase(); //small circles //large circles if (i == 0 || i == count - 1) { id = i + "--" + d.userName.toLowerCase(); } return "url(#" + id + ")"; }); //plot people circles //__labels var labelholder = d3.select(".labelholder"); //__ enter var labels = labelholder.selectAll("text") .data(data); labels.enter() .append("text") .attr("text-anchor", "left") //__ update labels .attr("x", function(d, i) { var displacement = (bigRadius/2) + smallRadius; var cx = (smallRadius * 2); if (i == 0) { cx = bigRadius; displacement = bigRadius/2; } if (i == count - 1) { cx = (bigRadius * 2) + bigRadius; displacement = bigRadius; } cx += displacement; return cx; }) .attr("y", function(d, i) { var cy = verticalGap * i; if (i == count - 1) { cy += extendedY - (bigRadius/2); } return cy; }) .text(function(d) { return d.userName; }); //__labels var backbone = treeholder.append("g") .append("svg:path"); backbone.attr("d", function(d, i) { var sx = (bigRadius / 2) - (bigRadius / 2); var tx = (bigRadius / 2) - (bigRadius / 2); var r = smallRadius; if (i == 0 || i == count - 1) { r = bigRadius; } var sy = ((r / 2) * i) + (r); var ty = verticalGap * (count - 2) - arcRadiusLeft; var dr = 0; return "M" + sx + "," + sy + "A" + dr + "," + dr + " 0 0,1 " + tx + "," + ty; });var displaceYBackboneRight = (bigRadius / 2) + 5; var backbone = treeholder.append("g") .append("svg:path"); backbone.attr("d", function(d, i) { var sx = (bigRadius * 2) + smallRadius/2; var tx = (bigRadius * 2) + smallRadius/2; var r = smallRadius; if (i == 0 || i == count - 1) { r = bigRadius; } var sy = ((r / 2) * i) + (r) + smallRadius + displaceYBackboneRight; var ty = verticalGap * (count - 2) + extendedY; var dr = 0; return "M" + sx + "," + sy + "A" + dr + "," + dr + " 0 0,1 " + tx + "," + ty; }); //branches on the left var leftpath = treeholder.append("g").selectAll("path.leftpath") .data(data) leftpath .enter().append("svg:path") .attr("class", function(d) { return "leftpath"; }); leftpath.attr("d", function(d, i) { var sx = 0; var tx = arcRadiusLeft; var sy = verticalGap * i - arcRadiusLeft; var ty = verticalGap * i; if (i != 0 && i != count - 1) { return "M" + sx + "," + sy + "A" + arcRadiusLeft + "," + arcRadiusLeft + " 0 0,0 " + tx + "," + ty; } }); //branches on the left var rightpath = treeholder.append("g").selectAll("path.rightpath") .data(data) rightpath .enter().append("svg:path") .attr("class", function(d) { return "rightpath"; }); rightpath.attr("d", function(d, i) { var sx = (bigRadius*2) + (smallRadius/2); var tx = arcRadiusRight + (bigRadius*2) + (smallRadius/2); var sy = verticalGap * i + (bigRadius / 2); var ty = verticalGap * i + arcRadiusRight + (bigRadius / 2); if (i != 0 && i != count - 1) { return "M" + sx + "," + sy + "A" + arcRadiusLeft + "," + arcRadiusLeft + " 0 0,0 " + tx + "," + ty; } }); 这篇关于d3.js网络曲线路径控制的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 上岸,阿里云! 09-02 03:53