HTML5 Canvas Running Texts (Part 1)

In the last two contributions to our Digital Signage Newsletter workshop we showed you how to create a scrolling text with CSS3 animations that plays headlines from an RSS feed. In this article we present an interesting alternative with the HTML5 element canvas. Using canvas running texts brings advantages and disadvantages. We will discuss these in more detail over the following two articles.

Canvas Running Texts
Canvas running texts image source: Herbert Weber, Hildesheim, Kreuzgang san paolo fuori le mura 3, cropped, CC BY-SA 3.0

What is an HTML5 canvas?

A canvas is a defined area in HTML5 in which you can draw with Javascript commands. Apple developed Canvas originally for their browser Safari. It was standardized as part of HTML5 sometime later. Canvas allows drawing circles, lines, polygons and other geometric forms. A reference map can be found at Wikipedia. This element is multi-purpose and can also play videos due to its image functions. These may, for example, include additional effects in real time. All current browsers (April 2018) are able to handle the canvas element.
This is how it is used in HTML:

<canvas id="myTicker" width="500" height="80">No Canvas</canvas>

The text “No Canvas” is a so-called “Fallback”. Only browsers that can’t render a canvas, e.g. Internet Explorer 8 display this text. We apply 80 pixels for the height and 500 pixels for the width.
With the attribute id we give the element a unique identification to be able to address it correctly via Javascript.

How do we draw a text in canvas?

For this purpose, we add the following lines between the body tags in the HTML source code:

<canvas id="myTicker" width="500" height="80" style="border:1px solid #ddd;">
	No Canvas
</canvas>
<script>
	var MyCanvas = document.getElementById("myTicker");
	var ctx      = MyCanvas.getContext("2d");
	ctx.font     = "30px Arial";
	ctx.fillText("Lorem ipsum dolor sit amet, consetetur", 10, 50);
</script>

Since the browser processes its contents from top to bottom, it is important for this example to enter the Javascript commands after the canvas element. Alternatively, we can of course load the canvas using onload in the body tag. We additionally add a grey border with style=”border:1px solid #ddd;”. The command document.getElementById(“myTicker”); loads the existing element into the variable MyCanvas. Now Javascript needs a context to the canvas.

The Canvas Context

The programmer defines a context as an interface to an object. The context provides functions and data structures. which we can apply to draw on the canvas. MyCanvas.getContext(“2d”) clarifies, that we need only functionality for two-dimensional vector graphics here. Alternative contexts would be e.g. webgl/webgl2 for three-dimensional vector graphics or bitmaprenderer to use pixel-oriented graphics functions. Since we do not need this, we initialize the context variable ctx with 2d.
Now the canvas context is assigned a 30 pixel Arial font using ctx.font = “30px Arial”. Finally, the command fillText() outputs the text “Lorem ipsum dolor sit amet, consetetur”.
The following two parameters set the ticker text 10 pixels to the right of the border and 50 pixels from above. It starts from the beginning of the text at the bottom left. Since the font is 30 pixels high, a value of 50 means that the text is 20 pixels below the edge at the top.

You can click on canvas_animations_1.html to see the result.

Javascript animation

We must now make the text “move”. The basic approach for canvas tickers is to change the position of the content at very short time intervals. To give the human brain the impression of a fluid movement, these intervals on a digital screen must not exceed a 30th of a second. We are then talking about the so-called frame rate, which in this case is 30fps (frames per second). To avoid jerk effects during fast movements, e.g. in videos or games, even 60fps are required. We therefore need Javascript functionality that starts certain actions on a time-controlled basis. In the past, the functions setTimeout or setInterval were used for this purpose. This method of creating animations has become obsolete and suboptimal.

The alternative is requestAnimationFrame

All current browsers support an efficient function called requestAnimationFrame since 2013. This function informs the browser that there is a pending animation. The user selects the frame rate and uses internal routines specially designed for animations. The top priority is to animate as smoothly as possible. It is generally better if the browser sets the frame rate, as the optimal value can also vary during runtime depending on the number and type of animations. With the old static functions, we will reach the limits quickly. Furthermore, the animation stops when the user changes the browser tab, while animations using setInterval() or stTimeout() simply continue to run in this case and consume resources without any sense.

The first running text

We extend example 1 to move the text. It should scroll infinitely often from right to left. I.e. as soon as the last letter at the left edge runs out, the ticker starts again from the right edge. The necessary code for canvas running texts looks like this:

<canvas id="myTicker" width="500" height="80" style="border:1px solid #d3d3d3;">
	No Canvas	
</canvas>	
<script>
	const move_pixel   = 1;
	var MyCanvas       = document.getElementById("myTicker");
	var ctx		   = MyCanvas.getContext("2d");
        ctx.font           = "30px Arial";
	var x              = 500;
	var ticker_content = "Lorem ipsum dolor sit amet, consetetur";
	var text_width     = ctx.measureText(ticker_content).width;
	ctx.fillText(ticker_content, x, 50);
	window.requestAnimationFrame(moveTicker);

	function moveTicker()
	{
		ctx.clearRect(0,0,x,80);
		if (x > -text_width)
			x = x - move_pixel;
		else
			x = 500;
		ctx.fillText(ticker_content, x, 50);	
		window.requestAnimationFrame(moveTicker);
	}
</script>

First we set a constant called pixel_move. This defines how many pixels the ticker text scrolls to the left for each frame. This constant controls the speed of the canvas running texts. With higher values, the text scrolls faster; with smaller values, e.g. 0.5 slower. A value of 1 would be fine for our purposes.

The next lines are identical to the first example. Since we “push” the text through the canvas, the x-position recalculates every time we run. So we set x = 500 as start value, because the right edge of the canvas is at 500 pixels. The content is also put into a variable because we will use it several times for simplification.
Now the script needs to know the width of the text in 30px Arial to see when the text has run completely. Then, it restart at position 500px. This calculation is done by the ctx. measureText(ticker_content).width command and is written to the text_width variable. On a system with Linux and Chromium/Chrome, for example, this corresponds to approx. 519 pixels. With ctx.fillText(ticker_content, x, 50); set the beginning of the text to the right edge of the canvas as described above. The next line window.requestAnimationFrame(moveTicker) calls the function moveTicker. Programmers characterize a function that is called as a parameter from another function as a so-called callback function. Now the “magic” happens in our callback moveTicker().

The Algorithm for Canvas running texts

At first ctx.clearRect(0,0,x,80) deletes all previous contents of the canvas context. The script then uses the if…else condition to evaluate the current x value and decide on the new text position. Either the text should move one pixel to the left or back to its initial state. As long as x is greater than the negative value of the text length (i.e. -519px), the text content moves further and further to the left. The variable x will eventually become smaller than -519, which means that the text is now completely out of the visible area. So its position must return to the starting value (x = 500).
To be able to playback the animation in an endless loop, the callback function finally calls itself again using requestAnimationFrame. Programmers call this a recursive function.

Click canvas_animations_2.html, to see the result. If you are sitting in front of a PC, you will probably notice that this ticker runs more smoothly than scrolling texts with CSS3-Animations .

What is the next step?

In the next part of our workshop we will combine the RSS handling from the previous article CSS3 animations with RSS slightly modified for Canvas running texts.

If you have any questions or comments, please do not hesitate to contact us.

Leave a Reply

Your email address will not be published. Required fields are marked *