<div id="ticker" style="width:1920px"> <canvas id="tape" width="4096" height="40">Your browser doesn't support canvas</canvas> </div>A small amount of JavaScript in the onload event starts the ticker running with data--an array of objects each with a Symbol and Value property.
<body onload="OnLoad();"> <div id="ticker" style="width:1920px"> <canvas id="tape" width="4096" height="40">Your browser doesn't support canvas</canvas> </div> ... <script> function OnLoad() { var items = []; items.push({ Symbol: 'AAA', Value: '1' }); items.push({ Symbol: 'BBB', Value: '22' }); items.push({ Symbol: 'CCC', Value: '3.3' }); items.push({ Symbol: 'DDD', Value: '44 1/4' }); items.push({ Symbol: 'EEE', Value: '5,000' }); items.push({ Symbol: 'FFF', Value: '-66' }); items.push({ Symbol: 'GGG', Value: '700' }); items.push({ Symbol: 'HHH', Value: '88' }); items.push({ Symbol: 'III', Value: '9999' }); items.push({ Symbol: 'JJJ', Value: '10' }); Ticker("ticker", "tape", items); } </script> </body>In the JavaScript, there is a Ticker function that starts off the ticker, a MoveTicker function that continues the animation based on a timer, and a TickerState object that maintains housekeeping information for the animation between calls to MoveTicker.
In Ticker, the first order of business is to write out the symbols and values in the data array that was passed in. This is done, as many times as needed, to fill the canvas for the target width. That allows scrolling that looks smooth, even if the data doesn't fully fit the ticker width, and the animation can be reset back to its starting point without any visual roughage. Ticker's final act is to start a timer to call MoveTicker. The interval affects the scolling speed: 10 is fast, 50 is medium, 100 is slow.
In MoveTicker, we use CSS to move the ticker left--specifically by decrementing the canvas left margin(which is negative throughout) and counter-adjusting the ticker tape rectangle with CSS clip. This creates the illusion of a ticker rectangle that does not appear to move but has content that does. Once a full set of the data has been slid off the left of the screen, it is reset back to the starting offset. MoveTicker then sets a timer again so it will be called over and over. The result is a gliding ticker tape.
var TickerState = { canvas: undefined, ctx: undefined, tickerX: 0, dataWidth: 0, interval: 10 /* Fast: 10 Medium: 50 Slow: 100 */ }; function Ticker(divId, canvasId, items) { ticker = document.getElementById(divId); maxWidth = parseInt(ticker.style.width); TickerState.canvas = document.getElementById(canvasId); TickerState.ctx = TickerState.canvas.getContext('2d'); TickerState.ctx.font = "20px sans-serif"; TickerState.ctx.font = "20px Nova Flat, 20px sans-serif"; TickerState.ctx.textAlign = "left"; var x = 10; var y = 20; var firstTime = true; while (x < maxWidth * 4) { for (var i = 0; i < items.length; i++) { TickerState.ctx.fillStyle = "Blue"; TickerState.ctx.fillText(items[i].Symbol, x, y); x += TickerState.ctx.measureText(items[i].Symbol).width; TickerState.ctx.fillStyle = "Green"; TickerState.ctx.fillText(items[i].Value, x, y + 10); x += TickerState.ctx.measureText(items[i].Value).width; x += 10 + 6; } if (firstTime) { TickerState.dataWidth = x; firstTime = false; } } setTimeout(MoveTicker, TickerState.interval); } function MoveTicker() { TickerState.tickerX += 1; if (TickerState.tickerX >= TickerState.dataWidth) { TickerState.tickerX = 10; } TickerState.canvas.style.marginLeft = "-" + TickerState.tickerX.toString() + "px"; TickerState.canvas.style.clip = "rect(0px " + (maxWidth + TickerState.tickerX).toString() + "px 40px -" + TickerState.tickerX.toString() + "px)"; setTimeout(MoveTicker, TickerState.interval); }Here's the HTML page in its entirety:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head> <title>Ticker</title> <link rel="stylesheet" type="text/css" href="http://fonts.googleapis.com/css?family=Nova+Flat"> <style> #ticker { font-family: 'Nova Flat', cursive; font-size: 20px; } #tape { font-family: 'Nova Flat', cursive; font-size: 20px; position: absolute; clip: rect(0px 2048px 40px 0px); vertical-align: top; margin-left: 0px; background-color: LightYellow; } </style> <script> var TickerState = { canvas: undefined, ctx: undefined, tickerX: 0, dataWidth: 0, interval: 10 /* Fast: 10 Medium: 50 Slow: 100 */ }; function Ticker(divId, canvasId, items) { ticker = document.getElementById(divId); maxWidth = parseInt(ticker.style.width); TickerState.canvas = document.getElementById(canvasId); TickerState.ctx = TickerState.canvas.getContext('2d'); TickerState.ctx.font = "20px sans-serif"; TickerState.ctx.font = "20px Nova Flat, 20px sans-serif"; TickerState.ctx.textAlign = "left"; var x = 10; var y = 20; var firstTime = true; while (x < maxWidth * 4) { for (var i = 0; i < items.length; i++) { TickerState.ctx.fillStyle = "Blue"; TickerState.ctx.fillText(items[i].Symbol, x, y); x += TickerState.ctx.measureText(items[i].Symbol).width; TickerState.ctx.fillStyle = "Green"; TickerState.ctx.fillText(items[i].Value, x, y + 10); x += TickerState.ctx.measureText(items[i].Value).width; x += 10 + 6; } if (firstTime) { TickerState.dataWidth = x; firstTime = false; } } setTimeout(MoveTicker, TickerState.interval); } function MoveTicker() { TickerState.tickerX += 1; if (TickerState.tickerX >= TickerState.dataWidth) { TickerState.tickerX = 10; } TickerState.canvas.style.marginLeft = "-" + TickerState.tickerX.toString() + "px"; TickerState.canvas.style.clip = "rect(0px " + (maxWidth + TickerState.tickerX).toString() + "px 40px -" + TickerState.tickerX.toString() + "px)"; setTimeout(MoveTicker, TickerState.interval); } </script> </head> <body onload="OnLoad();"> <div id="ticker" style="width:1920px"> <canvas id="tape" width="4096" height="40">Your browser doesn't support canvas</canvas> </div> <br /> <br /> <br /> Hello <script> var loaded = false; function OnLoad() { loaded = true; var items = []; items.push({ Symbol: 'AAA', Value: '1' }); items.push({ Symbol: 'BBB', Value: '22' }); items.push({ Symbol: 'CCC', Value: '3.3' }); items.push({ Symbol: 'DDD', Value: '44 1/4' }); items.push({ Symbol: 'EEE', Value: '5,000' }); items.push({ Symbol: 'FFF', Value: '-66' }); items.push({ Symbol: 'GGG', Value: '700' }); items.push({ Symbol: 'HHH', Value: '88' }); items.push({ Symbol: 'III', Value: '9999' }); items.push({ Symbol: 'JJJ', Value: '10' }); Ticker("ticker", "tape", items); } </script> </body> </html>