Panzorfork Posted September 3, 2013 Hey all, Just before going to bed on Friday night, I had a stupid idea for a script that would take the various tags on a page and animate them to render a string. That night at 4AM I woke up with a bit of insomnia (probably induced by drinking a 36 ounce bottle of Moxie in the hours leading up to bed and being over excited at recently getting a new job, idk though). Before finally getting back to sleep at 6AM, I ended up writing a pretty stupid script. Behold: breckon.js To run, navigate to idlethumbs.net in either Chrome or Firefox and open the developer console (in Chrome F12, then click "Console", in Firefox Control-Shift-K), then copy and paste the entire breckon.js script into the console and press enter. A technical breakdown of my lazy javascript for people who are slightly weary of running random javascript (or just interested): Line numbers at represented by [number], ie: [53]. Please note also that this script was written at 4AM and not really improved or fixed very much (beyond getting it to work), so there may be some extraneous / misnamed variables etc. loadScript is a function I wrote a while back to load up javascript [3], it's pretty bad, but it works. You'll notice the breckon function contains an IIFE (Immediately Invoked Function Expression) [50], then the jQuery ready function shorthand [51]. I added the IIFE around the ready function for pages that may not be compatible with jQuery (not that this script is very nice to page, but hey). I create a large canvas [70], set the body background color to gray [74] (so you can more clearly see what's going on), grab the window [78] (actually the document, w/e), setup the message [82], check to see if the "otherMessage" parameter has been set [84] (in the wrapping IIFE) and set the text size [88]. Fill the canvas with white [90], set the fill style to black and set the font style / font [95], measure the text width [98], use a hack to get the approximate text height [99], and render the text on the canvas [105]. I get the amount I'll need to scale the text compared to the document width [107], grab the pixel data [109] then start a double for loop to loop through each of the pixels in the canvas [113]. I get the offset for each pixel by multiplying the y value by the imageWidth (since it's a one dimensional array), then add the x value to get the proper x/y index [115] (which gets multiplied by 4 because pixel information is held in sets of 4 (red, green, blue, alpha all 0-225 values)). I then check to see if each color is equal to 0, meaning black [120]. If the pixel is black, I check to see if the firstPoint has been found yet [121] and store it if it hasn't, then I push the current pixel location into the points array relative to the firstPoint [128] (such that the value of the first pixel will be 0, 0). I select a good deal of tags [149] (I really just should have used $("*"), but w/e) and store them for later use. I create the empty elems array for later use [150]. I check to see if the currentPointIndex is greater than the points.length [157] and set the index back to 0 if it is; this creates the looped rendering of the message. I check if there are no more tags in the elems array and call selected.toArray() to fill it back up [163] (this was pretty lazy and a waste of memory, yay!). I pop the last tag off the elems array and throw it into jQuery to get the selector representation [167], get the current point to use [169] and increment the currentPointIndex [170]. I then call .offset() on the selector to get the top and left values for the tag relative to the top / left of the document [172], such that when I detach [175] and re-add [177] them with absolute positioning, they'll (mostly) look like they are being animated from where they were previously sitting. I then set their CSS such that they can be animated [180], look to be where they were previously [182], are only 10px wide / tall [184], should be above everything else [186] and won't have any overflow [187]. After the tags are moved roughly to where they previously were, I call .animate() on the selected tag and tell it to move to the scaled point that represents a black pixel of the message [196]. In the .animate() call, besides setting the duration, I also give it the "callbackLoop" function to use as the always callback [201] (which always gets called once the animation completes, whether or not it succeeded). I unnecessarily increment the zIndex variable, because that does nothing and I was tired [203]. Once all that is setup, I call "callbackLoop" to kick the whole thing off [207], and remove the canvas I used to render the message [209]. There, now you know how the sausage is made, I hope you're happy, because I certainly am, Congrats Nick Breckon Edited: Changed the Chrome instructions to be a bit more clear Share this post Link to post Share on other sites
osmosisch Posted September 3, 2013 This is hilarious and awesome. More insomnia please Share this post Link to post Share on other sites
Patrick R Posted September 3, 2013 Can someone screencap what this does? I can't quite figure out how to use it. Share this post Link to post Share on other sites
osmosisch Posted September 3, 2013 It doesn't really lend itself to screenshotting well. Basically the entire website is disassembled into tiny bits, then these bits form the slowly animating message Congrats Nick Breckon. Share this post Link to post Share on other sites
Panzorfork Posted September 4, 2013 Thanks osmosisch! I've changed the script a bit to maintain the previous size, then animate down to 10px wide / tall. I also made it a bit slower, from 50ms to 100ms. I made a short twitch.tv video tutorial, it got cut off a bit on the end, but it gets the point across (all that got cut off was me compulsively saying "have a good one"): http://www.twitch.tv/panzorfork/b/456048170 Share this post Link to post Share on other sites