d3.js网络曲线路径控制 [英] d3.js network curved path control
问题描述
//最新小提琴
我正在尝试构建此我可以控制弯曲路径以显示网络的特定图表。两个正确间隔的树干 - 然后是弯曲的树枝,分散给不同的人。
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/
所以这里的关键是要创建小弧正确使用数学。
< img src =https://i.stack.imgur.com/f2k5q.pngalt =在此输入图像说明>
类似于这个
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 fiddle http://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;
}
});
//old http://jsfiddle.net/NYEaX/1811/
So the key here is to create the small arcs correctly using maths.
Something like this
path.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网络曲线路径控制的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!