The first thing to do is find the height and width on the screen of each word. This response in SOEN shows a possible path (create a div
with the word and measure your clientWidth
and clientHeight
).
var palavras = [];
var larguraTotal = 0;
var alturaMaxima = 0;
$('li').each(function() {
palavras.push({
elemento:this,
largura:this.clientWidth,
altura:this.clientHeight
});
larguraTotal += this.clientWidth;
alturaMaxima = Math.max(alturaMaxima, this.clientHeight);
});
Once you've done this, you need to figure out the "harmonious" way of spreading your words on the screen (i.e. not letting them "tight" horizontally and "slack" vertically, or vice versa). One way - not necessarily the best one - would be:
var linhas = 0;
do {
linhas++;
var horizontal = larguraTotal / linhas / larguraConteiner;
var vertical = linhas * alturaMaxima / alturaConteiner;
} while ( vertical < horizontal*0.8 ); // Esse 0.8 é uma "folga"
Now it's problem of the backpack ! Well, almost ... You need to choose, for each line, a set of words that approaches the desired width (% with%). I suggest starting with the larger ones, as it is easier to fit smaller ones later.
var distribuicao = [];
for ( var i = 0 ; i < linhas ; i++ )
distribuicao.push({ palavras:[], larguraTotal:0 });
function minima() {
var min = 0;
for ( var i = 1 ; i < distribuicao.length ; i++ )
if ( distribuicao[i].larguraTotal < distribuicao[min].larguraTotal )
min = i;
return distribuicao[min];
}
palavras.sort(function(a,b) { return b.largura - a.largura; });
for ( var i = 0 ; i < palavras.length ; i++ ) {
var min = minima();
min.palavras.push(palavras[i]);
min.larguraTotal += palavras[i].largura;
}
Finally, let's distribute the words across the screen. I will do this using absolute positioning, but you can think of it in another way too.
var alturaSobrando = alturaConteiner - linhas*alturaMaxima;
var alturaAntes = alturaSobrando / linhas / 2;
for ( var i = 0 ; i < distribuicao.length ; i++ ) {
var larguraSobrando = larguraConteiner - distribuicao[i].larguraTotal;
var larguraAntes = larguraSobrando / distribuicao[i].palavras.length / 2;
var top = alturaAntes + i*(2*alturaAntes + alturaMaxima);
var left = larguraAntes;
for ( var t = 0 ; t < distribuicao[i].palavras.length ; t++ ) {
var palavra = distribuicao[i].palavras[t];
$(palavra.elemento).css({
position: "absolute",
top: top,
left: left
});
left += 2*larguraAntes + palavra.largura;
}
}
Well homogenous, no ? We now have room to maneuver to randomize each word. There is a space of larguraConteiner * horizontal
before and after each word. Same for larguraAntes
. I'm going to use half of that space (here you evaluate what's interesting, aesthetically speaking, in my opinion using the whole space left the appearance a bit bizarre).
top: top + Math.floor(Math.random()*alturaAntes - alturaAntes/2),
left: left + Math.floor(Math.random()*larguraAntes - larguraAntes/2)
End result . Each of these steps can be improved, if you wish, I did not spend much time with each of them not. Also, some limit conditions I believe may be bugged (for example, when testing using the whole space, some words have left out of the container) - but in the above example I believe this does not occur.