2014-05-09 84 views
6

我使用Jason Davies的dcl的wordcloud庫(https://github.com/jasondavies/d3-cloud),我的問題是雲中的單詞重疊。d3 wordcloud中的重疊

我知道這個問題已經有關於堆棧溢出(和其他網站)的問題,但沒有一個在我的情況幫助。

在下面的例子中我使用賈森戴維斯的網站例如雲和改變只有幾件事情:

  • 我讀我的文字和它們的大小從外部文件。
  • 我把旋轉設置爲0.雖然旋轉角度似乎沒有什麼區別。
  • 我將「Impact」字體註釋掉,以排除加載字體的任何問題。 (這沒有什麼區別要麼雖然。)

這裏是我的代碼:

<!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

一致認爲有困難。然而,玩一些尺寸(佈局和svg)和字體系列,可能只是偶爾和相對溫和的重疊(但這些重疊可以接受的可能有點主觀)。無論如何,這裏是我創建的一個[plunk](http://plnkr.co/edit/1In5m9Ot7nUPrNULOOYv?p=preview)。至少,我相信這些維度在排除詞語後有所改善......看起來他們大多數人都在那裏(儘管他們需要所有人都在那裏)。 – FernOfTheAndes

+0

是的,謝謝。據我所知,您改變了尺寸和字體?對於這個例子它確實工作得很好。不過,我真的想解決一般問題。實際上,我感到非常驚訝,因爲雲佈局這個詞的整個意思應該是避免重疊,我看到了很多讚譽。 – spaebrun

+0

你說得對。這就是我所做的一切。並同意你的看法,一般的解決方案就是所需要的。我們可能會錯過一些東西......我沒有時間深入研究它。你也可以寫信給[Jason](http://www.jasondavies.com)。 – FernOfTheAndes

回答

14

我最終要求Jason Davies自己,這實際上是一個非常簡單的錯誤:您必須在第一條語句中指定文本存取器函數(不僅在「draw」函數中)。

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(); 
+0

填充工作。感謝 – Adeel

+0

不,它只是調整大小的屏幕上的字的分佈和製成的箱體更小造成更多的重疊 – dresh

+0

*常見的問題:*沒有固定的SVG的文本到中心,'.attr(「文本錨」,「中間「)' –

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);