Now the mirror can detect when Alexa is listening to our voice input, it’s time to provide a visual feedback on the mirror. We could just do that using an alert or an extra module that displays a text. Instead I want to do something fancier.
It’s time for a small side project in the form of a new magic mirror module displaying a female head in a “matrix” effect, just like in the movie with a bunch of green falling letters hinting a silhouette. I’m saying green because I’m kind of preconditioned, but it can be any color anyway.
The name of the animation file is stored in the magic mirror’s configuration file :
Notice how, in the code extract above, the animation file is loaded using the loadAnimationFile method. This called whenever the MATRIX_ANIMATION_CONNECT notification is received.
Notice how a local variable is assigned to the payload.
In order to start and stop the matrix effect, the module relies on another module telling it to start and stop. In practice this will of course be the Alexa interface module doing this. It listens to 2 different notifications : START_MATRIXEFFECT en STOP_MATRIXEFFECT. The first one hides all of the modules except for the matrix effect module, shows the module itself, and starts the matrix using the animation definition and the yPositions array. The second one does the exact opposite.
The screenshot below shows a very simple piece of code overriding the getDom method by creating a HTML canvas, and getting the context from it. These objects are used to draw something on a HTML page. You can find more information on this here.
The code extract below is the bulk of the module and requires some detailed explanation.
The runMatrix function actually starts an interval. This is a piece of code (executed as a callback function in the call to the “setInterval” method, which is executed every x milliseconds. These milliseconds are also a parameter in the same method, and as a matter of fact it is controlled by the “updateSpeed” parameter of the animation definition.
The function starts by getting the canvas and the context and filling the screen with a black background. I haven’t made this variable yet, but I might do so in the future. Inside the callback function the canvas and the context are set again because the scope of the callback function is different. A matrix variable is created, containing the different column definitions in the animation file. Next, the random() function is called. It returns a random number between 0 and 1. I use it to determine if and when an almost transparent overlay is to be put over the existing area. Almost transparent, as you can see, the “alpha” of the rgba function component is 0.01. This takes care of the fading letters in the matrix effect.
Next the font is set to the primary color (secondary colours are not supported yet) and the font is determined to be a certain font name with a certain width, depending on the animation file. The next function is very important. The map function loops through the yPositions matrix and executes a callback function for every element. Where y is a coördinate on the y axis of the canvas and index is the index of a certain column. The for loop determines if a letter is to be printed because it is in between the “start” and “end” tag of a section. If it is, the text is printed on the y coördinate passed by the map function and the x coördinate based on a formula on the index. Lastly, the yPositions array is updated so the letters drop to the bottom. If they reach a certain depth, the yPositions array at that index is just rest.
The stopMatrix function just clears the interval allowing the loop to stop.
All this is configured in the animation definition. It looks like this :
The configuration file is “prepared” to do some more exotic things like working with different colors and different animation frames already. The code doesn’t use these properties yet. Notice all of the settings used in the code like canvasWidth and canvasHeight, textPoints, etc. The animation Matrix is a matrix in 3 dimensions :
- Dimension 1 is the animation frame. There’s only one in this example
- Dimension 2 is the matrix contain all columns
When running this module, the end result looks like this :
Granted, it still needs some work finetuning this. And I’ll probably need to make a little tool to be able to create the animation definition file more efficient, but that’s for a later phase.
When this module is in a more finished phase I will upload it as a magic mirror module.