我目前正在 d3.js 中进行可视化,目标是可视化数据相似性。我希望通过为每个节点创建两个半圆并将比较数据放在这些半圆内来比较我的数据。我的数据由字符串组成(每个半圆接收一个句子)。
我目前的方法如下:
首先,我使用pack-layout创建我必要的节点数据。
var bubble = d3.pack().size([SVG_WIDTH,SVG_HEIGHT]).padding(CIRCLE_PADDING),
root = d3.hierarchy({children: COMPARISON_DATA}).sum(function(d){ return d.children ? 0 : d[2]});
var nodeData = bubble(root).children;
d[2] 是被放入半圆的两个句子的最大字符串长度,因此决定了圆的半径。
接下来,我遍历每个节点并创建相应的半圆。我已经删除了所有与我的问题无关的代码部分。
nodeData.forEach(function (data, index) {
//upperCircleGroup simply adds a small y-translate, so that the semicircles have a margin
var gUpper = upperCircleGroup.append("g");
var gLower = lowerCircleGroup.append("g");
var lowerCircle = gLower.append('path')
.attr('d', d3.arc()({
innerRadius: 0,
outerRadius: data.r,
startAngle: Math.PI / 2,
endAngle: 3 / 2 * Math.PI
}))
.attr('transform', `translate(${data.x},${data.y})`)
var upperCircle = gUpper.append('path')
.attr('d', d3.arc()({
innerRadius: 0,
outerRadius: data.r,
startAngle: 1 / 2 * Math.PI,
endAngle: - 1 / 2 * Math.PI
}))
.attr('transform', `translate(${data.x},${data.y})`)
var upperText = gUpper
.append("foreignObject")
.attr("width", () => {return data.r*Math.sqrt(2)})
.attr("height", () => {return data.r*(Math.sqrt(2)/2)})
.attr('transform', `translate(${data.x - (data.r / Math.sqrt(2))},${data.y - (data.r/Math.sqrt(2)) })`)
.text(() => {return data.data[0]})
var lowerText = gLower
.append("foreignObject")
.attr("width", () => {return data.r*Math.sqrt(2)})
.attr("height", () => {return data.r*(Math.sqrt(2)/2)})
.attr('transform', `translate(${data.x - (data.r / Math.sqrt(2))},${data.y })`)
.text(() => {return data.data[1]})
});
如您所见,我使用 d3 的弧线绘制半圆。现在这就是我的问题出现的地方。我在将文本内容放在弧内时遇到了麻烦,所以在搜索了一段时间后,我选择了这个解决方案,将一个 div 放在我的半圆内,然后接收文本。sqrt(2) 操作用于将正方形拟合到半圆中。
我对这个解决方案的问题是,有时,句子根本不适合 div 并且某些内容会丢失。有没有办法计算必要的字符串的字体大小,以便它适合给定大小的 div?如果可能的话,我可以简单地计算适当的字体大小并为可视化添加缩放选项。此外,如果有更好的方法来实现我想要做的事情,我也很乐意从你们那里得到一些反馈,因为在使用 d3 时我是一个完整的初学者。