Skip to content

Instantly share code, notes, and snippets.

@pkpp1233
Created December 11, 2014 01:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pkpp1233/1cf3f5350d16dd9141f8 to your computer and use it in GitHub Desktop.
Save pkpp1233/1cf3f5350d16dd9141f8 to your computer and use it in GitHub Desktop.
wordcloud
// Word cloud layout by Jason Davies, http://www.jasondavies.com/word-cloud/
// Algorithm due to Jonathan Feinberg, http://static.mrfeinberg.com/bv_ch03.pdf
(function() {
function cloud() {
var size = [256, 256],
text = cloudText,
font = cloudFont,
fontSize = cloudFontSize,
fontStyle = cloudFontNormal,
fontWeight = cloudFontNormal,
rotate = cloudRotate,
padding = cloudPadding,
spiral = archimedeanSpiral,
words = [],
timeInterval = Infinity,
event = d3.dispatch("word", "end"),
timer = null,
cloud = {};
cloud.start = function() {
var board = zeroArray((size[0] >> 5) * size[1]),
bounds = null,
n = words.length,
i = -1,
tags = [],
data = words.map(function(d, i) {
d.text = text.call(this, d, i);
d.font = font.call(this, d, i);
d.style = fontStyle.call(this, d, i);
d.weight = fontWeight.call(this, d, i);
d.rotate = rotate.call(this, d, i);
d.size = ~~fontSize.call(this, d, i);
d.padding = padding.call(this, d, i);
return d;
}).sort(function(a, b) { return b.size - a.size; });
if (timer) clearInterval(timer);
timer = setInterval(step, 0);
step();
return cloud;
function step() {
var start = +new Date,
d;
while (+new Date - start < timeInterval && ++i < n && timer) {
d = data[i];
d.x = (size[0] * (Math.random() + .5)) >> 1;
d.y = (size[1] * (Math.random() + .5)) >> 1;
cloudSprite(d, data, i);
if (d.hasText && place(board, d, bounds)) {
tags.push(d);
event.word(d);
if (bounds) cloudBounds(bounds, d);
else bounds = [{x: d.x + d.x0, y: d.y + d.y0}, {x: d.x + d.x1, y: d.y + d.y1}];
// Temporary hack
d.x -= size[0] >> 1;
d.y -= size[1] >> 1;
}
}
if (i >= n) {
cloud.stop();
event.end(tags, bounds);
}
}
}
cloud.stop = function() {
if (timer) {
clearInterval(timer);
timer = null;
}
return cloud;
};
cloud.timeInterval = function(x) {
if (!arguments.length) return timeInterval;
timeInterval = x == null ? Infinity : x;
return cloud;
};
function place(board, tag, bounds) {
var perimeter = [{x: 0, y: 0}, {x: size[0], y: size[1]}],
startX = tag.x,
startY = tag.y,
maxDelta = Math.sqrt(size[0] * size[0] + size[1] * size[1]),
s = spiral(size),
dt = Math.random() < .5 ? 1 : -1,
t = -dt,
dxdy,
dx,
dy;
while (dxdy = s(t += dt)) {
dx = ~~dxdy[0];
dy = ~~dxdy[1];
if (Math.min(dx, dy) > maxDelta) break;
tag.x = startX + dx;
tag.y = startY + dy;
if (tag.x + tag.x0 < 0 || tag.y + tag.y0 < 0 ||
tag.x + tag.x1 > size[0] || tag.y + tag.y1 > size[1]) continue;
// TODO only check for collisions within current bounds.
if (!bounds || !cloudCollide(tag, board, size[0])) {
if (!bounds || collideRects(tag, bounds)) {
var sprite = tag.sprite,
w = tag.width >> 5,
sw = size[0] >> 5,
lx = tag.x - (w << 4),
sx = lx & 0x7f,
msx = 32 - sx,
h = tag.y1 - tag.y0,
x = (tag.y + tag.y0) * sw + (lx >> 5),
last;
for (var j = 0; j < h; j++) {
last = 0;
for (var i = 0; i <= w; i++) {
board[x + i] |= (last << msx) | (i < w ? (last = sprite[j * w + i]) >>> sx : 0);
}
x += sw;
}
delete tag.sprite;
return true;
}
}
}
return false;
}
cloud.words = function(x) {
if (!arguments.length) return words;
words = x;
return cloud;
};
cloud.size = function(x) {
if (!arguments.length) return size;
size = [+x[0], +x[1]];
return cloud;
};
cloud.font = function(x) {
if (!arguments.length) return font;
font = d3.functor(x);
return cloud;
};
cloud.fontStyle = function(x) {
if (!arguments.length) return fontStyle;
fontStyle = d3.functor(x);
return cloud;
};
cloud.fontWeight = function(x) {
if (!arguments.length) return fontWeight;
fontWeight = d3.functor(x);
return cloud;
};
cloud.rotate = function(x) {
if (!arguments.length) return rotate;
rotate = d3.functor(x);
return cloud;
};
cloud.text = function(x) {
if (!arguments.length) return text;
text = d3.functor(x);
return cloud;
};
cloud.spiral = function(x) {
if (!arguments.length) return spiral;
spiral = spirals[x + ""] || x;
return cloud;
};
cloud.fontSize = function(x) {
if (!arguments.length) return fontSize;
fontSize = d3.functor(x);
return cloud;
};
cloud.padding = function(x) {
if (!arguments.length) return padding;
padding = d3.functor(x);
return cloud;
};
return d3.rebind(cloud, event, "on");
}
function cloudText(d) {
return d.text;
}
function cloudFont() {
return "serif";
}
function cloudFontNormal() {
return "normal";
}
function cloudFontSize(d) {
return Math.sqrt(d.value);
}
function cloudRotate() {
return (~~(Math.random() * 6) - 3) * 30;
}
function cloudPadding() {
return 1;
}
// Fetches a monochrome sprite bitmap for the specified text.
// Load in batches for speed.
function cloudSprite(d, data, di) {
if (d.sprite) return;
c.clearRect(0, 0, (cw << 5) / ratio, ch / ratio);
var x = 0,
y = 0,
maxh = 0,
n = data.length;
--di;
while (++di < n) {
d = data[di];
c.save();
c.font = d.style + " " + d.weight + " " + ~~((d.size + 1) / ratio) + "px " + d.font;
var w = c.measureText(d.text + "m").width * ratio,
h = d.size << 1;
if (d.rotate) {
var sr = Math.sin(d.rotate * cloudRadians),
cr = Math.cos(d.rotate * cloudRadians),
wcr = w * cr,
wsr = w * sr,
hcr = h * cr,
hsr = h * sr;
w = (Math.max(Math.abs(wcr + hsr), Math.abs(wcr - hsr)) + 0x1f) >> 5 << 5;
h = ~~Math.max(Math.abs(wsr + hcr), Math.abs(wsr - hcr));
} else {
w = (w + 0x1f) >> 5 << 5;
}
if (h > maxh) maxh = h;
if (x + w >= (cw << 5)) {
x = 0;
y += maxh;
maxh = 0;
}
if (y + h >= ch) break;
c.translate((x + (w >> 1)) / ratio, (y + (h >> 1)) / ratio);
if (d.rotate) c.rotate(d.rotate * cloudRadians);
c.fillText(d.text, 0, 0);
if (d.padding) c.lineWidth = 2 * d.padding, c.strokeText(d.text, 0, 0);
c.restore();
d.width = w;
d.height = h;
d.xoff = x;
d.yoff = y;
d.x1 = w >> 1;
d.y1 = h >> 1;
d.x0 = -d.x1;
d.y0 = -d.y1;
d.hasText = true;
x += w;
}
var pixels = c.getImageData(0, 0, (cw << 5) / ratio, ch / ratio).data,
sprite = [];
while (--di >= 0) {
d = data[di];
if (!d.hasText) continue;
var w = d.width,
w32 = w >> 5,
h = d.y1 - d.y0;
// Zero the buffer
for (var i = 0; i < h * w32; i++) sprite[i] = 0;
x = d.xoff;
if (x == null) return;
y = d.yoff;
var seen = 0,
seenRow = -1;
for (var j = 0; j < h; j++) {
for (var i = 0; i < w; i++) {
var k = w32 * j + (i >> 5),
m = pixels[((y + j) * (cw << 5) + (x + i)) << 2] ? 1 << (31 - (i % 32)) : 0;
sprite[k] |= m;
seen |= m;
}
if (seen) seenRow = j;
else {
d.y0++;
h--;
j--;
y++;
}
}
d.y1 = d.y0 + seenRow;
d.sprite = sprite.slice(0, (d.y1 - d.y0) * w32);
}
}
// Use mask-based collision detection.
function cloudCollide(tag, board, sw) {
sw >>= 5;
var sprite = tag.sprite,
w = tag.width >> 5,
lx = tag.x - (w << 4),
sx = lx & 0x7f,
msx = 32 - sx,
h = tag.y1 - tag.y0,
x = (tag.y + tag.y0) * sw + (lx >> 5),
last;
for (var j = 0; j < h; j++) {
last = 0;
for (var i = 0; i <= w; i++) {
if (((last << msx) | (i < w ? (last = sprite[j * w + i]) >>> sx : 0))
& board[x + i]) return true;
}
x += sw;
}
return false;
}
function cloudBounds(bounds, d) {
var b0 = bounds[0],
b1 = bounds[1];
if (d.x + d.x0 < b0.x) b0.x = d.x + d.x0;
if (d.y + d.y0 < b0.y) b0.y = d.y + d.y0;
if (d.x + d.x1 > b1.x) b1.x = d.x + d.x1;
if (d.y + d.y1 > b1.y) b1.y = d.y + d.y1;
}
function collideRects(a, b) {
return a.x + a.x1 > b[0].x && a.x + a.x0 < b[1].x && a.y + a.y1 > b[0].y && a.y + a.y0 < b[1].y;
}
function archimedeanSpiral(size) {
var e = size[0] / size[1];
return function(t) {
return [e * (t *= .1) * Math.cos(t), t * Math.sin(t)];
};
}
function rectangularSpiral(size) {
var dy = 4,
dx = dy * size[0] / size[1],
x = 0,
y = 0;
return function(t) {
var sign = t < 0 ? -1 : 1;
// See triangular numbers: T_n = n * (n + 1) / 2.
switch ((Math.sqrt(1 + 4 * sign * t) - sign) & 3) {
case 0: x += dx; break;
case 1: y += dy; break;
case 2: x -= dx; break;
default: y -= dy; break;
}
return [x, y];
};
}
// TODO reuse arrays?
function zeroArray(n) {
var a = [],
i = -1;
while (++i < n) a[i] = 0;
return a;
}
var cloudRadians = Math.PI / 180,
cw = 1 << 11 >> 5,
ch = 1 << 11,
canvas,
ratio = 1;
if (typeof document !== "undefined") {
canvas = document.createElement("canvas");
canvas.width = 1;
canvas.height = 1;
ratio = Math.sqrt(canvas.getContext("2d").getImageData(0, 0, 1, 1).data.length >> 2);
canvas.width = (cw << 5) / ratio;
canvas.height = ch / ratio;
} else {
// Attempt to use node-canvas.
canvas = new Canvas(cw << 5, ch);
}
var c = canvas.getContext("2d"),
spirals = {
archimedean: archimedeanSpiral,
rectangular: rectangularSpiral
};
c.fillStyle = c.strokeStyle = "red";
c.textAlign = "center";
if (typeof module === "object" && module.exports) module.exports = cloud;
else (d3.layout || (d3.layout = {})).cloud = cloud;
})();
<html>
<head>
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script src="cloud.js"></script>
</head>
<body>
<script>
var cloud = d3.layout.cloud;
(function(){
var text = "\nAll's Well That Ends Well\nShakespeare homepage | All's Well That Ends Well | Act 1, Scene 1 \nNext scene\nSCENE I. Rousillon. The COUNT's palace.\n\nEnter BERTRAM, the COUNTESS of Rousillon, HELENA, and LAFEU, all in black\nCOUNTESS\nIn delivering my son from me, I bury a second husband.\nBERTRAM\nAnd I in going, madam, weep o'er my father's death\nanew: but I must attend his majesty's command, to\nwhom I am now in ward, evermore in subjection.\nLAFEU\nYou shall find of the king a husband, madam; you,\nsir, a father: he that so generally is at all times\ngood must of necessity hold his virtue to you; whose\nworthiness would stir it up where it wanted rather\nthan lack it where there is such abundance.\nCOUNTESS\nWhat hope is there of his majesty's amendment?\nLAFEU\nHe hath abandoned his physicians, madam; under whose\npractises he hath persecuted time with hope, and\nfinds no other advantage in the process but only the\nlosing of hope by time.\nCOUNTESS\nThis young gentlewoman had a father,--O, that\n'had'! how sad a passage 'tis!--whose skill was\nalmost as great as his honesty; had it stretched so\nfar, would have made nature immortal, and death\nshould have play for lack of work. Would, for the\nking's sake, he were living! I think it would be\nthe death of the king's disease.\nLAFEU\nHow called you the man you speak of, madam?\nCOUNTESS\nHe was famous, sir, in his profession, and it was\nhis great right to be so: Gerard de Narbon.\nLAFEU\nHe was excellent indeed, madam: the king very\nlately spoke of him admiringly and mourningly: he\nwas skilful enough to have lived still, if knowledge\ncould be set up against mortality.\nBERTRAM\nWhat is it, my good lord, the king languishes of?\nLAFEU\nA fistula, my lord.\nBERTRAM\nI heard not of it before.\nLAFEU\nI would it were not notorious. Was this gentlewoman\nthe daughter of Gerard de Narbon?\nCOUNTESS\nHis sole child, my lord, and bequeathed to my\noverlooking. I have those hopes of her good that\nher education promises; her dispositions she\ninherits, which makes fair gifts fairer; for where\nan unclean mind carries virtuous qualities, there\ncommendations go with pity; they are virtues and\ntraitors too; in her they are the better for their\nsimpleness; she derives her honesty and achieves her goodness.\nLAFEU\nYour commendations, madam, get from her tears.\nCOUNTESS\n'Tis the best brine a maiden can season her praise\nin. The remembrance of her father never approaches\nher heart but the tyranny of her sorrows takes all\nlivelihood from her cheek. No more of this, Helena;\ngo to, no more; lest it be rather thought you affect\na sorrow than have it.\nHELENA\nI do affect a sorrow indeed, but I have it too.\nLAFEU\nModerate lamentation is the right of the dead,\nexcessive grief the enemy to the living.\nCOUNTESS\nIf the living be enemy to the grief, the excess\nmakes it soon mortal.\nBERTRAM\nMadam, I desire your holy wishes.\nLAFEU\nHow understand we that?\nCOUNTESS\nBe thou blest, Bertram, and succeed thy father\nIn manners, as in shape! thy blood and virtue\nContend for empire in thee, and thy goodness\nShare with thy birthright! Love all, trust a few,\nDo wrong to none: be able for thine enemy\nRather in power than use, and keep thy friend\nUnder thy own life's key: be cheque'd for silence,\nBut never tax'd for speech. What heaven more will,\nThat thee may furnish and my prayers pluck down,\nFall on thy head! Farewell, my lord;\n'Tis an unseason'd courtier; good my lord,\nAdvise him.\nLAFEU\nHe cannot want the best\nThat shall attend his love.\nCOUNTESS\nHeaven bless him! Farewell, Bertram.\nExit\n\nBERTRAM\n[To HELENA] The best wishes that can be forged in\nyour thoughts be servants to you! Be comfortable\nto my mother, your mistress, and make much of her.\nLAFEU\nFarewell, pretty lady: you must hold the credit of\nyour father.\nExeunt BERTRAM and LAFEU\n\nHELENA\nO, were that all! I think not on my father;\nAnd these great tears grace his remembrance more\nThan those I shed for him. What was he like?\nI have forgot him: my imagination\nCarries no favour in't but Bertram's.\nI am undone: there is no living, none,\nIf Bertram be away. 'Twere all one\nThat I should love a bright particular star\nAnd think to wed it, he is so above me:\nIn his bright radiance and collateral light\nMust I be comforted, not in his sphere.\nThe ambition in my love thus plagues itself:\nThe hind that would be mated by the lion\nMust die for love. 'Twas pretty, though plague,\nTo see him every hour; to sit and draw\nHis arched brows, his hawking eye, his curls,\nIn our heart's table; heart too capable\nOf every line and trick of his sweet favour:\nBut now he's gone, and my idolatrous fancy\nMust sanctify his reliques. Who comes here?\nEnter PAROLLES\n\nAside\n\nOne that goes with him: I love him for his sake;\nAnd yet I know him a notorious liar,\nThink him a great way fool, solely a coward;\nYet these fixed evils sit so fit in him,\nThat they take place, when virtue's steely bones\nLook bleak i' the cold wind: withal, full oft we see\nCold wisdom waiting on superfluous folly.\nPAROLLES\nSave you, fair queen!\nHELENA\nAnd you, monarch!\nPAROLLES\nNo.\nHELENA\nAnd no.\nPAROLLES\nAre you meditating on virginity?\nHELENA\nAy. You have some stain of soldier in you: let me\nask you a question. Man is enemy to virginity; how\nmay we barricado it against him?\nPAROLLES\nKeep him out.\nHELENA\nBut he assails; and our virginity, though valiant,\nin the defence yet is weak: unfold to us some\nwarlike resistance.\nPAROLLES\nThere is none: man, sitting down before you, will\nundermine you and blow you up.\nHELENA\nBless our poor virginity from underminers and\nblowers up! Is there no military policy, how\nvirgins might blow up men?\nPAROLLES\nVirginity being blown down, man will quicklier be\nblown up: marry, in blowing him down again, with\nthe breach yourselves made, you lose your city. It\nis not politic in the commonwealth of nature to\npreserve virginity. Loss of virginity is rational\nincrease and there was never virgin got till\nvirginity was first lost. That you were made of is\nmetal to make virgins. Virginity by being once lost\nmay be ten times found; by being ever kept, it is\never lost: 'tis too cold a companion; away with 't!\nHELENA\nI will stand for 't a little, though therefore I die a virgin.\nPAROLLES\nThere's little can be said in 't; 'tis against the\nrule of nature. To speak on the part of virginity,\nis to accuse your mothers; which is most infallible\ndisobedience. He that hangs himself is a virgin:\nvirginity murders itself and should be buried in\nhighways out of all sanctified limit, as a desperate\noffendress against nature. Virginity breeds mites,\nmuch like a cheese; consumes itself to the very\nparing, and so dies with feeding his own stomach.\nBesides, virginity is peevish, proud, idle, made of\nself-love, which is the most inhibited sin in the\ncanon. Keep it not; you cannot choose but loose\nby't: out with 't! within ten year it will make\nitself ten, which is a goodly increase; and the\nprincipal itself not much the worse: away with 't!\nHELENA\nHow might one do, sir, to lose it to her own liking?\nPAROLLES\nLet me see: marry, ill, to like him that ne'er it\nlikes. 'Tis a commodity will lose the gloss with\nlying; the longer kept, the less worth: off with 't\nwhile 'tis vendible; answer the time of request.\nVirginity, like an old courtier, wears her cap out\nof fashion: richly suited, but unsuitable: just\nlike the brooch and the tooth-pick, which wear not\nnow. Your date is better in your pie and your\nporridge than in your cheek; and your virginity,\nyour old virginity, is like one of our French\nwithered pears, it looks ill, it eats drily; marry,\n'tis a withered pear; it was formerly better;\nmarry, yet 'tis a withered pear: will you anything with it?\nHELENA\nNot my virginity yet [ ]\nThere shall your master have a thousand loves,\nA mother and a mistress and a friend,\nA phoenix, captain and an enemy,\nA guide, a goddess, and a sovereign,\nA counsellor, a traitress, and a dear;\nHis humble ambition, proud humility,\nHis jarring concord, and his discord dulcet,\nHis faith, his sweet disaster; with a world\nOf pretty, fond, adoptious christendoms,\nThat blinking Cupid gossips. Now shall he--\nI know not what he shall. God send him well!\nThe court's a learning place, and he is one--\nPAROLLES\nWhat one, i' faith?\nHELENA\nThat I wish well. 'Tis pity--\nPAROLLES\nWhat's pity?\nHELENA\nThat wishing well had not a body in't,\nWhich might be felt; that we, the poorer born,\nWhose baser stars do shut us up in wishes,\nMight with effects of them follow our friends,\nAnd show what we alone must think, which never\nReturn us thanks.\nEnter Page\n\nPage\nMonsieur Parolles, my lord calls for you.\nExit\n\nPAROLLES\nLittle Helen, farewell; if I can remember thee, I\nwill think of thee at court.\nHELENA\nMonsieur Parolles, you were born under a charitable star.\nPAROLLES\nUnder Mars, I.\nHELENA\nI especially think, under Mars.\nPAROLLES\nWhy under Mars?\nHELENA\nThe wars have so kept you under that you must needs\nbe born under Mars.\nPAROLLES\nWhen he was predominant.\nHELENA\nWhen he was retrograde, I think, rather.\nPAROLLES\nWhy think you so?\nHELENA\nYou go so much backward when you fight.\nPAROLLES\nThat's for advantage.\nHELENA\nSo is running away, when fear proposes the safety;\nbut the composition that your valour and fear makes\nin you is a virtue of a good wing, and I like the wear well.\nPAROLLES\nI am so full of businesses, I cannot answer thee\nacutely. I will return perfect courtier; in the\nwhich, my instruction shall serve to naturalize\nthee, so thou wilt be capable of a courtier's\ncounsel and understand what advice shall thrust upon\nthee; else thou diest in thine unthankfulness, and\nthine ignorance makes thee away: farewell. When\nthou hast leisure, say thy prayers; when thou hast\nnone, remember thy friends; get thee a good husband,\nand use him as he uses thee; so, farewell.\nExit\n\nHELENA\nOur remedies oft in ourselves do lie,\nWhich we ascribe to heaven: the fated sky\nGives us free scope, only doth backward pull\nOur slow designs when we ourselves are dull.\nWhat power is it which mounts my love so high,\nThat makes me see, and cannot feed mine eye?\nThe mightiest space in fortune nature brings\nTo join like likes and kiss like native things.\nImpossible be strange attempts to those\nThat weigh their pains in sense and do suppose\nWhat hath been cannot be: who ever strove\nSo show her merit, that did miss her love?\nThe king's disease--my project may deceive me,\nBut my intents are fix'd and will not leave me.\nExit\n\nShakespeare homepage | All's Well That Ends Well | Act 1, Scene 1 \nNext scene",
width = 500,
height = 300,
rotate_words = true,
unique_word_counts = {};
var wordmap = processText(text);
var svg = d3.select('body').html('').append('svg');
drawCloud(wordmap, width, height, svg, rotate_words, complete);
function complete(body){
console.log("I am done");
console.log(body);
}
})();
function processText(text){
var unique_word_counts = {},
exclude_words = "i,me,my,myself,we,us,our,ours,ourselves,you,your,yours,yourself,yourselves,he,him,his,himself,she,her,hers,herself,it,its,itself,they,them,their,theirs,themselves,what,which,who,whom,whose,this,that,these,those,am,is,are,was,were,be,been,being,have,has,had,having,do,does,did,doing,will,would,should,can,could,ought,i'm,you're,he's,she's,it's,we're,they're,i've,you've,we've,they've,i'd,you'd,he'd,she'd,we'd,they'd,i'll,you'll,he'll,she'll,we'll,they'll,isn't,aren't,wasn't,weren't,hasn't,haven't,hadn't,doesn't,don't,didn't,won't,wouldn't,shan't,shouldn't,can't,cannot,couldn't,mustn't,let's,that's,who's,what's,here's,there's,when's,where's,why's,how's,a,an,the,and,but,if,or,because,as,until,while,of,at,by,for,with,about,against,between,into,through,during,before,after,above,below,to,from,up,upon,down,in,out,on,off,over,under,again,further,then,once,here,there,when,where,why,how,all,any,both,each,few,more,most,other,some,such,no,nor,not,only,own,same,so,than,too,very,say,says,said,poop,shall";
var tokenized_text = text.split(/[ '\-\(\)\*":;\[\]|{},.!?]+/);
tokenized_text.forEach(function(raw_word){
var word = raw_word.toLowerCase();
if (word != "" && exclude_words.indexOf(word)==-1 && word.length>1){
word in unique_word_counts ?
unique_word_counts[word]++ :
(unique_word_counts[word] = 1 + Math.random());
}
});
var wordmap = d3.entries(unique_word_counts).sort(function(a,b){
return b.value - a.value;
});
return wordmap;
}
function drawCloud(wordmap, width, height, svg, rotate_words, callback){
var max = Math.min(width / 5, height / 5, 100),
font_size = d3.scale.linear()
.domain([ 1, d3.max( wordmap, function(d) { return d.value; })])
.range([max / 10, max]),
fill = d3.scale.category20();
cloud().size([width, height])
.words(wordmap)
.timeInterval(20)
.padding(2)
.spiral("rectangular")
.fontSize(function(d) { return font_size(d.value); })
.font("Impact")
.text(function(d) { return d.key; })
.rotate(function() {
return rotate_words ? (~~(Math.random() * 2) * 90) : 0;
})
.on("end", function(words){
cloud().stop();
svg
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + [width >> 1, height >> 1] + ")")
.selectAll("text")
.data(words)
.enter().append("text")
.style("font-family", "Impact")
.style("font-size", function(d) { return font_size(d.value) + "px"; })
.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.key; });
})
.start();
callback(d3.select('body'));
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment