我使用Jason Davies' d3(https://github.com/jasondavies/d3-cloud)的wordcloud库,我的问题是云中的单词重叠。
我知道在堆栈溢出(和其他站点)上已经存在关于此问题的问题,但在我的情况下这些都没有帮助。
在下面的示例中,我使用了来自Jason Davies的示例云'网站只改变了一些事情:
这是我的代码:
<!DOCTYPE html>
<meta charset="utf-8">
<body>
<script src="d3.js"></script>
<script src="d3.layout.cloud.js"></script>
<script>
d3.tsv("testdata.txt",
function(error, data) {
var fill = d3.scale.category20();
d3.layout.cloud().size([300, 300])
.words(data)
.padding(1)
.rotate(function(d) { return 0; })
// .font("Impact")
.fontSize(function(d) { return d.size; })
.on("end", draw)
.start();
function draw(words) {
d3.select("body").append("svg")
.attr("width", 300)
.attr("height", 300)
.append("g")
.attr("transform", "translate(150,150)")
.selectAll("text")
.data(words)
.enter().append("text")
.style("font-size", function(d) { return d.size + "px"; })
// .style("font-family", "Impact")
.style("fill", function(d, i) { return fill(i); })
.attr("text-anchor", "middle")
.attr("transform", function(d) {
return "translate(" + [d.x, d.y] + ")rotate(" + d.rotate + ")";
})
.text(function(d) { return d.word; });
}
}
)
</script>
testdata看起来像这样(示例中没有使用颜色信息):
word size color
der 39 #a9a9a9
die 37 #a9a9a9
und 30 #a9a9a9
athenischen 29 #a9a9a9
Die 29 #a9a9a9
eine 28 #a9a9a9
, 27 #a9a9a9
einer 26 #a9a9a9
attischen 26 #a9a9a9
liberalen 26 #1e90ff
zur 25 #a9a9a9
athenische 24 #a9a9a9
christliche 23 #a9a9a9
attische 23 #a9a9a9
_START_ 22 #a9a9a9
reinen 22 #a9a9a9
englischen 21 #a9a9a9
oder 21 #a9a9a9
-- 21 #a9a9a9
radikalen 21 #a9a9a9
Q*M 21 #a9a9a9
Q*M 21 #a9a9a9
christlichen 20 #a9a9a9
schöne 20 #1e90ff
repräsentativen 20 #a9a9a9
sozialen 20 #a9a9a9
hellenische 19 #1e90ff
modernen 19 #a9a9a9
radikale 19 #a9a9a9
griechische 19 #a9a9a9
- 18 #a9a9a9
schönen 18 #1e90ff
alle 18 #a9a9a9
radicalen 18 #a9a9a9
als 17 #a9a9a9
neuen 17 #a9a9a9
perikleischen 16 #a9a9a9
bürgerlichen 16 #a9a9a9
Namen 16 #1e90ff
如果我用测试数据运行js脚本,我的文字云会出现重叠。有时它只会在重新加载后发生,但它很频繁。
其他人报告了同样的问题,发现它与使用网络字体或跳过rotate参数有关。这不适用于我的示例。
我怀疑它可能与画布大小有很多单词这一事实有关,但是,我也做了测试,我显着增加了画布尺寸并且它仍然发生(虽然不常见,随机放置这些话使它不太可能)。除此之外,由于画布尺寸较小,您可以看到几个单词都没有显示。为什么要留下一些并为其他人创造重叠?所以我认为问题出在其他地方。
有什么想法吗?
谢谢!
答案 0 :(得分:16)
我最后问了Jason Davies本人,这实际上是一个非常简单的错误:你必须在第一个语句中指定文本访问器函数(不仅仅是在&#34; draw&#34;函数中)。如果您添加如下所示的一行,它可以工作:
d3.layout.cloud().size([300, 300])
.words(data)
.padding(1)
.rotate(function(d) { return 0; })
// .font("Impact")
.text(function(d) { return d.word; }) // THE SOLUTION
.fontSize(function(d) { return d.size; })
.on("end", draw)
.start();
答案 1 :(得分:0)
我试过一个样本供你摆弄, 请看一看。 wordcloud without overlap
基本上:
<div id="cloud"></div>
// First define your cloud data, using `text` and `size` properties:
var fill = d3.scale.category20();
var words = {
"Battery Related": "52382",
"Billing": "52412",
"Break Related": "52490",
"Chain Related": "52471",
"Clutch Related": "52468",
"Dealer attitude": "52488",
"Electrical Related": "52352",
"Engine Related": "52446",
"Handle Bar Related": "52486",
"Happy": "52472",
"Jerking": "52325",
"Jerking Problem": "52325",
"Low Mileage": "52489",
"Noise": "52462",
"Poor Pickup": "52406",
"Running Off": "52242",
"Service Quality": "52488",
"Silencer Problem": "52468",
"Starting Trouble": "52490",
"Suspension Related": "52365",
"Vehicle Noise": "52467",
"Vibration": "52463",
"Washing": "52488"
};
var max_freq = 52490;
var cloudwords = ["Battery Related", "Billing", "Break Related", "Chain Related", "Clutch Related", "Dealer attitude", "Electrical Related", "Engine Related", "Handle Bar Related", "Happy", "Jerking", "Jerking Problem", "Low Mileage", "Noise", "Poor Pickup", "Running Off", "Service Quality", "Silencer Problem", "Starting Trouble", "Suspension Related", "Vehicle Noise", "Vibration", "Washing"];
var url = 'http://xxx.yyyy.zz.ww/?q=abc/';
var width = 800,
height = 800;
var leaders = cloudwords
.map(function(d) {
return {
text: d,
size: 5 + (words[d] / max_freq) * 0.9 * 30 // *the size of the "box" occupied by each word. has no relation to text size.
};
})
.sort(function(a, b) {
return d3.descending(a.size, b.size)
});
var leaderScale = d3.scale.linear().range([1, 20]); // *scale range to plot the relative sizes of the words.
leaderScale.domain([d3.min(leaders, function(d) {
return d.size;
}),
d3.max(leaders, function(d) {
return d.size;
})
]);
// Next you need to use the layout script to calculate the placement, rotation and size of each word:
d3.layout.cloud().size([width, height])
.words(leaders)
.padding(0) //fiddle with padding here, does not really have any effect on overlap.
.rotate(function() {
return ~~0; //to keep the words horizontal
})
.font("Impact")
.fontSize(function(d) {
return d.size;
})
.on("end", drawCloud)
.start();
function drawCloud(words) {
d3.select("#cloud").append("svg")
.attr("width", width)
.attr("height", height)
.attr("text-align", "center")
.append("g")
.attr("transform", "translate(" + [width >> 1, height >> 1] + ")") //for transalting words to their different postions.
.selectAll("text")
.data(words)
.enter().append("text")
.style("font-size", function(d) {
return leaderScale(d.size) + "px"; //used scale to resize words to a linear scale.
})
.style("font-family", "Impact")
.style("fill", function(d, i) {
return fill(i);
})
.attr("text-anchor", "middle")
.attr("transform", function(d) {
return "translate(" + [d.x, d.y] + ")rotate(" + d.rotate + ")";
})
.text(function(d) {
return d.text;
})
.on("click", function(d, i) {
window.open(url + d.text);
});
}
// set the viewbox to content bounding box (zooming in on the content, effectively trimming whitespace)
var svg = document.getElementsByTagName("svg")[0];
var bbox = svg.getBBox();
var viewBox = [bbox.x, bbox.y, bbox.width, bbox.height].join(" ");
svg.setAttribute("viewBox", viewBox);
答案 2 :(得分:0)
作者的修复对我不起作用。 d 的工作是在云布局设置中指定.font()
,并在绘图代码中声明相同的字体系列-讽刺的是,以上作者已将其注释掉。这为代码提供了用于计算尺寸的字体。没有它,就只能做出最佳猜测。
d3.layout.cloud().size([800, 400])
.words(words)
.font('Impact') // <-- what mattered
.fontSize(d => d.size)
.on('end', draw)
.start()
您还需要 在draw()
函数中指定字体系列,以便云以正确的字体呈现与您上面声明的字体匹配的单词:
.attr('font-family', 'Impact')