[TypeScript] Lightningtalks Timer by HTML5
以前作った HTML5 用のライトニングトーク用のタイマーを、TypeScript で書きなおしてみた。
TypeScript を使うことで、よりすっきりと書ける。また、Visual Studio でのインテリセンスや静的な型チェックが行える為、とても楽だ。
lightningtalktimer.ts
TypeScript コンパイラーによって lightningtalktimer.js に変換される。
// for lightningtalktimer.html // generated from lightningtalktimer.ts // Ver.1.01 2014-01-17 // Copyright © 2014 Sho's Software by Fujiwo http://www.shos.info module LightningTalkTimer { export class Application { private static timer = null; private static get canvas(): HTMLCanvasElement { return <HTMLCanvasElement>document.querySelector("canvas"); } private static get context(): CanvasRenderingContext2D { return <CanvasRenderingContext2D>Application.canvas.getContext("2d"); } static run() { Application.sizing(); Application.timer = new Timer(this.context, this.canvas.width, this.canvas.height); } static onClick() { Application.timer.start(); } private static sizing() { var canvas = Application.canvas; canvas.height = window.innerHeight; canvas.width = window.innerWidth ; } } class Utility { static getQuerystring(key: string, default_: string = null): string { if (default_ == null) default_ = ""; key = key.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]"); var regex = new RegExp("[\\?&]" + key + "=([^&#]*)"); var queryString = regex.exec(window.location.href); return queryString == null ? default_ : queryString[1]; } static secondsToString(totalSeconds: number): string { var minutes = Math.floor(totalSeconds / 60); var seconds = totalSeconds % 60; var secondsText = (seconds >= 10) ? seconds.toString() : "0" + seconds; return minutes.toString() + ':' + secondsText; } static getCurrentMilliSeconds(): number { return Date.parse(new Date().toString()); } } class Parameter { maxSeconds = 60 * 5; dangerousSeconds = 60 * 1; fontHeightRate = 70; constructor() { this.setMaxSeconds (); this.setDangerousSeconds(); this.setFontHeight (); } private setFontHeight() { var fontHeightRateText = Utility.getQuerystring("font"); if (fontHeightRateText != "") { var heightRate = parseInt(fontHeightRateText); if (heightRate > 0 && heightRate <= 100) this.fontHeightRate = heightRate; } } private setMaxSeconds() { var maxSecondsText = Utility.getQuerystring("max"); if (maxSecondsText != "") { var seconds = parseInt(maxSecondsText); if (seconds > 0) { this.maxSeconds = seconds; if (this.dangerousSeconds > this.maxSeconds) this.dangerousSeconds = this.maxSeconds; } } } private setDangerousSeconds() { var dangerousSecondsText = Utility.getQuerystring("danger"); if (dangerousSecondsText != "") { var seconds = parseInt(dangerousSecondsText); if (seconds >= 0 && seconds <= this.maxSeconds) this.dangerousSeconds = seconds; } } } class View { private static normalDarkColor = "#100"; private static normalLightColor = "#a99"; private static dangerousDarkColor = "#e00"; private static dangerousLightColor = "#f99"; private static shadowColor = "gray"; private context: CanvasRenderingContext2D; constructor(context: CanvasRenderingContext2D) { this.context = context; } draw(text: string, isNormal: boolean, width: number, height: number, fontHeightRate: number) { this.context.clearRect(0, 0, width, height); View.drawText(this.context, text, View.getDarkColor(isNormal), View.getLightColor(isNormal), width, height, fontHeightRate); } private static drawText(context: CanvasRenderingContext2D, text: string, colorDark: string, colorLight: string, width: number, height: number, fontHeightRate: number) { var fontHeight = height * fontHeightRate / 100; var y = fontHeight * (16 + 1) / 16; context.font = fontHeight + "px 'メイリオ',Meiryo,'ヒラギノ角ゴ Pro W3','Hiragino Kaku Gothic Pro',Calibri,sans-serif"; View.setGradient(context, fontHeight, colorDark, colorLight); View.setShadow (context, fontHeight ); context.fillText(text, fontHeight / 12, y); } private static getDarkColor(isNormal: boolean): string { return isNormal ? View.normalDarkColor : View.dangerousDarkColor; } private static getLightColor(isNormal: boolean): string { return isNormal ? View.normalLightColor : View.dangerousLightColor; } private static setGradient(context: CanvasRenderingContext2D, fontHeight: number, darkColor: string, lightColor: string) { var gradient = context.createLinearGradient(0, 0, 0, fontHeight); gradient.addColorStop(0.5, darkColor); gradient.addColorStop(0.6, lightColor); gradient.addColorStop(0.7, darkColor); context.fillStyle = gradient; } private static setShadow(context: CanvasRenderingContext2D, fontHeight: number) { context.shadowColor = View.shadowColor; context.shadowOffsetX = fontHeight / 36; context.shadowOffsetY = fontHeight / 36; context.shadowBlur = fontHeight / 48; } } class Timer { private width : number; private height : number; private parameter: Parameter; private view : View; private timerID = 0; constructor(context: CanvasRenderingContext2D, width: number, height: number) { this.width = width ; this.height = height ; this.parameter = new Parameter(); this.view = new View(context); this.draw(this.parameter.maxSeconds, this.isNormal(this.parameter.maxSeconds)); } private start() { this.reset(); var start = Utility.getCurrentMilliSeconds(); this.timerID = window.setInterval(() => this.update(start), 1000); } private update(start: number) { var now = Utility.getCurrentMilliSeconds(); var remainingSeconds = this.parameter.maxSeconds - (now - start) / 1000; if (remainingSeconds < 0) remainingSeconds = 0; this.draw(remainingSeconds, this.isNormal(remainingSeconds)); if (remainingSeconds == 0) window.clearInterval(this.timerID); } private reset() { window.clearInterval(this.timerID); this.draw(this.parameter.maxSeconds, this.isNormal(this.parameter.maxSeconds)); } private draw(seconds: number, isNormal: boolean) { this.view.draw(Utility.secondsToString(seconds), isNormal, this.width, this.height, this.parameter.fontHeightRate); } private isNormal(remainingSeconds: number): boolean { return remainingSeconds > this.parameter.dangerousSeconds; } } } window.onload = () => { LightningTalkTimer.Application.run(); };
lightningtalktimer.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width,minimum-scale=1, maximum-scale=1, initial-scale=1"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" /> <title>Sho's Lightning Talks Timer by HTML5</title> <style> html, body, div, span, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, abbr, address, cite, code, del, dfn, em, img, ins, kbd, q, samp, small, strong, sub, sup, var, b, i, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, dialog, figure, footer, header, hgroup, menu, nav, section, menu, time, mark, audio, video { margin: 0; padding: 0; border: 0; outline: 0; font-size: 100%; vertical-align: baseline; background: transparent; } article, aside, dialog, figure, footer, header, hgroup, nav, section { display: block; } body { width: 100%; overflow: hidden; } </style> <script src="lightningtalktimer.js"></script> </head> <body> <canvas width="500" height="500" onclick="LightningTalkTimer.Application.onClick()"></canvas> </body> </html> <!-- Usage: Click: reset and start counting down. lightningtalktimer.html : max = 300 seconds, dangerous = 60 seconds, font height 70% lightningtalktimer.html?max=100&danger=50 : max = 100 seconds, dangerous = 50 seconds lightningtalktimer.html?max=100&danger=100 : max = 100 seconds, dangerous = 100 seconds lightningtalktimer.html?max=100 : max = 100 seconds, dangerous = 60 seconds lightningtalktimer.html?max=10 : max = 10 seconds, dangerous = 10 seconds lightningtalktimer.html?danger=0 : max = 300 seconds, dangerous = 0 seconds lightningtalktimer.html?font=50 : font height 50% - This HTML can work with lightningtalktimer.js online or offline. Ver.1.01 2014-01-17 Copyright © 2014 Sho's Software by Fujiwo http://www.shos.info -->
実際に動くもの
使い方
- クリックするたびカウントダウン (デフォルト 5分)
- 残り時間が少なくなると赤くなる (デフォルト 1分)
- クエリー文字列:
- max で、時間 (秒) の設定 (lightningtalktimer.html?max=100 で 100秒)
- danger で、赤くなる時間 (秒) の設定 (lightningtalktimer.html?danger=10 で 10秒、lightningtalktimer.html?danger=0 だと最後だけ赤くなる)
- font で、文字サイズ (%) の設定 (lightningtalktimer.html?font=90 で文字の高さが最大値の90%)
- Internet Explorer、Firefox、Safari、Google Chrome、Opera の現時点での最新版で動作
- iPhone、Android フォン等スマートフォンで動作
ディスカッション
コメント一覧
まだ、コメントがありません