如何将和弦图的形状从圆形更改为椭圆形?
How to change shape of chord diagram from circle to ellipse shape?
我想使用 d3js 创建和弦图。这是我正在实施的示例代码:
<script src="http://d3js.org/d3.v3.min.js"></script>
<body>
<svg width="960" height="960"></svg>
<script>
d3.text("data.csv", function(error, datas) {
var dataf = d3.csv.parseRows(datas);
dataf.shift();
var text = [];
var nest = d3.nest()
.key(function(d) { return d[1]; })
.entries(dataf)
.sort(function(a, b) { return a.key < b.key ? -1 : 1; });
nest.forEach(function(d) {
text.push(d.key);
});
nest = d3.nest()
.key(function(d) { return d[2]; })
.entries(dataf)
.sort(function(a, b) { return a.key < b.key ? -1 : 1; });
nest.forEach(function(d) {
text.push(d.key);
});
var textnested = [];
d3.nest()
.key(function(d) { return d; })
.entries(text)
.forEach(function(d) {
textnested.push(d.key);
});
if(textnested.length < text.length) {
var inDirection = 1;
text = textnested;
text.sort(function(a, b) { return a < b ? -1 : 1; });
}
nest = d3.nest()
.key(function(d) { return d[0]; })
.entries(dataf);
if(nest.length < dataf.length) {
nest.forEach(function(d) {
d.values.forEach(function(e) { e.push(1/d.values.length); });
});
}
var matrix = [];
text.forEach(function(d, i) {
matrix[i] = d3.range(text.length).map(function() { return 0; });
});
dataf.forEach(function(d) {
var x = text.indexOf(d[1]),
y = text.indexOf(d[2]);
if(nest.length < dataf.length) matrix[x][y]+=d[d.length-1];
else matrix[x][y]++;
if(!inDirection) {
if(nest.length < dataf.length) matrix[y][x]+=d[d.length-1];
else matrix[y][x]++;
}
});
var chord = d3.layout.chord()
.padding(.04)
.matrix(matrix);
var svg = d3.select("svg")
.append("g")
.attr("transform", "translate(480, 480)");
var fill = d3.scale.category20();
var g = svg.selectAll(".group")
.data(chord.groups)
.enter()
.append("g")
.attr("class", "group");
g.append("path")
.attr("d", d3.svg.arc().innerRadius(350).outerRadius(370))
.style("fill", function(d) { return fill(d.index); })
.on("mouseover", standOut(0.1))
.on("mouseout", standOut(1));
g.append("text")
.attr("transform", function(d) {
return "rotate("+(((d.startAngle+d.endAngle)/2) * (180/Math.PI) - 90)+")"
+ "translate(376)" + (((d.startAngle+d.endAngle)/2) > Math.PI ? "rotate(180)" : ""); })
.attr("text-anchor", function(d) { return ((d.startAngle+d.endAngle)/2) > Math.PI ? "end" : ""; })
.text(function(d) { return text[d.index]; });
svg.selectAll(".chord")
.data(chord.chords)
.enter()
.append("path")
.attr("class", "chord")
.attr("d", d3.svg.chord().radius(350))
.style("fill", function(d) { return fill(d.source.index); })
.style("stroke", function(d) { return d3.rgb(fill(d.source.index)).darker(); });
function standOut(o) {
return function(d, i) {
var gstandout = [];
svg.selectAll(".chord")
.each(function(e) { e.source.index == i ? gstandout.push(e.target.index) : e.target.index == i ? gstandout.push(e.source.index) : ""; })
.filter(function(e) { return e.source.index != i && e.target.index != i; })
.style("opacity", o);
svg.selectAll(".group")
.filter(function(e, j) { return gstandout.indexOf(j) == -1 && j != i; })
.style("opacity", o);
};
}
});
</script>
</body>
以下是 data.csv 文件:
"CitingArticle","Cited","Subject"
"Locke et al., 2015","Laosinchai, P.","Agricultural and Biological Sciences"
"Locke et al., 2015","Laosinchai, P.","Biochemistry, Genetics and Molecular Biology"
"Yasri, 2015","Yasri, P.","Social Sciences"
"Yang et al., 2015","Panjaburee, P.","Computer Science"
"Yang et al., 2015","Panjaburee, P.","Social Sciences"
"Chu et al., 2015","Panjaburee, P.","Computer Science"
"Chu et al., 2015","Panjaburee, P.","Social Sciences"
"Yang et al., 2015","Panjaburee, P.","Computer Science"
"Yang et al., 2015","Panjaburee, P.","Social Sciences"
"Chu et al., 2015","Panjaburee, P.","Computer Science"
"Chu et al., 2015","Panjaburee, P.","Social Sciences"
"Buaraphan & Abedin Forhad, 2015","Buaraphan, K.","Social Sciences"
"Kim & Choi, 2015","Yodyingyong, S.","Chemical Engineering"
"Kim & Choi, 2015","Yodyingyong, S.","Chemistry"
"Kim & Choi, 2015","Yodyingyong, S.","Engineering"
"Kim & Choi, 2015","Yodyingyong, S.","Materials Science"
"Kim & Choi, 2015","Yodyingyong, S.","Physics and Astronomy"
"Bretz & McClary, 2015","Ratanaroutai, T.","Chemistry"
"Bretz & McClary, 2015","Ratanaroutai, T.","Social Sciences"
"Panijpan et al., 2015","Sriwattanarothai, N.","Biochemistry, Genetics and Molecular Biology"
"Panijpan et al., 2015","Sriwattanarothai, N.","Medicine"
"Durand & Borsa, 2015","Sriwattanarothai, N.","Agricultural and Biological Sciences"
"Durand & Borsa, 2015","Sriwattanarothai, N.","Biochemistry, Genetics and Molecular Biology"
"Durand & Borsa, 2015","Sriwattanarothai, N.","Immunology and Microbiology"
"Durand & Borsa, 2015","Sriwattanarothai, N.","Medicine"
"Vu et al., 2015","Yodyingyong, S.","Chemical Engineering"
"Vu et al., 2015","Yodyingyong, S.","Environmental Science"
"Chang et al., 2015","Yodyingyong, S.","Materials Science"
"Zhang et al., 2015","Ketpichainarong, W.","Social Sciences"
"Buaraphan & Abedin Forhad, 2015","Buaraphan, K.","Social Sciences"
"Cil, 2015","Buaraphan, K.","Social Sciences"
"Buaraphan & Abedin Forhad, 2015","Buaraphan, K.","Social Sciences"
"Di Russo et al., 2015","Chenprakhon, P.","Biochemistry, Genetics and Molecular Biology"
"De Sancho et al., 2015","Chenprakhon, P.","Chemistry"
"De Sancho et al., 2015","Chenprakhon, P.","Computer Science"
"Cazade et al., 2015","Chenprakhon, P.","Chemistry"
"Cazade et al., 2015","Chenprakhon, P.","Medicine"
"Cazade et al., 2015","Chenprakhon, P.","Physics and Astronomy"
但我想以椭圆形而不是圆形显示和弦。任何人都知道这怎么可能?非常感谢您的帮助。
首先,弦不是画成圆,而是画成贝塞尔曲线,在画的中心有一个控制点(有点像圆)。我建议将两个控制点放置在靠近边缘的位置以获得 "ellipse-like" 效果。
我不确定如何从头开始绘制这样的弧线,但可以在绘制后编辑路径的 d
属性。
这是我的 editPath
函数:
function editPath() {
var ratio = 0.6;
var path=d3.select(this).attr("d")
console.log(path);
find=path.match(/([\-\.0-9]+)\,([\-\.0-9]+)Q 0,0 ([\-\.0-9]+),([\-\.0-9]+)/);
if (!find) return;
path=path.replace(/Q 0,0/,"C "+find[1]*ratio+","+find[2]*ratio+" "+find[3]*ratio+","+find[4]*ratio);
console.log(path);
d3.select(this).attr("d", path)
}
此函数执行以下操作:
- 提取路径命令(
path
)
- 识别以
0,0
为中心的贝塞尔曲线(Q
)
- 提取起点和终点坐标(数组
find
)
- 计算新控制点的坐标(find[i]*ratio)
- 将其注入新的贝塞尔曲线(有两个控制点,
C
)
- 用新路径替换原来的路径
这只会替换路径中的一条贝塞尔曲线,因此您需要为每个和弦调用两次:
[...]
.attr("class", "chord")
.attr("d", d3.svg.chord().radius(350))
.each(editPath).each(editPath) //call twice!
我在这个例子中测试了这个:http://bl.ocks.org/mbostock/raw/4062006/ ...它在那里工作,我希望它应该在使用 d3.svg.chord
的任何图表上工作。
我想使用 d3js 创建和弦图。这是我正在实施的示例代码:
<script src="http://d3js.org/d3.v3.min.js"></script>
<body>
<svg width="960" height="960"></svg>
<script>
d3.text("data.csv", function(error, datas) {
var dataf = d3.csv.parseRows(datas);
dataf.shift();
var text = [];
var nest = d3.nest()
.key(function(d) { return d[1]; })
.entries(dataf)
.sort(function(a, b) { return a.key < b.key ? -1 : 1; });
nest.forEach(function(d) {
text.push(d.key);
});
nest = d3.nest()
.key(function(d) { return d[2]; })
.entries(dataf)
.sort(function(a, b) { return a.key < b.key ? -1 : 1; });
nest.forEach(function(d) {
text.push(d.key);
});
var textnested = [];
d3.nest()
.key(function(d) { return d; })
.entries(text)
.forEach(function(d) {
textnested.push(d.key);
});
if(textnested.length < text.length) {
var inDirection = 1;
text = textnested;
text.sort(function(a, b) { return a < b ? -1 : 1; });
}
nest = d3.nest()
.key(function(d) { return d[0]; })
.entries(dataf);
if(nest.length < dataf.length) {
nest.forEach(function(d) {
d.values.forEach(function(e) { e.push(1/d.values.length); });
});
}
var matrix = [];
text.forEach(function(d, i) {
matrix[i] = d3.range(text.length).map(function() { return 0; });
});
dataf.forEach(function(d) {
var x = text.indexOf(d[1]),
y = text.indexOf(d[2]);
if(nest.length < dataf.length) matrix[x][y]+=d[d.length-1];
else matrix[x][y]++;
if(!inDirection) {
if(nest.length < dataf.length) matrix[y][x]+=d[d.length-1];
else matrix[y][x]++;
}
});
var chord = d3.layout.chord()
.padding(.04)
.matrix(matrix);
var svg = d3.select("svg")
.append("g")
.attr("transform", "translate(480, 480)");
var fill = d3.scale.category20();
var g = svg.selectAll(".group")
.data(chord.groups)
.enter()
.append("g")
.attr("class", "group");
g.append("path")
.attr("d", d3.svg.arc().innerRadius(350).outerRadius(370))
.style("fill", function(d) { return fill(d.index); })
.on("mouseover", standOut(0.1))
.on("mouseout", standOut(1));
g.append("text")
.attr("transform", function(d) {
return "rotate("+(((d.startAngle+d.endAngle)/2) * (180/Math.PI) - 90)+")"
+ "translate(376)" + (((d.startAngle+d.endAngle)/2) > Math.PI ? "rotate(180)" : ""); })
.attr("text-anchor", function(d) { return ((d.startAngle+d.endAngle)/2) > Math.PI ? "end" : ""; })
.text(function(d) { return text[d.index]; });
svg.selectAll(".chord")
.data(chord.chords)
.enter()
.append("path")
.attr("class", "chord")
.attr("d", d3.svg.chord().radius(350))
.style("fill", function(d) { return fill(d.source.index); })
.style("stroke", function(d) { return d3.rgb(fill(d.source.index)).darker(); });
function standOut(o) {
return function(d, i) {
var gstandout = [];
svg.selectAll(".chord")
.each(function(e) { e.source.index == i ? gstandout.push(e.target.index) : e.target.index == i ? gstandout.push(e.source.index) : ""; })
.filter(function(e) { return e.source.index != i && e.target.index != i; })
.style("opacity", o);
svg.selectAll(".group")
.filter(function(e, j) { return gstandout.indexOf(j) == -1 && j != i; })
.style("opacity", o);
};
}
});
</script>
</body>
以下是 data.csv 文件:
"CitingArticle","Cited","Subject"
"Locke et al., 2015","Laosinchai, P.","Agricultural and Biological Sciences"
"Locke et al., 2015","Laosinchai, P.","Biochemistry, Genetics and Molecular Biology"
"Yasri, 2015","Yasri, P.","Social Sciences"
"Yang et al., 2015","Panjaburee, P.","Computer Science"
"Yang et al., 2015","Panjaburee, P.","Social Sciences"
"Chu et al., 2015","Panjaburee, P.","Computer Science"
"Chu et al., 2015","Panjaburee, P.","Social Sciences"
"Yang et al., 2015","Panjaburee, P.","Computer Science"
"Yang et al., 2015","Panjaburee, P.","Social Sciences"
"Chu et al., 2015","Panjaburee, P.","Computer Science"
"Chu et al., 2015","Panjaburee, P.","Social Sciences"
"Buaraphan & Abedin Forhad, 2015","Buaraphan, K.","Social Sciences"
"Kim & Choi, 2015","Yodyingyong, S.","Chemical Engineering"
"Kim & Choi, 2015","Yodyingyong, S.","Chemistry"
"Kim & Choi, 2015","Yodyingyong, S.","Engineering"
"Kim & Choi, 2015","Yodyingyong, S.","Materials Science"
"Kim & Choi, 2015","Yodyingyong, S.","Physics and Astronomy"
"Bretz & McClary, 2015","Ratanaroutai, T.","Chemistry"
"Bretz & McClary, 2015","Ratanaroutai, T.","Social Sciences"
"Panijpan et al., 2015","Sriwattanarothai, N.","Biochemistry, Genetics and Molecular Biology"
"Panijpan et al., 2015","Sriwattanarothai, N.","Medicine"
"Durand & Borsa, 2015","Sriwattanarothai, N.","Agricultural and Biological Sciences"
"Durand & Borsa, 2015","Sriwattanarothai, N.","Biochemistry, Genetics and Molecular Biology"
"Durand & Borsa, 2015","Sriwattanarothai, N.","Immunology and Microbiology"
"Durand & Borsa, 2015","Sriwattanarothai, N.","Medicine"
"Vu et al., 2015","Yodyingyong, S.","Chemical Engineering"
"Vu et al., 2015","Yodyingyong, S.","Environmental Science"
"Chang et al., 2015","Yodyingyong, S.","Materials Science"
"Zhang et al., 2015","Ketpichainarong, W.","Social Sciences"
"Buaraphan & Abedin Forhad, 2015","Buaraphan, K.","Social Sciences"
"Cil, 2015","Buaraphan, K.","Social Sciences"
"Buaraphan & Abedin Forhad, 2015","Buaraphan, K.","Social Sciences"
"Di Russo et al., 2015","Chenprakhon, P.","Biochemistry, Genetics and Molecular Biology"
"De Sancho et al., 2015","Chenprakhon, P.","Chemistry"
"De Sancho et al., 2015","Chenprakhon, P.","Computer Science"
"Cazade et al., 2015","Chenprakhon, P.","Chemistry"
"Cazade et al., 2015","Chenprakhon, P.","Medicine"
"Cazade et al., 2015","Chenprakhon, P.","Physics and Astronomy"
但我想以椭圆形而不是圆形显示和弦。任何人都知道这怎么可能?非常感谢您的帮助。
首先,弦不是画成圆,而是画成贝塞尔曲线,在画的中心有一个控制点(有点像圆)。我建议将两个控制点放置在靠近边缘的位置以获得 "ellipse-like" 效果。
我不确定如何从头开始绘制这样的弧线,但可以在绘制后编辑路径的 d
属性。
这是我的 editPath
函数:
function editPath() {
var ratio = 0.6;
var path=d3.select(this).attr("d")
console.log(path);
find=path.match(/([\-\.0-9]+)\,([\-\.0-9]+)Q 0,0 ([\-\.0-9]+),([\-\.0-9]+)/);
if (!find) return;
path=path.replace(/Q 0,0/,"C "+find[1]*ratio+","+find[2]*ratio+" "+find[3]*ratio+","+find[4]*ratio);
console.log(path);
d3.select(this).attr("d", path)
}
此函数执行以下操作:
- 提取路径命令(
path
) - 识别以
0,0
为中心的贝塞尔曲线( - 提取起点和终点坐标(数组
find
) - 计算新控制点的坐标(find[i]*ratio)
- 将其注入新的贝塞尔曲线(有两个控制点,
C
) - 用新路径替换原来的路径
Q
)
这只会替换路径中的一条贝塞尔曲线,因此您需要为每个和弦调用两次:
[...]
.attr("class", "chord")
.attr("d", d3.svg.chord().radius(350))
.each(editPath).each(editPath) //call twice!
我在这个例子中测试了这个:http://bl.ocks.org/mbostock/raw/4062006/ ...它在那里工作,我希望它应该在使用 d3.svg.chord
的任何图表上工作。