Last active
February 13, 2022 09:20
-
-
Save unixpi/9a38c54405f2159a22ec to your computer and use it in GitHub Desktop.
sacha jessicat first month correspondence: noire et rouge (scarlet)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| (function(exports) { | |
| function cloud() { | |
| var size = [256, 256], | |
| text = cloudText, | |
| font = cloudFont, | |
| fontSize = cloudFontSize, | |
| 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) { | |
| return { | |
| text: text.call(this, d, i), | |
| font: font.call(this, d, i), | |
| rotate: rotate.call(this, d, i), | |
| size: ~~fontSize.call(this, d, i), | |
| padding: cloudPadding.call(this, d, i) | |
| }; | |
| }).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 (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.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 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.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); | |
| 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; | |
| x += w; | |
| } | |
| var pixels = c.getImageData(0, 0, (cw << 5) / ratio, ch / ratio).data, | |
| sprite = []; | |
| while (--di >= 0) { | |
| d = data[di]; | |
| var w = d.width, | |
| w32 = w >> 5, | |
| h = d.y1 - d.y0, | |
| p = d.padding; | |
| // 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; | |
| if (p) { | |
| if (j) sprite[k - w32] |= m; | |
| if (j < w - 1) sprite[k + w32] |= m; | |
| m |= (m << 1) | (m >> 1); | |
| } | |
| 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 { | |
| // node-canvas support | |
| var Canvas = require("canvas"); | |
| canvas = new Canvas(cw << 5, ch); | |
| } | |
| var c = canvas.getContext("2d"), | |
| spirals = { | |
| archimedean: archimedeanSpiral, | |
| rectangular: rectangularSpiral | |
| }; | |
| c.fillStyle = "red"; | |
| c.textAlign = "center"; | |
| exports.cloud = cloud; | |
| })(typeof exports === "undefined" ? d3.layout || (d3.layout = {}) : exports); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!doctype html> | |
| <html> | |
| <script charset="utf-8" src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script> | |
| <script src="shakewordcloud.js" type="text/javascript"></script> | |
| <script src="d3.layout.cloud.js" type="text/javascript"></script> | |
| <body onload="createWordCloud()"> | |
| </head> | |
| <body> | |
| <div id="vizcontainer"> | |
| <svg style="width:962px;height:502px;border:1px lightgray solid;" /> | |
| </div> | |
| </body> | |
| </html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| text | frequency | |
|---|---|---|
| managed | 1 | |
| walking | 5 | |
| woods | 1 | |
| sleep | 5 | |
| follow | 1 | |
| paris | 3 | |
| send | 2 | |
| finally | 2 | |
| sorry | 9 | |
| friendly | 1 | |
| deeper | 2 | |
| sitting | 1 | |
| very | 6 | |
| worst | 1 | |
| fall | 2 | |
| ticket | 1 | |
| watered | 1 | |
| leave | 1 | |
| sang | 1 | |
| quick | 1 | |
| havent | 1 | |
| enjoy | 1 | |
| says | 3 | |
| tired | 2 | |
| dealing | 2 | |
| discover | 1 | |
| messy | 1 | |
| pass | 1 | |
| shining | 1 | |
| even | 1 | |
| paintings | 1 | |
| giving | 1 | |
| sun | 1 | |
| sum | 1 | |
| fingers | 1 | |
| paying | 1 | |
| waiting | 2 | |
| goes | 2 | |
| reply | 1 | |
| told | 5 | |
| full | 2 | |
| here | 8 | |
| water | 2 | |
| packing | 1 | |
| let | 6 | |
| making | 1 | |
| alone | 1 | |
| path | 1 | |
| change | 2 | |
| wait | 3 | |
| great | 5 | |
| healthy | 1 | |
| root | 2 | |
| changed | 2 | |
| beaucoup | 1 | |
| leaving | 3 | |
| accomplished | 1 | |
| pick | 1 | |
| had | 2 | |
| makes | 1 | |
| love | 37 | |
| feelings | 1 | |
| brought | 1 | |
| raffel | 1 | |
| sparkling | 1 | |
| crisis | 2 | |
| from | 8 | |
| working | 2 | |
| hospital | 1 | |
| give | 1 | |
| rafa | 1 | |
| two | 4 | |
| next | 4 | |
| few | 1 | |
| live | 1 | |
| wondering | 1 | |
| kristian | 1 | |
| tell | 2 | |
| today | 4 | |
| more | 4 | |
| knows | 1 | |
| haha | 16 | |
| sister | 2 | |
| phone | 1 | |
| train | 2 | |
| everywhere | 1 | |
| far | 1 | |
| must | 1 | |
| town | 6 | |
| join | 7 | |
| hour | 2 | |
| this | 7 | |
| car | 3 | |
| ride | 1 | |
| des | 1 | |
| sucks | 1 | |
| pour | 1 | |
| morgan | 15 | |
| island | 1 | |
| meet | 7 | |
| closing | 1 | |
| arrive | 1 | |
| beautiful | 8 | |
| figure | 1 | |
| millier | 1 | |
| stressing | 1 | |
| something | 2 | |
| want | 17 | |
| phrase | 1 | |
| wonderful | 2 | |
| honest | 1 | |
| influenced | 1 | |
| needs | 1 | |
| recovery | 1 | |
| conversation | 1 | |
| rilke | 1 | |
| travel | 1 | |
| stayed | 1 | |
| how | 8 | |
| amazing | 2 | |
| answer | 2 | |
| wolf | 2 | |
| beach | 1 | |
| profile | 1 | |
| staying | 1 | |
| pleasure | 1 | |
| plans | 1 | |
| teleport | 1 | |
| xiringuito | 1 | |
| freezing | 1 | |
| after | 4 | |
| thankyou | 1 | |
| wrong | 1 | |
| pas | 2 | |
| coming | 1 | |
| effective | 1 | |
| light | 1 | |
| childhood | 2 | |
| octavia | 1 | |
| honestly | 1 | |
| things | 4 | |
| title | 1 | |
| dream | 1 | |
| order | 1 | |
| talk | 4 | |
| typical | 1 | |
| passages | 1 | |
| shoes | 1 | |
| josephine | 1 | |
| over | 1 | |
| sooo | 1 | |
| soon | 2 | |
| trade | 1 | |
| course | 1 | |
| terrace | 2 | |
| during | 1 | |
| cold | 3 | |
| still | 12 | |
| drinking | 2 | |
| before | 2 | |
| perfect | 1 | |
| le | 2 | |
| thank | 5 | |
| mais | 1 | |
| la | 5 | |
| somewhere | 2 | |
| interesting | 1 | |
| actually | 2 | |
| late | 4 | |
| absence | 2 | |
| degrees | 2 | |
| fid | 1 | |
| might | 1 | |
| selfie | 1 | |
| happened | 1 | |
| then | 3 | |
| them | 3 | |
| evening | 1 | |
| yo | 1 | |
| safe | 2 | |
| break | 2 | |
| they | 5 | |
| half | 2 | |
| day | 1 | |
| mushrooms | 1 | |
| didn | 4 | |
| rocks | 2 | |
| someone | 1 | |
| rock | 1 | |
| found | 2 | |
| side | 2 | |
| everyone | 2 | |
| doing | 1 | |
| house | 1 | |
| spanish | 5 | |
| idea | 2 | |
| aren | 1 | |
| ex | 1 | |
| forgot | 1 | |
| our | 4 | |
| happen | 1 | |
| worried | 5 | |
| message | 5 | |
| sunrise | 1 | |
| out | 9 | |
| try | 5 | |
| opened | 1 | |
| miss | 7 | |
| tried | 2 | |
| since | 1 | |
| looking | 1 | |
| philosophy | 1 | |
| turning | 1 | |
| shots | 1 | |
| free | 2 | |
| put | 1 | |
| attendant | 1 | |
| wanted | 2 | |
| grab | 1 | |
| couldn | 1 | |
| waiter | 1 | |
| steal | 1 | |
| could | 4 | |
| impose | 1 | |
| messages | 1 | |
| days | 4 | |
| british | 1 | |
| keep | 1 | |
| thing | 3 | |
| cures | 1 | |
| place | 2 | |
| uses | 1 | |
| messaged | 1 | |
| think | 11 | |
| already | 5 | |
| dont | 5 | |
| feel | 3 | |
| one | 8 | |
| done | 2 | |
| adopted | 1 | |
| another | 2 | |
| wasn | 3 | |
| toi | 1 | |
| sounds | 1 | |
| open | 1 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| function createWordCloud() { | |
| d3.csv("love.csv", function(data) {makeWordCloud(data)}) | |
| function makeWordCloud(data) { | |
| //use a scale rather than raw values for the font | |
| var wScale = d3.scale.linear().domain([0,60]).range([10,160]); | |
| var rRotation = d3.scale.linear().domain([0,1]).range([-20,20]); | |
| console.log(data); | |
| d3.layout.cloud() | |
| .size([962, 502]) | |
| .words(data) | |
| //take a random number between 0 and 1 and rotate by a corresponding angle | |
| //between -20 and 20 degrees | |
| .rotate(function() {return rRotation(Math.random())}) | |
| .fontSize(function(d) {return wScale(d.frequency);}) | |
| .on("end", paint) | |
| .start(); | |
| //the cloud layout is initialized using start(), when it's done it fires "end" and | |
| //runs whichever function "end" is associated with. | |
| //here we've assigned paint() to "end" which automatically passes the processed | |
| //dataset as the words variable | |
| function paint(words) { | |
| console.log(words); | |
| var wordCloudRoot = d3.select("svg") | |
| .append("g") | |
| .attr("id", "wordCloudG") | |
| .attr("transform", "translate(481,251)"); | |
| //create a text element inside the svg for each word | |
| wordCloudRoot.selectAll("text") | |
| .data(words) | |
| .enter() | |
| .append("text") | |
| .style("font-size", function(d) {return d.size + "px"; }) | |
| .style("fill", function(d) {return (d.text).length > 5 ? "black" : "#FF2400"}) | |
| .style("opacity", .75) | |
| .attr("text-anchor", "middle") | |
| .attr("transform", function(d) {return "translate(" + [d.x, d.y] + ")rotate(" + d.rotate + ")"}) | |
| .text(function(d) { return d.text; }); | |
| }; | |
| }; | |
| }; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment