2014-05-09 22 views
6

Io uso biblioteca wordcloud Jason Davies' per d3 (https://github.com/jasondavies/d3-cloud) e il mio problema è che le parole del sovrapposizione cloud.sovrapposizione in d3 wordcloud

Sono consapevole che ci sono già domande per quanto riguarda questo problema su stack overflow (e altri siti), ma nessuno di questi ha aiutato nel mio caso.

Nel seguente esempio io uso l'esempio nuvola dal sito di Jason Davies' e alterata solo poche cose:

  • ho letto le mie parole e le loro dimensioni da un file esterno.
  • Ho impostato la rotazione su 0. Tuttavia, l'angolo di rotazione non sembra fare la differenza.
  • Ho commentato il carattere "Impatto", per escludere eventuali problemi con il caricamento del font. (Non fa differenza neanche se.)

Ecco il mio codice:

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

Il testdata assomiglia a questo (le informazioni sul colore non viene utilizzato nell'esempio):

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 

Se eseguo lo script js con i dati di test, il mio word cloud esce con sovrapposizioni. A volte succede solo dopo alcune ricariche, ma è abbastanza frequente.

Altre persone hanno segnalato lo stesso problema e hanno scoperto che era correlato all'utilizzo di caratteri Web o al salto del parametro di rotazione. Questo non si applica nel mio esempio.

ho il sospetto che potrebbe essere correlato al fatto che ci sono molte parole per le dimensioni della tela, però, ho anche fatto i test in cui ho signficantly aumentato le dimensioni della tela e ancora capitato (anche se meno frequentemente, come il caso il posizionamento delle parole lo rendeva meno probabile). Oltre a ciò, è possibile vedere che diverse parole non vengono mostrate affatto a causa delle dimensioni ridotte della tela. Perché lasciare un po 'fuori e creare sovrapposizioni per gli altri? Quindi penso che il problema risieda altrove.

Qualche idea?

Grazie!

+0

convenuto che ci sono difficoltà. Tuttavia, giocando un po 'con le dimensioni (layout e svg) e la famiglia dei font, è possibile raggiungere solo sovrapposizioni occasionali e relativamente miti (ma quanto accettabili quelle sovrapposizioni possono essere un po' soggettive). In ogni caso, ecco un [plunk] (http://plnkr.co/edit/1In5m9Ot7nUPrNULOOYv?p=preview) che ho creato per giocarci. Per lo meno, credo che queste dimensioni siano migliorate con l'esclusione delle parole ... sembra che la maggior parte di esse sia presente (anche se avrebbero bisogno di essere tutte lì). – FernOfTheAndes

+0

Sì, grazie. Hai cambiato le dimensioni e il carattere per quanto vedo?Funziona abbastanza bene per l'esempio. Tuttavia, mi piacerebbe davvero risolvere il problema in generale. In realtà sono piuttosto sorpreso che ciò accada perché l'intero punto della parola nuvola dovrebbe essere quello di evitare sovrapposizioni e ho visto molte lodi per questo. – spaebrun

+0

Hai ragione. Questo è tutto ciò che ho fatto. E d'accordo con te, una soluzione generale è ciò che è necessario. Potremmo mancare qualcosa ... Non ho avuto il tempo di approfondire troppo profondamente. Potresti anche scrivere un'email a [Jason] (http://www.jasondavies.com). – FernOfTheAndes

risposta

14

Ho finito per chiedere a Jason Davies stesso ed è stato in realtà un errore piuttosto semplice: è necessario specificare la funzione di accesso al testo nella prima istruzione (non solo nella funzione "disegna"). Funziona se si aggiunge una linea come questa:

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

imbottitura funzionante. grazie – Adeel

+0

No, ha semplicemente ridimensionato la distribuzione delle parole sullo schermo e ha reso la casella ancora più piccola causando più sovrapposizioni – dresh

+0

* NUMERO COMUNE: * non ancorando il testo SVG al centro, '.attr (" text-anchor "," medio ")' –

0

ho provato un campione per giocherellare con, prega di dare un'occhiata. wordcloud without overlap

essenzialmente:

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