├── save ├── .htaccess ├── php │ ├── ajax.php │ ├── pseudo-crypt.php │ └── db.php ├── canvas-letters.sql ├── ajax.js ├── index.php ├── json.js └── canvas-letters.js ├── readme.md ├── banner ├── index.html └── canvas-letters-banner.js ├── full-screen └── index.html ├── index.html ├── canvas-letter-creator └── index.html ├── inline └── index.html ├── config └── index.html └── canvas-letters.js /save/.htaccess: -------------------------------------------------------------------------------- 1 | #stats redirects 2 | 3 | RewriteEngine On 4 | #RewriteBase /stats/ 5 | RewriteCond %{REQUEST_FILENAME} !-f 6 | RewriteCond %{REQUEST_FILENAME} !-d 7 | RewriteRule (.*) ./?slug=$1 [L] 8 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Canvas Letters 2 | 3 | ## Post 4 | 5 | - [https://f90.co.uk/labs/canvas-letters/](https://f90.co.uk/labs/canvas-letters/) 6 | 7 | ## Example 8 | 9 | - [https://orangespaceman.github.io/canvas-letters](https://orangespaceman.github.io/canvas-letters) 10 | -------------------------------------------------------------------------------- /save/php/ajax.php: -------------------------------------------------------------------------------- 1 | 0) { 4 | 5 | // check what to do 6 | require_once("db.php"); 7 | $model = new DB(); 8 | $method = $_POST['method']; 9 | unset($_POST['method']); 10 | 11 | // 12 | switch ($method) { 13 | 14 | // save post 15 | case "save": 16 | $result = $model->save($_POST); 17 | echo json_encode($result); 18 | break; 19 | 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /banner/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Canvas Letters Banner 6 | 7 | 8 | 21 | 22 | 23 |

Canvas Letters Banner

24 | 25 | 26 | -------------------------------------------------------------------------------- /save/php/pseudo-crypt.php: -------------------------------------------------------------------------------- 1 | array(1,23,809,28837,1038073,37370257 /*,1345328833*/) 9 | ); 10 | 11 | public static function udihash($num, $len = 5, $base = 36) { 12 | $gp = self::$golden_primes[$base]; 13 | $maxlen = count($gp); 14 | $len = $len > ($maxlen-1) ? ($maxlen-1) : $len; 15 | while($len < $maxlen && pow($base,$len) < $num) $len++; 16 | if($len >= $maxlen) throw new Exception($num." out of range (max ".pow($base,$maxlen-1).")"); 17 | $ceil = pow($base,$len); 18 | $prime = $gp[$len]; 19 | $dechash = ($num * $prime) % $ceil; 20 | $hash = base_convert($dechash, 10, $base); 21 | return str_pad($hash, $len, "0", STR_PAD_LEFT); 22 | } 23 | } -------------------------------------------------------------------------------- /save/canvas-letters.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE `canvas-letters` ( 2 | `id` int(11) unsigned NOT NULL AUTO_INCREMENT, 3 | `slug` varchar(50) DEFAULT NULL, 4 | `blockColour` varchar(6) NOT NULL, 5 | `canvasColour` varchar(6) NOT NULL, 6 | `blockSize` int(2) NOT NULL, 7 | `textString` text NOT NULL, 8 | `clearance` int(2) NOT NULL, 9 | `breakWord` tinyint(1) unsigned NOT NULL DEFAULT '0', 10 | `ordering` varchar(20) NOT NULL, 11 | `do_loop` tinyint(1) unsigned NOT NULL DEFAULT '1', 12 | `animate` tinyint(1) unsigned NOT NULL DEFAULT '1', 13 | `speed` int(2) NOT NULL DEFAULT '5', 14 | `views` int(11) NOT NULL DEFAULT '0', 15 | `ip` varchar(20) NOT NULL, 16 | `dateadded` datetime NOT NULL, 17 | PRIMARY KEY (`id`) 18 | ) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=2 ; 19 | 20 | -- 21 | -- Dumping data for table `canvas-letters` 22 | -- 23 | 24 | 25 | INSERT INTO `canvas-letters` VALUES(1, '8hy5e', 'ff9900', '000000', 15, 'Quidquid latine dictum sit; altum sonatur.', 10, 1, 'default', 1, 1, 5, 0, '192.168.0.7', '2010-10-13 11:40:52'); -------------------------------------------------------------------------------- /full-screen/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Canvas Letters - Simple 6 | 7 | 8 | 28 | 29 | 30 |

Canvas Letters

31 | 32 | 33 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Canvas Letters 6 | 21 | 22 | 41 | 42 | 43 | 44 |

Inline Canvas Letters

45 | 46 | 47 | 48 | 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /save/ajax.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Ajax 3 | */ 4 | var ajax = function() { 5 | 6 | // 7 | var ajaxUrl = null; 8 | 9 | 10 | // 11 | var callback = null; 12 | 13 | 14 | // 15 | var init = function(options) { 16 | ajaxUrl = options.ajaxUrl; 17 | callback = options.callback; 18 | request(options.values); 19 | }; 20 | 21 | 22 | // 23 | var getXMLHttp = function() { 24 | var xmlHttp; 25 | 26 | try { 27 | //Firefox, Opera 8.0+, Safari 28 | xmlHttp = new XMLHttpRequest(); 29 | } 30 | catch(e) { 31 | //Internet Explorer 32 | try { 33 | xmlHttp = new ActiveXObject("Msxml2.XMLHTTP"); 34 | } catch(e) { 35 | try { 36 | xmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); 37 | } catch(e) { 38 | //alert("Your browser does not support AJAX!") 39 | return false; 40 | } 41 | } 42 | } 43 | return xmlHttp; 44 | }; 45 | 46 | 47 | // 48 | var request = function(values) { 49 | var xmlHttp = getXMLHttp(); 50 | xmlHttp.onreadystatechange = function() { 51 | if(xmlHttp.readyState == 4) { 52 | if (xmlHttp.status == 200) { 53 | callback(xmlHttp.responseText); 54 | } 55 | } 56 | }; 57 | xmlHttp.open("POST", ajaxUrl, true); 58 | xmlHttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); 59 | //xmlHttp.setRequestHeader("Content-length", values.length); 60 | //xmlHttp.setRequestHeader("Connection", "close"); 61 | xmlHttp.send(values); 62 | }; 63 | 64 | 65 | // 66 | var serialise = function(formEl) { 67 | var values = ""; 68 | for (var i=0; i < formEl.elements.length; i++) { 69 | el = formEl.elements[i]; 70 | if (el.type != "submit") { 71 | if (el.type == "checkbox" || el.type == "radio") { 72 | if (!el.checked) { 73 | continue; 74 | } 75 | } 76 | values += encodeURIComponent(el.name) + "=" + encodeURIComponent(el.value) + "&"; 77 | } 78 | } 79 | return values.slice(0, -1); 80 | }; 81 | 82 | 83 | // 84 | return { 85 | init: init, 86 | serialise: serialise 87 | }; 88 | }(); -------------------------------------------------------------------------------- /canvas-letter-creator/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Canvas Letter Creator 6 | 15 | 44 | 45 | 46 |

Canvas Letter Creator

47 |
48 | 1 49 | 2 50 | 3 51 | 4 52 | 5 53 | 6 54 | 7 55 | 8 56 | 9 57 | 10 58 | 11 59 | 12 60 | 13 61 | 14 62 | 15 63 | 16 64 | 17 65 | 18 66 | 19 67 | 20 68 | 21 69 | 22 70 | 23 71 | 24 72 | 25 73 | 26 74 | 27 75 | 28 76 | 29 77 | 30 78 | 31 79 | 32 80 | 33 81 | 34 82 | 35 83 |
84 |

85 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /save/php/db.php: -------------------------------------------------------------------------------- 1 | server = "localhost"; 23 | $this->user = "root"; 24 | $this->pass = "root"; 25 | $this->dbname = "canvas-letters"; 26 | $this->dbtable = "canvas-letters"; 27 | $this->salt = "canvas-letters"; 28 | 29 | //start the connection 30 | $this->conn = @mysql_connect($this->server,$this->user,$this->pass); 31 | @mysql_select_db($this->dbname, $this->conn); 32 | 33 | } 34 | 35 | /** 36 | * Generic MySQL select query 37 | */ 38 | function selectQuery($sql) { 39 | 40 | //run the initial query 41 | $result = @mysql_query($sql); 42 | 43 | //condition : if it is a single value, return it 44 | if (@mysql_num_fields($result) === 1 && @mysql_num_rows($result) === 1) { 45 | list($return) = @mysql_fetch_row($result); 46 | 47 | // it is more than a single row, start an array to contain each object... 48 | } else { 49 | 50 | //start the var to return 51 | $return = array(); 52 | 53 | //for each row in the result, start a new object 54 | while ($row = @mysql_fetch_object($result)) { 55 | $return[] = $row; 56 | } 57 | } 58 | 59 | return $return; 60 | } 61 | 62 | 63 | /** 64 | * Generic MySQL update query 65 | */ 66 | function updateQuery($sql) { 67 | 68 | //run the initial query 69 | $result = mysql_query($sql); 70 | 71 | if ($result) { 72 | $return = true; 73 | } else { 74 | $return = false; 75 | } 76 | 77 | return $return; 78 | } 79 | 80 | 81 | /** 82 | * Generic MySQL add query 83 | */ 84 | function addQuery($sql) { 85 | 86 | //run the initial query 87 | $result = mysql_query($sql); 88 | 89 | if ($result) { 90 | $return = mysql_insert_id(); 91 | } else { 92 | $return = false; 93 | } 94 | 95 | return $return; 96 | } 97 | 98 | 99 | 100 | /* 101 | * 102 | * Site-specific calls 103 | * 104 | */ 105 | 106 | /* 107 | * get slug 108 | */ 109 | function get($slug) { 110 | 111 | $slug = mysql_real_escape_string($slug); 112 | $slug = strip_tags($slug); 113 | $slug = stripslashes($slug); 114 | 115 | $sql = "SELECT *, date_format(dateadded, '%W %D %M %Y, %k:%i') as date_added from `".$this->dbtable."` where `slug` = '".$slug."' limit 0,1"; 116 | $result = $this->selectQuery($sql); 117 | 118 | return $result[0]; 119 | } 120 | 121 | /* 122 | * increase view count 123 | */ 124 | function increaseViewCount($slug) { 125 | $sql = "UPDATE `".$this->dbtable."` set views = views + 1 WHERE `slug` = '".$slug."'"; 126 | $result = $this->updateQuery($sql); 127 | return $result; 128 | } 129 | 130 | /* 131 | * get count 132 | */ 133 | function getDBCount() { 134 | $sql = "SELECT count('id') as dbcount FROM `".$this->dbtable."`"; 135 | $result = $this->selectQuery($sql); 136 | return $result; 137 | } 138 | 139 | /* 140 | * save 141 | */ 142 | function save($post) { 143 | 144 | require_once('pseudo-crypt.php'); 145 | 146 | // sanitise 147 | foreach($post as $key => $postitem) { 148 | $postitem = strip_tags($postitem); 149 | $postitem = mysql_real_escape_string($postitem); 150 | $post[$key] = $postitem; 151 | } 152 | 153 | //insert 154 | $sql = "INSERT into `".$this->dbtable."` 155 | ( 156 | blockColour, 157 | canvasColour, 158 | blockSize, 159 | textString, 160 | clearance, 161 | breakWord, 162 | ordering, 163 | do_loop, 164 | animate, 165 | speed, 166 | ip, 167 | views, 168 | dateadded 169 | ) values ( 170 | '".$post['blockColour']."', 171 | '".$post['canvasColour']."', 172 | '".$post['blockSize']."', 173 | '".$post['textString']."', 174 | '".$post['clearance']."', 175 | '".$post['breakWord']."', 176 | '".$post['ordering']."', 177 | '".$post['do_loop']."', 178 | '".$post['animate']."', 179 | '".$post['speed']."', 180 | '".$_SERVER['REMOTE_ADDR']."', 181 | '0', 182 | NOW() 183 | )"; 184 | 185 | $id = $this->addQuery($sql); 186 | 187 | $slug = PseudoCrypt::udihash($id); 188 | 189 | $url = 'http://' . $_SERVER['HTTP_HOST'] . '/' . $slug; 190 | 191 | $post['url'] = $url; 192 | $post['slug'] = $slug; 193 | $post['id'] = $id; 194 | 195 | 196 | $sql = "UPDATE `".$this->dbtable."` set `slug` = '".$slug."' WHERE `id` = '".$id."'"; 197 | $result = $this->updateQuery($sql); 198 | 199 | $return = array( 200 | 'success' => true, 201 | 'details' => $post 202 | ); 203 | 204 | //return $return; 205 | //return $slug; 206 | return $post; 207 | } 208 | } -------------------------------------------------------------------------------- /inline/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Inline Canvas Letters 6 | 21 | 22 | 85 | 86 | 87 |

Inline Canvas Letters

88 | 89 | 90 | 91 |

Canvas configuration:

92 |
93 |
94 |
95 | Canvas Letters config 96 |
97 | 98 | 99 |
100 | 101 |
102 | 103 | 104 |
105 | 106 |
107 | 108 | 109 |
110 | 111 |
112 | 113 | 114 |
115 | 116 |
117 | 118 | 119 |
120 | 121 |
122 |

Break words?

123 | 124 | 125 |
126 | 127 |
128 | 129 | 130 |
131 | 132 |
133 |

Block order

134 | 135 | 136 | 137 | 138 | 139 |
140 | 141 |
142 |

Loop?

143 | 144 | 145 |
146 | 147 |
148 |

Animate?

149 | 150 | 151 |
152 | 153 |
154 | 155 |
156 |
157 |
158 |
159 | 160 | 161 | -------------------------------------------------------------------------------- /config/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Canvas Letters 6 | 20 | 21 | 92 | 93 | 94 |

Canvas Letters

95 |
96 |

Config

97 |
98 |
99 | Canvas Letters config 100 |
101 | 102 | 103 |
104 | 105 |
106 | 107 | 108 |
109 | 110 |
111 | 112 | 113 |
114 | 115 |
116 | 117 | 118 |
119 | 120 |
121 | 122 | 123 |
124 | 125 |
126 |

Break words?

127 | 128 | 129 | 130 | 131 |
132 | 133 |
134 | 135 | 136 |
137 | 138 |
139 |

Block order

140 | 141 | 142 | 143 | 144 | 145 |
146 | 147 |
148 |

Loop?

149 | 150 | 151 |
152 | 153 |
154 |

Animate?

155 | 156 | 157 |
158 | 159 |
160 | 161 |
162 |
163 |
164 |
165 | 166 | 167 | -------------------------------------------------------------------------------- /save/index.php: -------------------------------------------------------------------------------- 1 | blockColour = "ff9900"; 6 | $defaults->canvasColour = "000000"; 7 | $defaults->blockSize = 15; 8 | $defaults->speed = 5; 9 | $defaults->textString = "Got something to say?"; 10 | $defaults->clearance = 10; 11 | $defaults->breakWord = false; 12 | $defaults->ordering = 'default'; 13 | $defaults->do_loop = true; 14 | $defaults->animate = true; 15 | 16 | 17 | if (isset($_GET['slug']) && !empty($_GET['slug'])) { 18 | $db = new DB(); 19 | $values = $db->get($_GET['slug']); 20 | $db->increaseViewCount($_GET['slug']); 21 | } 22 | 23 | 24 | if (!isset($values) || count($values) < 1) { 25 | $values = $defaults; 26 | } 27 | ?> 28 | 29 | 30 | 31 | 32 | Canvas Letters 33 | 50 | 51 | 52 | 53 | 150 | 151 | 152 |

Canvas Letters

153 |
154 | views)) { echo '

('.$values->views.' views)

'; } ?> 155 | 156 |

Create your own

157 |
158 |
159 | Canvas Letters config 160 |
161 | 162 | 163 |
164 | 165 |
166 | 167 | 168 |
169 | 170 |
171 | 172 | 173 |
174 | 175 |
176 | 177 | 178 |
179 | 180 |
181 | 182 | 183 |
184 | 185 |
186 |

Break words?

187 | 188 | 189 | 190 | 191 |
192 | 193 |
194 | 195 | 196 |
197 | 198 |
199 |

Block order

200 | 201 | 202 | 203 | 204 | 205 |
206 | 207 |
208 |

Loop?

209 | 210 | 211 |
212 | 213 |
214 |

Animate?

215 | 216 | 217 |
218 | 219 |
220 | 221 | 222 |
223 |
224 |
225 |
226 | 227 | -------------------------------------------------------------------------------- /save/json.js: -------------------------------------------------------------------------------- 1 | //alert('IMPORTANT: Remove this line from json_parse.js before deployment.'); 2 | /* 3 | http://www.JSON.org/json_parse.js 4 | 2009-05-31 5 | 6 | Public Domain. 7 | 8 | NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. 9 | 10 | This file creates a json_parse function. 11 | 12 | json_parse(text, reviver) 13 | This method parses a JSON text to produce an object or array. 14 | It can throw a SyntaxError exception. 15 | 16 | The optional reviver parameter is a function that can filter and 17 | transform the results. It receives each of the keys and values, 18 | and its return value is used instead of the original value. 19 | If it returns what it received, then the structure is not modified. 20 | If it returns undefined then the member is deleted. 21 | 22 | Example: 23 | 24 | // Parse the text. Values that look like ISO date strings will 25 | // be converted to Date objects. 26 | 27 | myData = json_parse(text, function (key, value) { 28 | var a; 29 | if (typeof value === 'string') { 30 | a = 31 | /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value); 32 | if (a) { 33 | return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4], 34 | +a[5], +a[6])); 35 | } 36 | } 37 | return value; 38 | }); 39 | 40 | This is a reference implementation. You are free to copy, modify, or 41 | redistribute. 42 | 43 | This code should be minified before deployment. 44 | See http://javascript.crockford.com/jsmin.html 45 | 46 | USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO 47 | NOT CONTROL. 48 | */ 49 | 50 | /*members "", "\"", "\/", "\\", at, b, call, charAt, f, fromCharCode, 51 | hasOwnProperty, message, n, name, push, r, t, text 52 | */ 53 | 54 | var json_parse = (function () { 55 | 56 | // This is a function that can parse a JSON text, producing a JavaScript 57 | // data structure. It is a simple, recursive descent parser. It does not use 58 | // eval or regular expressions, so it can be used as a model for implementing 59 | // a JSON parser in other languages. 60 | 61 | // We are defining the function inside of another function to avoid creating 62 | // global variables. 63 | 64 | var at, // The index of the current character 65 | ch, // The current character 66 | escapee = { 67 | '"': '"', 68 | '\\': '\\', 69 | '/': '/', 70 | b: '\b', 71 | f: '\f', 72 | n: '\n', 73 | r: '\r', 74 | t: '\t' 75 | }, 76 | text, 77 | 78 | error = function (m) { 79 | 80 | // Call error when something is wrong. 81 | 82 | throw { 83 | name: 'SyntaxError', 84 | message: m, 85 | at: at, 86 | text: text 87 | }; 88 | }, 89 | 90 | next = function (c) { 91 | 92 | // If a c parameter is provided, verify that it matches the current character. 93 | 94 | if (c && c !== ch) { 95 | error("Expected '" + c + "' instead of '" + ch + "'"); 96 | } 97 | 98 | // Get the next character. When there are no more characters, 99 | // return the empty string. 100 | 101 | ch = text.charAt(at); 102 | at += 1; 103 | return ch; 104 | }, 105 | 106 | number = function () { 107 | 108 | // Parse a number value. 109 | 110 | var number, 111 | string = ''; 112 | 113 | if (ch === '-') { 114 | string = '-'; 115 | next('-'); 116 | } 117 | while (ch >= '0' && ch <= '9') { 118 | string += ch; 119 | next(); 120 | } 121 | if (ch === '.') { 122 | string += '.'; 123 | while (next() && ch >= '0' && ch <= '9') { 124 | string += ch; 125 | } 126 | } 127 | if (ch === 'e' || ch === 'E') { 128 | string += ch; 129 | next(); 130 | if (ch === '-' || ch === '+') { 131 | string += ch; 132 | next(); 133 | } 134 | while (ch >= '0' && ch <= '9') { 135 | string += ch; 136 | next(); 137 | } 138 | } 139 | number = +string; 140 | if (isNaN(number)) { 141 | error("Bad number"); 142 | } else { 143 | return number; 144 | } 145 | }, 146 | 147 | string = function () { 148 | 149 | // Parse a string value. 150 | 151 | var hex, 152 | i, 153 | string = '', 154 | uffff; 155 | 156 | // When parsing for string values, we must look for " and \ characters. 157 | 158 | if (ch === '"') { 159 | while (next()) { 160 | if (ch === '"') { 161 | next(); 162 | return string; 163 | } else if (ch === '\\') { 164 | next(); 165 | if (ch === 'u') { 166 | uffff = 0; 167 | for (i = 0; i < 4; i += 1) { 168 | hex = parseInt(next(), 16); 169 | if (!isFinite(hex)) { 170 | break; 171 | } 172 | uffff = uffff * 16 + hex; 173 | } 174 | string += String.fromCharCode(uffff); 175 | } else if (typeof escapee[ch] === 'string') { 176 | string += escapee[ch]; 177 | } else { 178 | break; 179 | } 180 | } else { 181 | string += ch; 182 | } 183 | } 184 | } 185 | error("Bad string"); 186 | }, 187 | 188 | white = function () { 189 | 190 | // Skip whitespace. 191 | 192 | while (ch && ch <= ' ') { 193 | next(); 194 | } 195 | }, 196 | 197 | word = function () { 198 | 199 | // true, false, or null. 200 | 201 | switch (ch) { 202 | case 't': 203 | next('t'); 204 | next('r'); 205 | next('u'); 206 | next('e'); 207 | return true; 208 | case 'f': 209 | next('f'); 210 | next('a'); 211 | next('l'); 212 | next('s'); 213 | next('e'); 214 | return false; 215 | case 'n': 216 | next('n'); 217 | next('u'); 218 | next('l'); 219 | next('l'); 220 | return null; 221 | } 222 | error("Unexpected '" + ch + "'"); 223 | }, 224 | 225 | value, // Place holder for the value function. 226 | 227 | array = function () { 228 | 229 | // Parse an array value. 230 | 231 | var array = []; 232 | 233 | if (ch === '[') { 234 | next('['); 235 | white(); 236 | if (ch === ']') { 237 | next(']'); 238 | return array; // empty array 239 | } 240 | while (ch) { 241 | array.push(value()); 242 | white(); 243 | if (ch === ']') { 244 | next(']'); 245 | return array; 246 | } 247 | next(','); 248 | white(); 249 | } 250 | } 251 | error("Bad array"); 252 | }, 253 | 254 | object = function () { 255 | 256 | // Parse an object value. 257 | 258 | var key, 259 | object = {}; 260 | 261 | if (ch === '{') { 262 | next('{'); 263 | white(); 264 | if (ch === '}') { 265 | next('}'); 266 | return object; // empty object 267 | } 268 | while (ch) { 269 | key = string(); 270 | white(); 271 | next(':'); 272 | if (Object.hasOwnProperty.call(object, key)) { 273 | error('Duplicate key "' + key + '"'); 274 | } 275 | object[key] = value(); 276 | white(); 277 | if (ch === '}') { 278 | next('}'); 279 | return object; 280 | } 281 | next(','); 282 | white(); 283 | } 284 | } 285 | error("Bad object"); 286 | }; 287 | 288 | value = function () { 289 | 290 | // Parse a JSON value. It could be an object, an array, a string, a number, 291 | // or a word. 292 | 293 | white(); 294 | switch (ch) { 295 | case '{': 296 | return object(); 297 | case '[': 298 | return array(); 299 | case '"': 300 | return string(); 301 | case '-': 302 | return number(); 303 | default: 304 | return ch >= '0' && ch <= '9' ? number() : word(); 305 | } 306 | }; 307 | 308 | // Return the json_parse function. It will have access to all of the above 309 | // functions and variables. 310 | 311 | return function (source, reviver) { 312 | var result; 313 | 314 | text = source; 315 | at = 0; 316 | ch = ' '; 317 | result = value(); 318 | white(); 319 | if (ch) { 320 | error("Syntax error"); 321 | } 322 | 323 | // If there is a reviver function, we recursively walk the new structure, 324 | // passing each name/value pair to the reviver function for possible 325 | // transformation, starting with a temporary root object that holds the result 326 | // in an empty key. If there is not a reviver function, we simply return the 327 | // result. 328 | 329 | return typeof reviver === 'function' ? (function walk(holder, key) { 330 | var k, v, value = holder[key]; 331 | if (value && typeof value === 'object') { 332 | for (k in value) { 333 | if (Object.hasOwnProperty.call(value, k)) { 334 | v = walk(value, k); 335 | if (v !== undefined) { 336 | value[k] = v; 337 | } else { 338 | delete value[k]; 339 | } 340 | } 341 | } 342 | } 343 | return reviver.call(holder, key, value); 344 | }({'': result}, '')) : result; 345 | }; 346 | }()); -------------------------------------------------------------------------------- /banner/canvas-letters-banner.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Canvas Letters Banner 3 | * 4 | */ 5 | var canvasLettersBanner = function() { 6 | 7 | /* 8 | * The HTML body element 9 | */ 10 | var body = null, 11 | 12 | /* 13 | * The canvas HTMl element 14 | */ 15 | canvas = null, 16 | 17 | /* 18 | * The canvas draw context 19 | */ 20 | drawContext = null, 21 | 22 | /* 23 | * The draw interval 24 | */ 25 | drawInterval = null, 26 | 27 | /* 28 | * Bool - are we currently recalculating? 29 | */ 30 | redrawing = false, 31 | 32 | /* 33 | * Array of blocks to draw 34 | */ 35 | blocks = [], 36 | blockCount = 0, 37 | blockSize = 0, 38 | 39 | /* 40 | * current block drawing details 41 | */ 42 | currentX = 0, 43 | currentY = 0, 44 | 45 | /* 46 | * current animation settings 47 | */ 48 | currentXOffset = 0, 49 | textStringWidth = 0, 50 | 51 | 52 | /* 53 | * Character block dimensions 54 | */ 55 | characterBlockWidth = 5, 56 | characterBlockHeight = 7, 57 | characterWidth = 0, 58 | 59 | /* 60 | * the (potentially modified) text string we're drawing 61 | */ 62 | textString = "", 63 | 64 | /* 65 | * Debug timeout 66 | */ 67 | debugTimeout = null, 68 | 69 | /* 70 | * Characters 71 | */ 72 | characters = { 73 | "a": [0,0,1,0,0,0,1,0,1,0,1,0,0,0,1,1,0,0,0,1,1,1,1,1,1,1,0,0,0,1,1,0,0,0,1], 74 | "b": [1,1,1,1,0,1,0,0,0,1,1,0,0,0,1,1,1,1,1,0,1,0,0,0,1,1,0,0,0,1,1,1,1,1,0], 75 | "c": [0,1,1,1,0,1,0,0,0,1,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,1,0,1,1,1,0], 76 | "d": [1,1,1,0,0,1,0,0,1,0,1,0,0,0,1,1,0,0,0,1,1,0,0,0,1,1,0,0,1,0,1,1,1,0,0], 77 | "e": [1,1,1,1,1,1,0,0,0,0,1,0,0,0,0,1,1,1,0,0,1,0,0,0,0,1,0,0,0,0,1,1,1,1,1], 78 | "f": [1,1,1,1,1,1,0,0,0,0,1,0,0,0,0,1,1,1,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0], 79 | "g": [0,1,1,1,0,1,0,0,0,1,1,0,0,0,0,1,0,1,1,1,1,0,0,0,1,1,0,0,0,1,0,1,1,1,1], 80 | "h": [1,0,0,0,1,1,0,0,0,1,1,0,0,0,1,1,1,1,1,1,1,0,0,0,1,1,0,0,0,1,1,0,0,0,1], 81 | "i": [1,1,1,1,1,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,1,1,1,1,1], 82 | "j": [1,1,1,1,1,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,1,0,1,0,0,1,0,1,0,0,1,1,1,0,0], 83 | "k": [1,0,0,0,1,1,0,0,1,0,1,0,1,0,0,1,1,0,0,0,1,0,1,0,0,1,0,0,1,0,1,0,0,0,1], 84 | "l": [1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,1,1,1,1], 85 | "m": [1,0,0,0,1,1,1,0,1,1,1,0,1,0,1,1,0,1,0,1,1,0,0,0,1,1,0,0,0,1,1,0,0,0,1], 86 | "n": [1,0,0,0,1,1,0,0,0,1,1,1,0,0,1,1,0,1,0,1,1,0,0,1,1,1,0,0,0,1,1,0,0,0,1], 87 | "o": [0,1,1,1,0,1,0,0,0,1,1,0,0,0,1,1,0,0,0,1,1,0,0,0,1,1,0,0,0,1,0,1,1,1,0], 88 | "p": [1,1,1,1,0,1,0,0,0,1,1,0,0,0,1,1,1,1,1,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0], 89 | "q": [0,1,1,1,0,1,0,0,0,1,1,0,0,0,1,1,0,0,0,1,1,0,1,0,1,1,0,0,1,0,0,1,1,0,1], 90 | "r": [1,1,1,1,0,1,0,0,0,1,1,0,0,0,1,1,1,1,1,0,1,0,1,0,0,1,0,0,1,0,1,0,0,0,1], 91 | "s": [0,1,1,1,0,1,0,0,0,1,1,0,0,0,0,0,1,1,1,0,0,0,0,0,1,1,0,0,0,1,0,1,1,1,0], 92 | "t": [1,1,1,1,1,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0], 93 | "u": [1,0,0,0,1,1,0,0,0,1,1,0,0,0,1,1,0,0,0,1,1,0,0,0,1,1,0,0,0,1,0,1,1,1,0], 94 | "v": [1,0,0,0,1,1,0,0,0,1,1,0,0,0,1,0,1,0,1,0,0,1,0,1,0,0,0,1,0,0,0,0,1,0,0], 95 | "w": [1,0,0,0,1,1,0,0,0,1,1,0,0,0,1,1,0,1,0,1,1,0,1,0,1,1,0,1,0,1,0,1,0,1,0], 96 | "x": [1,0,0,0,1,1,0,0,0,1,0,1,0,1,0,0,0,1,0,0,0,1,0,1,0,1,0,0,0,1,1,0,0,0,1], 97 | "y": [1,0,0,0,1,1,0,0,0,1,1,0,0,0,1,0,1,0,1,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0], 98 | "z": [1,1,1,1,1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1,1,1,1,1], 99 | "0": [0,1,1,1,0,1,0,0,0,1,1,0,0,1,1,1,0,1,0,1,1,1,0,0,1,1,0,0,0,1,0,1,1,1,0], 100 | "1": [0,0,1,0,0,0,1,1,0,0,1,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,1,1,1,1,1], 101 | "2": [0,1,1,1,0,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,1], 102 | "3": [0,1,1,1,0,1,0,0,0,1,0,0,0,0,1,0,0,1,1,0,0,0,0,0,1,1,0,0,0,1,0,1,1,1,0], 103 | "4": [0,0,0,1,0,0,0,1,1,0,0,1,0,1,0,1,0,0,1,0,1,1,1,1,1,0,0,0,1,0,0,0,0,1,0], 104 | "5": [1,1,1,1,1,1,0,0,0,0,1,0,0,0,0,1,1,1,1,0,0,0,0,0,1,1,0,0,0,1,0,1,1,1,0], 105 | "6": [0,0,1,1,0,0,1,0,0,0,1,0,0,0,0,1,1,1,1,0,1,0,0,0,1,1,0,0,0,1,0,1,1,1,0], 106 | "7": [1,1,1,1,1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0], 107 | "8": [0,1,1,1,0,1,0,0,0,1,1,0,0,0,1,0,1,1,1,0,1,0,0,0,1,1,0,0,0,1,0,1,1,1,0], 108 | "9": [0,1,1,1,0,1,0,0,0,1,1,0,0,0,1,0,1,1,1,1,0,0,0,0,1,0,0,0,1,0,0,1,1,0,0], 109 | " ": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 110 | "!": [0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0], 111 | "@": [0,1,1,1,0,1,0,0,0,1,1,0,1,1,1,1,0,1,0,1,1,0,1,1,0,1,0,0,0,1,0,1,1,1,0], 112 | "€": [0,0,1,0,0,0,1,0,1,0,1,0,0,0,1,1,1,0,0,0,1,0,0,0,1,0,1,0,1,0,0,0,1,0,0], 113 | "£": [0,0,1,0,0,0,1,0,1,0,1,0,0,0,1,1,1,1,0,0,1,0,0,0,0,1,0,0,0,1,1,1,1,1,1], 114 | "#": [0,0,0,0,0,0,1,0,1,0,1,1,1,1,1,0,1,0,1,0,1,1,1,1,1,0,1,0,1,0,0,0,0,0,0], 115 | "$": [0,0,1,0,0,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,0,0,1,0,0], 116 | "%": [0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0], 117 | "^": [0,0,1,0,0,0,1,0,1,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 118 | "&": [0,1,1,0,0,1,0,0,1,0,1,0,1,0,0,0,1,0,0,0,1,0,1,0,1,1,0,0,1,0,0,1,1,0,1], 119 | "*": [1,0,1,0,1,0,1,1,1,0,1,1,1,1,1,0,1,1,1,0,1,0,1,0,1,0,0,0,0,0,0,0,0,0,0], 120 | "(": [0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1], 121 | ")": [1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0], 122 | "-": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 123 | "_": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1], 124 | "+": [0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,1,1,1,1,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0], 125 | "=": [0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0], 126 | "[": [1,1,1,1,1,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,1,1,1,1], 127 | "]": [1,1,1,1,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,1,1,1,1,1], 128 | "{": [0,1,1,1,1,0,1,0,0,0,0,1,0,0,0,1,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,1,1,1], 129 | "}": [1,1,1,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,1,0,0,0,1,0,0,0,0,1,0,1,1,1,1,0], 130 | ":": [0,0,0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0], 131 | ";": [0,0,0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,1,1,0,0,0,1,1,0,0,1,1,0,0,0], 132 | "\"": [0,1,0,1,0,0,1,0,1,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 133 | "'": [0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 134 | "|": [0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0], 135 | "\\": [0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0], 136 | "~": [0,0,0,0,0,0,1,0,0,0,1,0,1,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 137 | "`": [0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 138 | "<": [0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1], 139 | ",": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,1,1,0,0,1,1,0,0,0], 140 | ">": [1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0], 141 | ".": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,1,1,0], 142 | "?": [0,1,1,1,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0], 143 | "/": [0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0] 144 | }, 145 | 146 | 147 | 148 | /* 149 | * default options 150 | * (the ones to copy from if an option isn't specified specifically) 151 | */ 152 | defaults = { 153 | blockColour : "ff9900", 154 | canvasColour : "000000", 155 | textString : "Lorem ipsum dolor sit amet, consectetur adipisicing elit", 156 | clearance : 30, 157 | speed : 50, 158 | animate : false, 159 | debugMode : false 160 | }, 161 | 162 | /* 163 | * config options 164 | * (the combined options, the ones to use) 165 | */ 166 | options = {}, 167 | 168 | 169 | /* 170 | * initialisation method 171 | */ 172 | init = function(initOptions){ 173 | 174 | debug("init()"); 175 | 176 | // save the init options 177 | saveOptions(initOptions); 178 | 179 | // create canvas element 180 | if (!canvas) { 181 | createCanvas(); 182 | } 183 | 184 | // init canvas set-up 185 | startLetters(); 186 | 187 | // reset on resize 188 | if (!options.inline) { 189 | window.onresize = function() { 190 | startLetters(); 191 | }; 192 | } 193 | }, 194 | 195 | 196 | /* 197 | * save any options sent through to the intialisation script, if set 198 | */ 199 | saveOptions = function(initOptions) { 200 | 201 | debug('saveOptions()'); 202 | 203 | for (var option in defaults) { 204 | if (!!initOptions[option] || initOptions[option] === false) { 205 | options[option] = initOptions[option]; 206 | } else { 207 | options[option] = defaults[option]; 208 | } 209 | } 210 | }, 211 | 212 | 213 | 214 | /* 215 | * Create canvas element 216 | */ 217 | createCanvas = function() { 218 | 219 | debug("createCanvas()"); 220 | 221 | // condition : if we are creating a full-screen canvas 222 | if (!options.inline) { 223 | 224 | // create canvas 225 | canvas = document.createElement('canvas'); 226 | canvas.id = "canvas"; 227 | canvas.style.position = "absolute"; 228 | canvas.style.zIndex = 1; 229 | canvas.style.left = 0; 230 | canvas.style.top = 0; 231 | 232 | // add the canvas into the page 233 | body = document.getElementsByTagName('body')[0]; 234 | body.appendChild(canvas); 235 | 236 | // if we are using an existing canvas element inline in the page 237 | } else { 238 | canvas = document.getElementById(options.canvasId); 239 | } 240 | 241 | // get the draw context 242 | drawContext = canvas.getContext("2d"); 243 | }, 244 | 245 | 246 | 247 | /* 248 | * Start letters 249 | */ 250 | startLetters = function() { 251 | 252 | debug('startLetters()'); 253 | 254 | // catch multiple calls 255 | if (!redrawing) { 256 | 257 | redrawing = true; 258 | 259 | clearInterval(drawInterval); 260 | 261 | // init values 262 | blocks = []; 263 | blockCount = 0; 264 | currentX = options.clearance; 265 | currentY = options.clearance; 266 | textString = options.textString.toLowerCase(); 267 | 268 | // set up functions 269 | setCanvasWidth(); 270 | setCanvasHeight(); 271 | setBlockSize(); 272 | calculateBlockPositions(); 273 | setLoopWidth(); 274 | 275 | currentXOffset = -canvas.width; 276 | 277 | debug('textStringWidth: ' + textStringWidth); 278 | 279 | // start loop 280 | drawInterval = setInterval(draw, 20); 281 | 282 | // redrawing complete! 283 | redrawing = false; 284 | } 285 | }, 286 | 287 | 288 | /* 289 | * 290 | */ 291 | setCanvasWidth = function() { 292 | canvas.width = document.body.offsetWidth; 293 | }, 294 | 295 | 296 | /* 297 | * 298 | */ 299 | setCanvasHeight = function() { 300 | canvas.height = document.documentElement.clientHeight; 301 | }, 302 | 303 | 304 | /* 305 | * 306 | */ 307 | setBlockSize = function() { 308 | blockSize = Math.floor((canvas.height - (options.clearance*2)) / characterBlockHeight); 309 | }, 310 | 311 | 312 | /* 313 | * 314 | */ 315 | calculateBlockPositions = function() { 316 | 317 | debug('calculateBlockPositions()'); 318 | 319 | characterWidth = (blockSize * characterBlockWidth) + options.clearance; 320 | 321 | // draw the text string 322 | for (var character = 0, textStringLength = textString.length; character < textString.length; character++) { 323 | 324 | // if we can draw this letter, begin 325 | if (!!characters[textString[character]]) { 326 | 327 | // if this isn't the first character, work out how far along the line to put it 328 | if (character > 0) { 329 | currentX += characterWidth; 330 | } 331 | 332 | // get the blocks for this character 333 | var blockArray = characters[textString[character]]; 334 | 335 | // for each block within a character 336 | for (var block = 0, blockArrayLength = blockArray.length; block < blockArrayLength; block++) { 337 | 338 | // calculate X & Y positions for each block 339 | var x = currentX; 340 | var y = currentY; 341 | x += (blockSize * (block % characterBlockWidth)); 342 | if (block >= characterBlockWidth) { 343 | y += (blockSize*(Math.floor(block/characterBlockWidth))); 344 | } 345 | 346 | // if we're drawing a block, add it to the array 347 | if (blockArray[block] == 1) { 348 | //debug('draw a block at ' + x + ', ' + y); 349 | blocks.push({x:x,y:y,opacity:0}); 350 | } 351 | } 352 | } else { 353 | debug("calculateBlockPositions() - letter not recognised: " + textString[character]); 354 | } 355 | } 356 | 357 | blockCount = blocks.length; 358 | debug('calculateBlockPositions() - block count: ' + blockCount); 359 | }, 360 | 361 | 362 | 363 | /* 364 | * 365 | */ 366 | setLoopWidth = function() { 367 | textStringWidth = blocks[blocks.length-1].x; 368 | }, 369 | 370 | 371 | /* 372 | * 373 | */ 374 | drawRectangle = function(x,y,w,h) { 375 | drawContext.beginPath(); 376 | drawContext.rect(x,y,w,h); 377 | drawContext.closePath(); 378 | drawContext.fill(); 379 | }, 380 | 381 | 382 | 383 | /* 384 | * 385 | */ 386 | draw = function() { 387 | 388 | // clear canvas 389 | drawContext.clearRect(0,0,canvas.width,canvas.height); 390 | 391 | // draw background 392 | drawContext.fillStyle = "#"+options.canvasColour; 393 | drawContext.fillRect(0, 0, canvas.width, canvas.height); 394 | 395 | // normal direction, add blocks 396 | var drawColour = options.blockColour; 397 | 398 | // calculate which blocks to work on 399 | var animateLimit = blocks.length; 400 | 401 | // loop through blocks and draw! 402 | for (var counter = animateLimit; counter >= 0; counter--) { 403 | if (!!blocks[counter]) { 404 | if (blocks[counter].x > currentXOffset-blockSize && blocks[counter].x < currentXOffset+canvas.width) { 405 | drawContext.fillStyle = "#"+options.blockColour; 406 | drawRectangle(blocks[counter].x-currentXOffset, blocks[counter].y, blockSize, blockSize); 407 | } 408 | } 409 | }; 410 | 411 | // add one to loop 412 | currentXOffset+=options.speed; 413 | 414 | // calculate whether to end the drawing 415 | if (currentXOffset >= textStringWidth + canvas.width) { 416 | currentXOffset = -canvas.width; 417 | } 418 | }, 419 | 420 | 421 | /* 422 | * Debug 423 | * output debug messages 424 | * 425 | * @return void 426 | * @private 427 | */ 428 | debug = function(content) { 429 | if (!!options.debugMode) { 430 | console.log(content); 431 | clearTimeout(debugTimeout); 432 | debugTimeout = setTimeout(debugSpacer, 2000); 433 | } 434 | }, 435 | debugSpacer = function() { 436 | if (!!options.debugMode) { 437 | console.log("----------------------------------------------------------------------------------"); 438 | } 439 | }; 440 | 441 | 442 | 443 | /* 444 | * expose public methods 445 | */ 446 | return { 447 | init: init 448 | }; 449 | }; -------------------------------------------------------------------------------- /save/canvas-letters.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Canvas Letters 3 | * 4 | */ 5 | var canvasLetters = function() { 6 | 7 | /* 8 | * The HTML body element 9 | */ 10 | var body = null, 11 | 12 | /* 13 | * The canvas HTMl element 14 | */ 15 | canvas = null, 16 | 17 | /* 18 | * The canvas draw context 19 | */ 20 | drawContext = null, 21 | 22 | /* 23 | * The draw interval 24 | */ 25 | drawInterval = null, 26 | 27 | /* 28 | * Bool - are we currently recalculating? 29 | */ 30 | redrawing = false, 31 | 32 | /* 33 | * Bool - are we currently reversing 34 | */ 35 | reversing = false, 36 | 37 | /* 38 | * Array of blocks to draw 39 | */ 40 | blocks = [], 41 | blockCount = 0, 42 | 43 | /* 44 | * current block drawing details 45 | */ 46 | currentX = 0, 47 | currentY = 0, 48 | currentBlock = 0, 49 | lineCount = 1, 50 | 51 | /* 52 | * Character block dimensions 53 | */ 54 | characterBlockWidth = 5, 55 | characterBlockHeight = 7, 56 | 57 | /* 58 | * the (potentially modified) text string we're drawing 59 | */ 60 | textString = "", 61 | 62 | /* 63 | * Debug timeout 64 | */ 65 | debugTimeout = null, 66 | 67 | /* 68 | * Characters 69 | */ 70 | characters = { 71 | "a": [0,0,1,0,0,0,1,0,1,0,1,0,0,0,1,1,0,0,0,1,1,1,1,1,1,1,0,0,0,1,1,0,0,0,1], 72 | "b": [1,1,1,1,0,1,0,0,0,1,1,0,0,0,1,1,1,1,1,0,1,0,0,0,1,1,0,0,0,1,1,1,1,1,0], 73 | "c": [0,1,1,1,0,1,0,0,0,1,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,1,0,1,1,1,0], 74 | "d": [1,1,1,0,0,1,0,0,1,0,1,0,0,0,1,1,0,0,0,1,1,0,0,0,1,1,0,0,1,0,1,1,1,0,0], 75 | "e": [1,1,1,1,1,1,0,0,0,0,1,0,0,0,0,1,1,1,0,0,1,0,0,0,0,1,0,0,0,0,1,1,1,1,1], 76 | "f": [1,1,1,1,1,1,0,0,0,0,1,0,0,0,0,1,1,1,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0], 77 | "g": [0,1,1,1,0,1,0,0,0,1,1,0,0,0,0,1,0,1,1,1,1,0,0,0,1,1,0,0,0,1,0,1,1,1,1], 78 | "h": [1,0,0,0,1,1,0,0,0,1,1,0,0,0,1,1,1,1,1,1,1,0,0,0,1,1,0,0,0,1,1,0,0,0,1], 79 | "i": [1,1,1,1,1,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,1,1,1,1,1], 80 | "j": [1,1,1,1,1,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,1,0,1,0,0,1,0,1,0,0,1,1,1,0,0], 81 | "k": [1,0,0,0,1,1,0,0,1,0,1,0,1,0,0,1,1,0,0,0,1,0,1,0,0,1,0,0,1,0,1,0,0,0,1], 82 | "l": [1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,1,1,1,1], 83 | "m": [1,0,0,0,1,1,1,0,1,1,1,0,1,0,1,1,0,1,0,1,1,0,0,0,1,1,0,0,0,1,1,0,0,0,1], 84 | "n": [1,0,0,0,1,1,0,0,0,1,1,1,0,0,1,1,0,1,0,1,1,0,0,1,1,1,0,0,0,1,1,0,0,0,1], 85 | "o": [0,1,1,1,0,1,0,0,0,1,1,0,0,0,1,1,0,0,0,1,1,0,0,0,1,1,0,0,0,1,0,1,1,1,0], 86 | "p": [1,1,1,1,0,1,0,0,0,1,1,0,0,0,1,1,1,1,1,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0], 87 | "q": [0,1,1,1,0,1,0,0,0,1,1,0,0,0,1,1,0,0,0,1,1,0,1,0,1,1,0,0,1,0,0,1,1,0,1], 88 | "r": [1,1,1,1,0,1,0,0,0,1,1,0,0,0,1,1,1,1,1,0,1,0,1,0,0,1,0,0,1,0,1,0,0,0,1], 89 | "s": [0,1,1,1,0,1,0,0,0,1,1,0,0,0,0,0,1,1,1,0,0,0,0,0,1,1,0,0,0,1,0,1,1,1,0], 90 | "t": [1,1,1,1,1,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0], 91 | "u": [1,0,0,0,1,1,0,0,0,1,1,0,0,0,1,1,0,0,0,1,1,0,0,0,1,1,0,0,0,1,0,1,1,1,0], 92 | "v": [1,0,0,0,1,1,0,0,0,1,1,0,0,0,1,0,1,0,1,0,0,1,0,1,0,0,0,1,0,0,0,0,1,0,0], 93 | "w": [1,0,0,0,1,1,0,0,0,1,1,0,0,0,1,1,0,1,0,1,1,0,1,0,1,1,0,1,0,1,0,1,0,1,0], 94 | "x": [1,0,0,0,1,1,0,0,0,1,0,1,0,1,0,0,0,1,0,0,0,1,0,1,0,1,0,0,0,1,1,0,0,0,1], 95 | "y": [1,0,0,0,1,1,0,0,0,1,1,0,0,0,1,0,1,0,1,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0], 96 | "z": [1,1,1,1,1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1,1,1,1,1], 97 | "0": [0,1,1,1,0,1,0,0,0,1,1,0,0,1,1,1,0,1,0,1,1,1,0,0,1,1,0,0,0,1,0,1,1,1,0], 98 | "1": [0,0,1,0,0,0,1,1,0,0,1,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,1,1,1,1,1], 99 | "2": [0,1,1,1,0,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,1], 100 | "3": [0,1,1,1,0,1,0,0,0,1,0,0,0,0,1,0,0,1,1,0,0,0,0,0,1,1,0,0,0,1,0,1,1,1,0], 101 | "4": [0,0,0,1,0,0,0,1,1,0,0,1,0,1,0,1,0,0,1,0,1,1,1,1,1,0,0,0,1,0,0,0,0,1,0], 102 | "5": [1,1,1,1,1,1,0,0,0,0,1,0,0,0,0,1,1,1,1,0,0,0,0,0,1,1,0,0,0,1,0,1,1,1,0], 103 | "6": [0,0,1,1,0,0,1,0,0,0,1,0,0,0,0,1,1,1,1,0,1,0,0,0,1,1,0,0,0,1,0,1,1,1,0], 104 | "7": [1,1,1,1,1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0], 105 | "8": [0,1,1,1,0,1,0,0,0,1,1,0,0,0,1,0,1,1,1,0,1,0,0,0,1,1,0,0,0,1,0,1,1,1,0], 106 | "9": [0,1,1,1,0,1,0,0,0,1,1,0,0,0,1,0,1,1,1,1,0,0,0,0,1,0,0,0,1,0,0,1,1,0,0], 107 | " ": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 108 | "!": [0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0], 109 | "@": [0,1,1,1,0,1,0,0,0,1,1,0,1,1,1,1,0,1,0,1,1,0,1,1,0,1,0,0,0,1,0,1,1,1,0], 110 | "€": [0,0,1,0,0,0,1,0,1,0,1,0,0,0,1,1,1,0,0,0,1,0,0,0,1,0,1,0,1,0,0,0,1,0,0], 111 | "£": [0,0,1,0,0,0,1,0,1,0,1,0,0,0,1,1,1,1,0,0,1,0,0,0,0,1,0,0,0,1,1,1,1,1,1], 112 | "#": [0,0,0,0,0,0,1,0,1,0,1,1,1,1,1,0,1,0,1,0,1,1,1,1,1,0,1,0,1,0,0,0,0,0,0], 113 | "$": [0,0,1,0,0,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,0,0,1,0,0], 114 | "%": [0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0], 115 | "^": [0,0,1,0,0,0,1,0,1,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 116 | "&": [0,1,1,0,0,1,0,0,1,0,1,0,1,0,0,0,1,0,0,0,1,0,1,0,1,1,0,0,1,0,0,1,1,0,1], 117 | "*": [1,0,1,0,1,0,1,1,1,0,1,1,1,1,1,0,1,1,1,0,1,0,1,0,1,0,0,0,0,0,0,0,0,0,0], 118 | "(": [0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1], 119 | ")": [1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0], 120 | "-": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 121 | "_": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1], 122 | "+": [0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,1,1,1,1,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0], 123 | "=": [0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0], 124 | "[": [1,1,1,1,1,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,1,1,1,1], 125 | "]": [1,1,1,1,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,1,1,1,1,1], 126 | "{": [0,1,1,1,1,0,1,0,0,0,0,1,0,0,0,1,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,1,1,1], 127 | "}": [1,1,1,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,1,0,0,0,1,0,0,0,0,1,0,1,1,1,1,0], 128 | ":": [0,0,0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0], 129 | ";": [0,0,0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,1,1,0,0,0,1,1,0,0,1,1,0,0,0], 130 | "\"": [0,1,0,1,0,0,1,0,1,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 131 | "'": [0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 132 | "|": [0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0], 133 | "\\": [0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0], 134 | "~": [0,0,0,0,0,0,1,0,0,0,1,0,1,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 135 | "`": [0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 136 | "<": [0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1], 137 | ",": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,1,1,0,0,1,1,0,0,0], 138 | ">": [1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0], 139 | ".": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,1,1,0], 140 | "?": [0,1,1,1,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0], 141 | "/": [0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0] 142 | }, 143 | 144 | 145 | 146 | /* 147 | * default options 148 | * (the ones to copy from if an option isn't specified specifically) 149 | */ 150 | defaults = { 151 | inline : false, 152 | canvasId : null, 153 | blockColour : "ff9900", 154 | canvasColour : "000000", 155 | blockSize : 10, 156 | textString : "Lorem ipsum dolor sit amet, consectetur adipisicing elit", 157 | breakWord : false, 158 | clearance : 30, 159 | ordering : 'default', 160 | loop : false, 161 | speed : 10, 162 | animate : false, 163 | debugMode : false 164 | }, 165 | 166 | /* 167 | * config options 168 | * (the combined options, the ones to use) 169 | */ 170 | options = {}, 171 | 172 | 173 | /* 174 | * initialisation method 175 | */ 176 | init = function(initOptions){ 177 | 178 | debug("init()"); 179 | 180 | // save the init options 181 | saveOptions(initOptions); 182 | 183 | // create canvas element 184 | if (!canvas) { 185 | createCanvas(); 186 | } 187 | 188 | // init canvas set-up 189 | startLetters(); 190 | 191 | // reset on resize 192 | if (!options.inline) { 193 | window.onresize = function() { 194 | startLetters(); 195 | }; 196 | } 197 | }, 198 | 199 | 200 | /* 201 | * save any options sent through to the intialisation script, if set 202 | */ 203 | saveOptions = function(initOptions) { 204 | 205 | debug('saveOptions()'); 206 | 207 | for (var option in defaults) { 208 | if (!!initOptions[option] || initOptions[option] === false) { 209 | options[option] = initOptions[option]; 210 | } else { 211 | options[option] = defaults[option]; 212 | } 213 | } 214 | }, 215 | 216 | 217 | 218 | /* 219 | * Create canvas element 220 | */ 221 | createCanvas = function() { 222 | 223 | debug("createCanvas()"); 224 | 225 | // condition : if we are creating a full-screen canvas 226 | if (!options.inline) { 227 | 228 | // create canvas 229 | canvas = document.createElement('canvas'); 230 | canvas.id = "canvas"; 231 | canvas.style.position = "absolute"; 232 | canvas.style.zIndex = 1; 233 | canvas.style.left = 0; 234 | canvas.style.top = 0; 235 | 236 | // add the canvas into the page 237 | body = document.getElementsByTagName('body')[0]; 238 | body.appendChild(canvas); 239 | 240 | // if we are using an existing canvas element inline in the page 241 | } else { 242 | canvas = document.getElementById(options.canvasId); 243 | } 244 | 245 | // get the draw context 246 | drawContext = canvas.getContext("2d"); 247 | }, 248 | 249 | 250 | 251 | /* 252 | * Start letters 253 | */ 254 | startLetters = function() { 255 | 256 | debug('startLetters()'); 257 | 258 | // catch multiple calls 259 | if (!redrawing) { 260 | 261 | redrawing = true; 262 | 263 | clearInterval(drawInterval); 264 | 265 | // init values 266 | lineCount = 1; 267 | currentBlock = 0; 268 | blocks = []; 269 | blockCount = 0; 270 | reversing = false; 271 | currentX = options.clearance; 272 | currentY = options.clearance; 273 | 274 | // set up functions 275 | if (!options.inline) { 276 | setCanvasWidth(); 277 | } 278 | fixTextLength(); 279 | calculateBlockPositions(); 280 | if (!options.inline) { 281 | setCanvasHeight(); 282 | } 283 | 284 | // if we're not animating, show everything at once 285 | if (!options.animate) { 286 | currentBlock = blocks.length; 287 | } 288 | 289 | // draw background 290 | drawContext.fillStyle = "#"+options.canvasColour; 291 | drawContext.fillRect(0, 0, canvas.width, canvas.height); 292 | 293 | // start loop 294 | drawInterval = setInterval(draw, options.speed); 295 | 296 | // redrawing complete! 297 | redrawing = false; 298 | } 299 | }, 300 | 301 | 302 | /* 303 | * 304 | */ 305 | setCanvasWidth = function() { 306 | 307 | debug("setCanvasWidth()"); 308 | 309 | canvas.width = document.body.offsetWidth; 310 | }, 311 | 312 | 313 | /* 314 | * 315 | */ 316 | setCanvasHeight = function() { 317 | var canvasHeight = (lineCount*(characterBlockHeight*options.blockSize))+((lineCount+2)*options.clearance); 318 | if (canvasHeight < document.documentElement.clientHeight) { canvasHeight = document.documentElement.clientHeight; } 319 | canvas.height = canvasHeight; 320 | 321 | debug("setCanvasHeight() - " + canvasHeight + " ("+lineCount+" lines)"); 322 | }, 323 | 324 | 325 | /* 326 | * 327 | */ 328 | fixTextLength = function() { 329 | 330 | debug('fixTextLength()'); 331 | 332 | textString = options.textString.toLowerCase(); 333 | 334 | // calculate line length 335 | var lineLength = Math.floor( ( canvas.width - options.clearance ) / ( ( characterBlockWidth * options.blockSize ) + options.clearance ) ); 336 | debug('fixTextLength() - line length: ' + lineLength); 337 | 338 | // test each word invidivually 339 | textStringArray = textString.split(" "); 340 | for (var counter = textStringArray.length - 1; counter >= 0; counter--){ 341 | 342 | // if any words are longer than the line-length, hyphenate 343 | if (textStringArray[counter].length > lineLength) { 344 | 345 | var originalWord = word = textStringArray[counter]; 346 | var wordArray = []; 347 | 348 | debug('fixTextLength() - word is too long: ' + word); 349 | 350 | // split the word every time it hits the line length 351 | while (word.length > lineLength) { 352 | wordArray.push(word.substr(0, lineLength-1)); 353 | word = word.substr(lineLength-1); 354 | } 355 | wordArray.push(word); 356 | 357 | textString = textString.replace(originalWord, wordArray.join("- ")); 358 | } 359 | }; 360 | 361 | }, 362 | 363 | 364 | 365 | /* 366 | * 367 | */ 368 | calculateBlockPositions = function() { 369 | 370 | debug('calculateBlockPositions()'); 371 | 372 | // draw the text string 373 | for (var character = 0, textStringLength = textString.length; character < textString.length; character++) { 374 | 375 | // if we can draw this letter, begin 376 | if (!!characters[textString[character]]) { 377 | 378 | // if this isn't the first character, work out how far along the line to put it 379 | if (character > 0) { 380 | currentX += (options.blockSize * characterBlockWidth) + options.clearance; 381 | } 382 | 383 | // find the position of the next space (to calculate the word length) 384 | var nextSpacePosition = textString.indexOf(" ", character); 385 | if (nextSpacePosition == -1) { nextSpacePosition = textStringLength; } 386 | 387 | // start working out where to place the new letter/word 388 | var newLineRequired = false; 389 | 390 | 391 | // condition : if we're not breaking words then check the whole word will fit on the next line 392 | if (!options.breakWord) { 393 | 394 | // condition : is this word going to fit on the current line? 395 | if (currentX + (options.blockSize * (characterBlockWidth*(nextSpacePosition-character))) + (options.clearance*(nextSpacePosition-character)) > canvas.width - options.clearance) { 396 | newLineRequired = true; 397 | } 398 | 399 | // breaking words is fine 400 | } else { 401 | // condition : is this letter going to fit on the current line? 402 | if (currentX + (options.blockSize * characterBlockWidth) > canvas.width - options.clearance) { 403 | newLineRequired = true; 404 | } 405 | } 406 | 407 | 408 | // condition : start a new line? 409 | if (newLineRequired && textString[character] != " ") { 410 | currentX = options.clearance; 411 | currentY = (lineCount*(characterBlockHeight*options.blockSize)) + (options.clearance*++lineCount); 412 | } 413 | 414 | 415 | // get the blocks for this character 416 | var blockArray = characters[textString[character]]; 417 | 418 | // for each block within a character 419 | for (var block = 0, blockArrayLength = blockArray.length; block < blockArrayLength; block++) { 420 | 421 | // calculate X & Y positions for each block 422 | var x = currentX; 423 | var y = currentY; 424 | x += (options.blockSize * (block % characterBlockWidth)); 425 | if (block >= characterBlockWidth) { 426 | y += (options.blockSize*(Math.floor(block/characterBlockWidth))); 427 | } 428 | 429 | // if we're drawing a block, add it to the array 430 | if (blockArray[block] == 1) { 431 | blocks.push({x:x,y:y,opacity:0}); 432 | } 433 | } 434 | } else { 435 | debug("calculateBlockPositions() - letter not recognised: " + textString[character]); 436 | } 437 | } 438 | 439 | // condition : change order of appearing blocks 440 | switch (options.ordering) { 441 | case "vertical": 442 | function vertical(a, b) { return a.y - b.y; } 443 | blocks.sort(vertical); 444 | break; 445 | 446 | case "horizontal": 447 | function horizontal(a, b) { return a.x - b.x; } 448 | blocks.sort(horizontal); 449 | break; 450 | 451 | case "reverse": 452 | blocks.reverse(); 453 | break; 454 | 455 | case "random": 456 | function randOrd(){ return (Math.round(Math.random())-0.5); } 457 | blocks.sort(randOrd); 458 | break; 459 | } 460 | 461 | 462 | blockCount = blocks.length; 463 | debug('calculateBlockPositions() - block count: ' + blockCount); 464 | }, 465 | 466 | 467 | 468 | /* 469 | * 470 | */ 471 | drawCircle = function(x,y,r) { 472 | drawContext.beginPath(); 473 | drawContext.arc(x, y, r, 0, Math.PI*2, true); 474 | drawContext.closePath(); 475 | drawContext.fill(); 476 | }, 477 | 478 | 479 | /* 480 | * 481 | */ 482 | drawRectangle = function(x,y,w,h) { 483 | drawContext.beginPath(); 484 | drawContext.rect(x,y,w,h); 485 | drawContext.closePath(); 486 | drawContext.fill(); 487 | }, 488 | 489 | 490 | 491 | /* 492 | * 493 | */ 494 | draw = function() { 495 | 496 | // normal direction, add blocks 497 | var drawColour = (!reversing) ? options.blockColour : options.canvasColour; 498 | 499 | // calculate which blocks to work on 500 | var animateLimit = (!!options.animate) ? currentBlock-10 : 0; 501 | 502 | // loop through blocks and draw! 503 | for (var counter = animateLimit; counter < currentBlock; counter++) { 504 | if (!!blocks[counter]) { 505 | if (blocks[counter].opacity < 1) { blocks[counter].opacity += 0.1; } 506 | drawContext.fillStyle = "rgba("+HexToRGB(drawColour)+", "+blocks[counter].opacity+")"; 507 | drawRectangle(blocks[counter].x, blocks[counter].y, options.blockSize, options.blockSize); 508 | //drawCircle(blocks[counter].x, blocks[counter].y, options.blockSize); 509 | } 510 | }; 511 | 512 | // add one to loop 513 | currentBlock++; 514 | 515 | // calculate whether to end the drawing 516 | if (currentBlock == blockCount+10) { 517 | if (!options.loop || !options.animate) { 518 | clearInterval(drawInterval); 519 | debug('finished drawing'); 520 | } else { 521 | blocks.reverse(); 522 | for (var count = blocks.length - 1; count >= 0; count--){ blocks[count].opacity = 0;} 523 | reversing = !reversing; 524 | currentBlock = 0; 525 | } 526 | } 527 | }, 528 | 529 | 530 | 531 | /* 532 | * Turn Hex into RGB, for block colour 533 | */ 534 | HexToRGB = function(h) {return HexToR(h) +","+HexToG(h)+","+HexToB(h);}, 535 | HexToR = function(h) {return parseInt((cutHex(h)).substring(0,2),16);}, 536 | HexToG = function(h) {return parseInt((cutHex(h)).substring(2,4),16);}, 537 | HexToB = function(h) {return parseInt((cutHex(h)).substring(4,6),16);}, 538 | cutHex = function(h) {return (h.charAt(0)=="#") ? h.substring(1,7):h;}, 539 | 540 | 541 | /* 542 | * Debug 543 | * output debug messages 544 | * 545 | * @return void 546 | * @private 547 | */ 548 | debug = function(content) { 549 | if (!!options.debugMode) { 550 | console.log(content); 551 | clearTimeout(debugTimeout); 552 | debugTimeout = setTimeout(debugSpacer, 2000); 553 | } 554 | }, 555 | debugSpacer = function() { 556 | if (!!options.debugMode) { 557 | console.log("----------------------------------------------------------------------------------"); 558 | } 559 | }; 560 | 561 | 562 | 563 | /* 564 | * expose public methods 565 | */ 566 | return { 567 | init: init 568 | }; 569 | }; -------------------------------------------------------------------------------- /canvas-letters.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Canvas Letters 3 | * 4 | */ 5 | var canvasLetters = function() { 6 | 7 | /* 8 | * The HTML body element 9 | */ 10 | var body = null, 11 | 12 | /* 13 | * The canvas HTMl element 14 | */ 15 | canvas = null, 16 | 17 | /* 18 | * The canvas draw context 19 | */ 20 | drawContext = null, 21 | 22 | /* 23 | * The draw interval 24 | */ 25 | drawInterval = null, 26 | 27 | /* 28 | * Bool - are we currently recalculating? 29 | */ 30 | redrawing = false, 31 | 32 | /* 33 | * Bool - are we currently reversing 34 | */ 35 | reversing = false, 36 | 37 | /* 38 | * Array of blocks to draw 39 | */ 40 | blocks = [], 41 | blockCount = 0, 42 | 43 | /* 44 | * current block drawing details 45 | */ 46 | currentX = 0, 47 | currentY = 0, 48 | currentBlock = 0, 49 | lineCount = 1, 50 | 51 | /* 52 | * Character block dimensions 53 | */ 54 | characterBlockWidth = 5, 55 | characterBlockHeight = 7, 56 | 57 | /* 58 | * the (potentially modified) text string we're drawing 59 | */ 60 | textString = "", 61 | 62 | /* 63 | * Debug timeout 64 | */ 65 | debugTimeout = null, 66 | 67 | /* 68 | * Characters 69 | */ 70 | characters = { 71 | "a": [0,0,1,0,0,0,1,0,1,0,1,0,0,0,1,1,0,0,0,1,1,1,1,1,1,1,0,0,0,1,1,0,0,0,1], 72 | "b": [1,1,1,1,0,1,0,0,0,1,1,0,0,0,1,1,1,1,1,0,1,0,0,0,1,1,0,0,0,1,1,1,1,1,0], 73 | "c": [0,1,1,1,0,1,0,0,0,1,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,1,0,1,1,1,0], 74 | "d": [1,1,1,0,0,1,0,0,1,0,1,0,0,0,1,1,0,0,0,1,1,0,0,0,1,1,0,0,1,0,1,1,1,0,0], 75 | "e": [1,1,1,1,1,1,0,0,0,0,1,0,0,0,0,1,1,1,0,0,1,0,0,0,0,1,0,0,0,0,1,1,1,1,1], 76 | "f": [1,1,1,1,1,1,0,0,0,0,1,0,0,0,0,1,1,1,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0], 77 | "g": [0,1,1,1,0,1,0,0,0,1,1,0,0,0,0,1,0,1,1,1,1,0,0,0,1,1,0,0,0,1,0,1,1,1,1], 78 | "h": [1,0,0,0,1,1,0,0,0,1,1,0,0,0,1,1,1,1,1,1,1,0,0,0,1,1,0,0,0,1,1,0,0,0,1], 79 | "i": [1,1,1,1,1,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,1,1,1,1,1], 80 | "j": [1,1,1,1,1,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,1,0,1,0,0,1,0,1,0,0,1,1,1,0,0], 81 | "k": [1,0,0,0,1,1,0,0,1,0,1,0,1,0,0,1,1,0,0,0,1,0,1,0,0,1,0,0,1,0,1,0,0,0,1], 82 | "l": [1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,1,1,1,1], 83 | "m": [1,0,0,0,1,1,1,0,1,1,1,0,1,0,1,1,0,1,0,1,1,0,0,0,1,1,0,0,0,1,1,0,0,0,1], 84 | "n": [1,0,0,0,1,1,0,0,0,1,1,1,0,0,1,1,0,1,0,1,1,0,0,1,1,1,0,0,0,1,1,0,0,0,1], 85 | "o": [0,1,1,1,0,1,0,0,0,1,1,0,0,0,1,1,0,0,0,1,1,0,0,0,1,1,0,0,0,1,0,1,1,1,0], 86 | "p": [1,1,1,1,0,1,0,0,0,1,1,0,0,0,1,1,1,1,1,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0], 87 | "q": [0,1,1,1,0,1,0,0,0,1,1,0,0,0,1,1,0,0,0,1,1,0,1,0,1,1,0,0,1,0,0,1,1,0,1], 88 | "r": [1,1,1,1,0,1,0,0,0,1,1,0,0,0,1,1,1,1,1,0,1,0,1,0,0,1,0,0,1,0,1,0,0,0,1], 89 | "s": [0,1,1,1,0,1,0,0,0,1,1,0,0,0,0,0,1,1,1,0,0,0,0,0,1,1,0,0,0,1,0,1,1,1,0], 90 | "t": [1,1,1,1,1,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0], 91 | "u": [1,0,0,0,1,1,0,0,0,1,1,0,0,0,1,1,0,0,0,1,1,0,0,0,1,1,0,0,0,1,0,1,1,1,0], 92 | "v": [1,0,0,0,1,1,0,0,0,1,1,0,0,0,1,0,1,0,1,0,0,1,0,1,0,0,0,1,0,0,0,0,1,0,0], 93 | "w": [1,0,0,0,1,1,0,0,0,1,1,0,0,0,1,1,0,1,0,1,1,0,1,0,1,1,0,1,0,1,0,1,0,1,0], 94 | "x": [1,0,0,0,1,1,0,0,0,1,0,1,0,1,0,0,0,1,0,0,0,1,0,1,0,1,0,0,0,1,1,0,0,0,1], 95 | "y": [1,0,0,0,1,1,0,0,0,1,1,0,0,0,1,0,1,0,1,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0], 96 | "z": [1,1,1,1,1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1,1,1,1,1], 97 | "0": [0,1,1,1,0,1,0,0,0,1,1,0,0,1,1,1,0,1,0,1,1,1,0,0,1,1,0,0,0,1,0,1,1,1,0], 98 | "1": [0,0,1,0,0,0,1,1,0,0,1,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,1,1,1,1,1], 99 | "2": [0,1,1,1,0,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,1], 100 | "3": [0,1,1,1,0,1,0,0,0,1,0,0,0,0,1,0,0,1,1,0,0,0,0,0,1,1,0,0,0,1,0,1,1,1,0], 101 | "4": [0,0,0,1,0,0,0,1,1,0,0,1,0,1,0,1,0,0,1,0,1,1,1,1,1,0,0,0,1,0,0,0,0,1,0], 102 | "5": [1,1,1,1,1,1,0,0,0,0,1,0,0,0,0,1,1,1,1,0,0,0,0,0,1,1,0,0,0,1,0,1,1,1,0], 103 | "6": [0,0,1,1,0,0,1,0,0,0,1,0,0,0,0,1,1,1,1,0,1,0,0,0,1,1,0,0,0,1,0,1,1,1,0], 104 | "7": [1,1,1,1,1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0], 105 | "8": [0,1,1,1,0,1,0,0,0,1,1,0,0,0,1,0,1,1,1,0,1,0,0,0,1,1,0,0,0,1,0,1,1,1,0], 106 | "9": [0,1,1,1,0,1,0,0,0,1,1,0,0,0,1,0,1,1,1,1,0,0,0,0,1,0,0,0,1,0,0,1,1,0,0], 107 | " ": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 108 | "!": [0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0], 109 | "@": [0,1,1,1,0,1,0,0,0,1,1,0,1,1,1,1,0,1,0,1,1,0,1,1,0,1,0,0,0,1,0,1,1,1,0], 110 | "€": [0,0,1,0,0,0,1,0,1,0,1,0,0,0,1,1,1,0,0,0,1,0,0,0,1,0,1,0,1,0,0,0,1,0,0], 111 | "£": [0,0,1,0,0,0,1,0,1,0,1,0,0,0,1,1,1,1,0,0,1,0,0,0,0,1,0,0,0,1,1,1,1,1,1], 112 | "#": [0,0,0,0,0,0,1,0,1,0,1,1,1,1,1,0,1,0,1,0,1,1,1,1,1,0,1,0,1,0,0,0,0,0,0], 113 | "$": [0,0,1,0,0,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,0,0,1,0,0], 114 | "%": [0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0], 115 | "^": [0,0,1,0,0,0,1,0,1,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 116 | "&": [0,1,1,0,0,1,0,0,1,0,1,0,1,0,0,0,1,0,0,0,1,0,1,0,1,1,0,0,1,0,0,1,1,0,1], 117 | "*": [1,0,1,0,1,0,1,1,1,0,1,1,1,1,1,0,1,1,1,0,1,0,1,0,1,0,0,0,0,0,0,0,0,0,0], 118 | "(": [0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1], 119 | ")": [1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0], 120 | "-": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 121 | "_": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1], 122 | "+": [0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,1,1,1,1,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0], 123 | "=": [0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0], 124 | "[": [1,1,1,1,1,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,1,1,1,1], 125 | "]": [1,1,1,1,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,1,1,1,1,1], 126 | "{": [0,1,1,1,1,0,1,0,0,0,0,1,0,0,0,1,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,1,1,1], 127 | "}": [1,1,1,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,1,0,0,0,1,0,0,0,0,1,0,1,1,1,1,0], 128 | ":": [0,0,0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0], 129 | ";": [0,0,0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,1,1,0,0,0,1,1,0,0,1,1,0,0,0], 130 | "\"": [0,1,0,1,0,0,1,0,1,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 131 | "'": [0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 132 | "|": [0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0], 133 | "\\": [0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0], 134 | "~": [0,0,0,0,0,0,1,0,0,0,1,0,1,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 135 | "`": [0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 136 | "<": [0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1], 137 | ",": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,1,1,0,0,1,1,0,0,0], 138 | ">": [1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0], 139 | ".": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,1,1,0], 140 | "?": [0,1,1,1,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0], 141 | "/": [0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0] 142 | }, 143 | 144 | 145 | 146 | /* 147 | * default options 148 | * (the ones to copy from if an option isn't specified specifically) 149 | */ 150 | defaults = { 151 | inline : false, 152 | canvasId : null, 153 | blockColour : "ff9900", 154 | canvasColour : "000000", 155 | blockSize : 10, 156 | textString : "Lorem ipsum dolor sit amet, consectetur adipisicing elit", 157 | breakWord : false, 158 | clearance : 30, 159 | ordering : 'default', 160 | loop : false, 161 | speed : 10, 162 | animate : false, 163 | debugMode : false 164 | }, 165 | 166 | /* 167 | * config options 168 | * (the combined options, the ones to use) 169 | */ 170 | options = {}, 171 | 172 | 173 | /* 174 | * initialisation method 175 | */ 176 | init = function(initOptions){ 177 | 178 | debug("init()"); 179 | 180 | // save the init options 181 | saveOptions(initOptions); 182 | 183 | // create canvas element 184 | if (!canvas) { 185 | createCanvas(); 186 | } 187 | 188 | // init canvas set-up 189 | startLetters(); 190 | 191 | // reset on resize 192 | if (!options.inline) { 193 | window.onresize = function() { 194 | startLetters(); 195 | }; 196 | } 197 | }, 198 | 199 | 200 | /* 201 | * save any options sent through to the intialisation script, if set 202 | */ 203 | saveOptions = function(initOptions) { 204 | 205 | debug('saveOptions()'); 206 | 207 | for (var option in defaults) { 208 | if (!!initOptions[option] || initOptions[option] === false) { 209 | options[option] = initOptions[option]; 210 | } else { 211 | options[option] = defaults[option]; 212 | } 213 | } 214 | }, 215 | 216 | 217 | 218 | /* 219 | * Create canvas element 220 | */ 221 | createCanvas = function() { 222 | 223 | debug("createCanvas()"); 224 | 225 | // condition : if we are creating a full-screen canvas 226 | if (!options.inline) { 227 | 228 | // create canvas 229 | canvas = document.createElement('canvas'); 230 | canvas.id = "canvas"; 231 | canvas.style.position = "absolute"; 232 | canvas.style.zIndex = 1; 233 | canvas.style.left = 0; 234 | canvas.style.top = 0; 235 | 236 | // add the canvas into the page 237 | body = document.getElementsByTagName('body')[0]; 238 | body.appendChild(canvas); 239 | 240 | // if we are using an existing canvas element inline in the page 241 | } else { 242 | canvas = document.getElementById(options.canvasId); 243 | } 244 | 245 | // get the draw context 246 | drawContext = canvas.getContext("2d"); 247 | }, 248 | 249 | 250 | 251 | /* 252 | * Start letters 253 | */ 254 | startLetters = function() { 255 | 256 | debug('startLetters()'); 257 | 258 | // catch multiple calls 259 | if (!redrawing) { 260 | 261 | redrawing = true; 262 | 263 | clearInterval(drawInterval); 264 | 265 | // init values 266 | lineCount = 1; 267 | currentBlock = 0; 268 | blocks = []; 269 | blockCount = 0; 270 | reversing = false; 271 | currentX = options.clearance; 272 | currentY = options.clearance; 273 | 274 | // set up functions 275 | if (!options.inline) { 276 | setCanvasWidth(); 277 | } 278 | fixTextLength(); 279 | calculateBlockPositions(); 280 | if (!options.inline) { 281 | setCanvasHeight(); 282 | } 283 | 284 | // if we're not animating, show everything at once 285 | if (!options.animate) { 286 | currentBlock = blocks.length; 287 | } 288 | 289 | // draw background 290 | drawContext.fillStyle = "#"+options.canvasColour; 291 | drawContext.fillRect(0, 0, canvas.width, canvas.height); 292 | 293 | // start loop 294 | drawInterval = setInterval(draw, options.speed); 295 | 296 | // redrawing complete! 297 | redrawing = false; 298 | } 299 | }, 300 | 301 | 302 | /* 303 | * 304 | */ 305 | setCanvasWidth = function() { 306 | 307 | debug("setCanvasWidth()"); 308 | 309 | canvas.width = document.body.offsetWidth; 310 | }, 311 | 312 | 313 | /* 314 | * 315 | */ 316 | setCanvasHeight = function() { 317 | var canvasHeight = (lineCount*(characterBlockHeight*options.blockSize))+((lineCount+2)*options.clearance); 318 | if (canvasHeight < document.documentElement.clientHeight) { canvasHeight = document.documentElement.clientHeight; } 319 | canvas.height = canvasHeight; 320 | 321 | debug("setCanvasHeight() - " + canvasHeight + " ("+lineCount+" lines)"); 322 | }, 323 | 324 | 325 | /* 326 | * 327 | */ 328 | fixTextLength = function() { 329 | 330 | debug('fixTextLength()'); 331 | 332 | textString = options.textString.toLowerCase(); 333 | 334 | // calculate line length 335 | var lineLength = Math.floor( ( canvas.width - options.clearance ) / ( ( characterBlockWidth * options.blockSize ) + options.clearance ) ); 336 | debug('fixTextLength() - line length: ' + lineLength); 337 | 338 | // test each word invidivually 339 | textStringArray = textString.split(" "); 340 | for (var counter = textStringArray.length - 1; counter >= 0; counter--){ 341 | 342 | // if any words are longer than the line-length, hyphenate 343 | if (textStringArray[counter].length > lineLength) { 344 | 345 | var originalWord = word = textStringArray[counter]; 346 | var wordArray = []; 347 | 348 | debug('fixTextLength() - word is too long: ' + word); 349 | 350 | // split the word every time it hits the line length 351 | while (word.length > lineLength) { 352 | wordArray.push(word.substr(0, lineLength-1)); 353 | word = word.substr(lineLength-1); 354 | } 355 | wordArray.push(word); 356 | 357 | textString = textString.replace(originalWord, wordArray.join("- ")); 358 | } 359 | }; 360 | 361 | }, 362 | 363 | 364 | 365 | /* 366 | * 367 | */ 368 | calculateBlockPositions = function() { 369 | 370 | debug('calculateBlockPositions()'); 371 | 372 | // draw the text string 373 | for (var character = 0, textStringLength = textString.length; character < textString.length; character++) { 374 | 375 | // if we can draw this letter, begin 376 | if (!!characters[textString[character]]) { 377 | 378 | // if this isn't the first character, work out how far along the line to put it 379 | if (character > 0) { 380 | currentX += (options.blockSize * characterBlockWidth) + options.clearance; 381 | } 382 | 383 | // find the position of the next space (to calculate the word length) 384 | var nextSpacePosition = textString.indexOf(" ", character); 385 | if (nextSpacePosition == -1) { nextSpacePosition = textStringLength; } 386 | 387 | // start working out where to place the new letter/word 388 | var newLineRequired = false; 389 | 390 | 391 | // condition : if we're not breaking words then check the whole word will fit on the next line 392 | if (!options.breakWord) { 393 | 394 | // condition : is this word going to fit on the current line? 395 | if (currentX + (options.blockSize * (characterBlockWidth*(nextSpacePosition-character))) + (options.clearance*(nextSpacePosition-character)) > canvas.width - options.clearance) { 396 | newLineRequired = true; 397 | } 398 | 399 | // breaking words is fine 400 | } else { 401 | // condition : is this letter going to fit on the current line? 402 | if (currentX + (options.blockSize * characterBlockWidth) > canvas.width - options.clearance) { 403 | newLineRequired = true; 404 | } 405 | } 406 | 407 | 408 | // condition : start a new line? 409 | if (newLineRequired && textString[character] != " ") { 410 | currentX = options.clearance; 411 | currentY = (lineCount*(characterBlockHeight*options.blockSize)) + (options.clearance*++lineCount); 412 | } 413 | 414 | 415 | // get the blocks for this character 416 | var blockArray = characters[textString[character]]; 417 | 418 | // for each block within a character 419 | for (var block = 0, blockArrayLength = blockArray.length; block < blockArrayLength; block++) { 420 | 421 | // calculate X & Y positions for each block 422 | var x = currentX; 423 | var y = currentY; 424 | x += (options.blockSize * (block % characterBlockWidth)); 425 | if (block >= characterBlockWidth) { 426 | y += (options.blockSize*(Math.floor(block/characterBlockWidth))); 427 | } 428 | 429 | // if we're drawing a block, add it to the array 430 | if (blockArray[block] == 1) { 431 | blocks.push({x:x,y:y,opacity:0}); 432 | } 433 | } 434 | } else { 435 | debug("calculateBlockPositions() - letter not recognised: " + textString[character]); 436 | } 437 | } 438 | 439 | // condition : change order of appearing blocks 440 | switch (options.ordering) { 441 | case "vertical": 442 | function vertical(a, b) { return a.y - b.y; } 443 | blocks.sort(vertical); 444 | break; 445 | 446 | case "horizontal": 447 | function horizontal(a, b) { return a.x - b.x; } 448 | blocks.sort(horizontal); 449 | break; 450 | 451 | case "reverse": 452 | blocks.reverse(); 453 | break; 454 | 455 | case "random": 456 | function randOrd(){ return (Math.round(Math.random())-0.5); } 457 | blocks.sort(randOrd); 458 | break; 459 | } 460 | 461 | 462 | blockCount = blocks.length; 463 | debug('calculateBlockPositions() - block count: ' + blockCount); 464 | }, 465 | 466 | 467 | 468 | /* 469 | * 470 | */ 471 | drawCircle = function(x,y,r) { 472 | drawContext.beginPath(); 473 | drawContext.arc(x, y, r, 0, Math.PI*2, true); 474 | drawContext.closePath(); 475 | drawContext.fill(); 476 | }, 477 | 478 | 479 | /* 480 | * 481 | */ 482 | drawRectangle = function(x,y,w,h) { 483 | drawContext.beginPath(); 484 | drawContext.rect(x,y,w,h); 485 | drawContext.closePath(); 486 | drawContext.fill(); 487 | }, 488 | 489 | 490 | 491 | /* 492 | * 493 | */ 494 | draw = function() { 495 | 496 | // normal direction, add blocks 497 | var drawColour = (!reversing) ? options.blockColour : options.canvasColour; 498 | 499 | // calculate which blocks to work on 500 | var animateLimit = (!!options.animate) ? currentBlock-10 : 0; 501 | 502 | // loop through blocks and draw! 503 | for (var counter = animateLimit; counter < currentBlock; counter++) { 504 | if (!!blocks[counter]) { 505 | if (blocks[counter].opacity < 1) { blocks[counter].opacity += 0.1; } 506 | drawContext.fillStyle = "rgba("+HexToRGB(drawColour)+", "+blocks[counter].opacity+")"; 507 | drawRectangle(blocks[counter].x, blocks[counter].y, options.blockSize, options.blockSize); 508 | //drawCircle(blocks[counter].x, blocks[counter].y, options.blockSize); 509 | } 510 | }; 511 | 512 | // add one to loop 513 | currentBlock++; 514 | 515 | // calculate whether to end the drawing 516 | if (currentBlock == blockCount+10) { 517 | if (!options.loop || !options.animate) { 518 | clearInterval(drawInterval); 519 | debug('finished drawing'); 520 | } else { 521 | blocks.reverse(); 522 | for (var count = blocks.length - 1; count >= 0; count--){ blocks[count].opacity = 0;} 523 | reversing = !reversing; 524 | currentBlock = 0; 525 | } 526 | } 527 | }, 528 | 529 | 530 | 531 | /* 532 | * Turn Hex into RGB, for block colour 533 | */ 534 | HexToRGB = function(h) {return HexToR(h) +","+HexToG(h)+","+HexToB(h);}, 535 | HexToR = function(h) {return parseInt((cutHex(h)).substring(0,2),16);}, 536 | HexToG = function(h) {return parseInt((cutHex(h)).substring(2,4),16);}, 537 | HexToB = function(h) {return parseInt((cutHex(h)).substring(4,6),16);}, 538 | cutHex = function(h) {return (h.charAt(0)=="#") ? h.substring(1,7):h;}, 539 | 540 | 541 | /* 542 | * Debug 543 | * output debug messages 544 | * 545 | * @return void 546 | * @private 547 | */ 548 | debug = function(content) { 549 | if (!!options.debugMode) { 550 | console.log(content); 551 | clearTimeout(debugTimeout); 552 | debugTimeout = setTimeout(debugSpacer, 2000); 553 | } 554 | }, 555 | debugSpacer = function() { 556 | if (!!options.debugMode) { 557 | console.log("----------------------------------------------------------------------------------"); 558 | } 559 | }; 560 | 561 | 562 | 563 | /* 564 | * expose public methods 565 | */ 566 | return { 567 | init: init 568 | }; 569 | }; --------------------------------------------------------------------------------