Scrolling Display
I thought it would be fun to create a simulation of a scrolling message display, using HTML & CSS as the “hardware” and Javascript to drive the logic. I don’t know how real scrolling displays work and I stopped studying electronics before I understood the kind of constructions those things use. I’ll be making this up as I go along.
The approach I took, more or less, was to hack at it intuitively, rather than to solve every aspect of the problem in theory and then implement it. It’s fun doing it this way.
Whilst I do use JavaScript’s prototype chains or the new ES2015 class constructions in my day job, I prefer to sketch focusing on functions. (My ultimate aim in this regard is to build the bulk of my personal projects using a functional programming paradigm, but I’m a long way off that yet).
- I built the HTML and some really basic CSS
- I wrote functions to illuminate a single “lamp” at a time, stepping through coloumn by column, row by row. This got me used to thinking in the grid I’d created. Stepping or animation was built very simply, using
setInterval
. This function has many issues, but for now none of them matter. - Next I got a single column to illuminate and then appear to “move” from one side of the grid to the other. This prompted me to create dedicated functions for finding lamps in the grid (i.e. finding the DOM elements) and for turning them off or on (i.e. un/setting a classname).
-
The animation seemed jerky to me. This was probably due to the speed I had things update (not very fast). The fact I was turning off all the “on” lamps, before turning on the next set may also have contributed to the illusion of jerkiness. Although I wasn’t sure it would help, I decided to refactor the way I selected lamps to turn on. The lamps are HTML
<div />
elements. I was searching for them by drilling down through the DOM of the wrapper div I was using:var wrapper = document.querySelector('.wrapper'); // and then later on... var lamp = wrapper.children[ row_index ].children[ column_index ];
That works fine, but I wondered if I could get more speed from it. At the CreativeJS course I attended last year we learned that that “good” partical systems cache their particles (this similar to some highly performant front-end code which caches and reuses elements rather than creating and destroying them). The lamps are possibly particles. I decided to cache them all. I dislike nested data, so decided on a flat array (rather than an array of rows with nested arrays of columns of lamps), each lamp being an element of the same array. That forces me to compose the array in a regular way, and to write a method to map row and column indeces to array indeces.
-
I used these structures first with the column drawing function to check they worked, and then to create a more complicated shape. I imagined a rough circle could be represented as nested arrays of booleans (well, actually truthy 0s & 1s because they’re easier on the eye). The array represented rows, and each row represented columns of lamps. This one can see the intended display shape from the code itself:
var circle = [ [0,0,0,1,1,0,0,0], [0,1,1,0,0,1,1,0], [1,0,0,0,0,0,0,1], [1,0,0,0,0,0,0,1], [1,0,0,0,0,0,0,1], [1,0,0,0,0,0,0,1], [0,1,1,0,0,1,1,0], [0,0,0,1,1,0,0,0] ];
I wrote a function to step over the elements of these nested arrays and to find and turn on lamps in the correspecting locations in the lamps array. This worked. I then added the ability to offset the drawing, so it could happen further into the message display. Then I automated stepping up the column offset, so the shape would appear to move across the display; at this point I discovered a problem. When the shape is plotted far enough along the display that some of its “pixels” should be lost off the right edge, what in fact happens is my code for calculating lamp positions instead finds a lamp on the next row down, wrapping around to the left edge of the display.
- Looking over points 4 and 5, I can see there’s likely a conflict between different modelling ideas: I’ve got a flat, unstructured array of lamps, mapped to a “physical” structure (the grid of lamps) with a function. But then I have a structured array of image/shape data. This conflict has a physical representation: if a “circle” is plotted with an offset almost as high as the number of columns in the grid (so it’s plotted towards the right-hand side of the display), some points “fall off” the edge of the display.