1/* 2 * Walkway.js 3 * 4 * Copyright 2014, Connor Atherton - http://connoratherton.com/ 5 * Released under the MIT Licence 6 * http://opensource.org/licenses/MIT 7 * 8 * Github: http://github.com/ConnorAtherton/Walkway 9 */ 10 11// Export Walkway depending on environment (AMD, CommonJS or Browser global) 12;(function(root, factory) { 13 if (typeof define === 'function' && define.amd) { 14 // AMD. Register as an anonymous module. 15 define(factory); 16 } else if (typeof exports === 'object') { 17 // CommonJS 18 module.exports = factory(); 19 } else { 20 // Browser globals 21 root.Walkway = factory(); 22 } 23}(this, function factory(exports) { 24 'use strict'; 25 26 /* 27 * Shim for requestAnimationFrame on older browsers 28 */ 29 30 var lastTime = 0; 31 window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; 32 window.cancelAnimationFrame = window.cancelAnimationFrame || window.mozCancelAnimationFrame; 33 34 if (!window.requestAnimationFrame) { 35 window.requestAnimationFrame = function(callback, element) { 36 var currTime = new Date().getTime(); 37 var timeToCall = Math.max(0, 16 - (currTime - lastTime)); 38 var id = window.setTimeout(function() { 39 callback(currTime + timeToCall); 40 }, timeToCall); 41 42 lastTime = currTime + timeToCall; 43 return id; 44 }; 45 } 46 47 if (!window.cancelAnimationFrame) { 48 window.cancelAnimationFrame = function(id) { 49 clearTimeout(id); 50 }; 51 } 52 53 /* 54 * Easing Functions - inspired from http://gizma.com/easing/ 55 * only considering the t value for the range [0, 1] => [0, 1] 56 * 57 * Taken from https://gist.github.com/gre/1650294 58 */ 59 60 var EasingFunctions = { 61 // no easing, no acceleration 62 linear: function (t) { return t; }, 63 // accelerating from zero velocity 64 easeInQuad: function (t) { return t*t; }, 65 // decelerating to zero velocity 66 easeOutQuad: function (t) { return t*(2-t); }, 67 // acceleration until halfway, then deceleration 68 easeInOutQuad: function (t) { return t<0.5 ? 2*t*t : -1+(4-2*t)*t; }, 69 // accelerating from zero velocity 70 easeInCubic: function (t) { return t*t*t; }, 71 // decelerating to zero velocity 72 easeOutCubic: function (t) { return (--t)*t*t+1; }, 73 // acceleration until halfway, then deceleration 74 easeInOutCubic: function (t) { return t<0.5 ? 4*t*t*t : (t-1)*(2*t-2)*(2*t-2)+1; }, 75 // accelerating from zero velocity 76 easeInQuart: function (t) { return t*t*t*t; }, 77 // decelerating to zero velocity 78 easeOutQuart: function (t) { return 1-(--t)*t*t*t; }, 79 // acceleration until halfway, then deceleration 80 easeInOutQuart: function (t) { return t<0.5 ? 8*t*t*t*t : 1-8*(--t)*t*t*t; }, 81 // accelerating from zero velocity 82 easeInQuint: function (t) { return t*t*t*t*t; }, 83 // decelerating to zero velocity 84 easeOutQuint: function (t) { return 1+(--t)*t*t*t*t; }, 85 // acceleration until halfway, then deceleration 86 easeInOutQuint: function (t) { return t<0.5 ? 16*t*t*t*t*t : 1+16*(--t)*t*t*t*t; } 87 }; 88 89 /* 90 * Creates a selector used to select all element to animate 91 * Currently only supports *path*, *line*, and *polyline* svg elements 92 * 93 * @param {string} selector The selector of the parent element 94 * @returns {string} the complete selector 95 * @private 96 */ 97 98 function _createSelector(selector) { 99 var supported = ['path', 'line', 'polyline']; 100 var newSelector = supported.reduce(function(prev, curr){ 101 return prev + selector + ' ' + curr + ', '; 102 }, ''); 103 // chop the last , from the string 104 return newSelector.slice(0, -2); 105 } 106 107 /* 108 * Walkway constructor function 109 * opts.selector is the only mandatory param and can be passed in alone 110 * as a string 111 * 112 * @param {object} opts the configuration objects for the instance. 113 * @returns {walkway} 114 */ 115 116 function Walkway(opts) { 117 if (!(this instanceof Walkway)) { 118 return new Walkway(opts); 119 } 120 121 if (typeof opts === 'string') { 122 opts = { selector: opts }; 123 } 124 125 if (!opts.selector) { 126 return this.error('A selector needs to be specified'); 127 } 128 129 this.opts = opts; 130 this.selector = opts.selector; 131 this.duration = opts.duration || 500; 132 this.easing = (typeof opts.easing === 'function') 133 ? opts.easing
134 : EasingFunctions[opts.easing] || EasingFunctions.easeInOutCubic; 135 this.id = false; 136 this.paths = this.getPaths(); 137 138 this.setInitialStyles(); 139 } 140 141 /* 142 * Prints an error message to the console 143 * 144 * @param {string} message the message to be displayed 145 * @returns {void} 146 */ 147 148 Walkway.prototype.error = function(message) { 149 console.log('Walkway error: ' + message); 150 }; 151 152 /* 153 * Uses a pre-build selector to find and store elements to animate 154 * 155 * @returns {array} of Path instances 156 */ 157 158 Walkway.prototype.getPaths = function() { 159 var self = this; 160 var selector = _createSelector(this.selector); 161 var els = document.querySelectorAll(selector); 162 els = Array.prototype.slice.call(els); 163 164 return els.map(function(el) { 165 if(el.tagName === 'path') { 166 return new Path(el, self.duration, self.easing); 167 } else if (el.tagName === 'line') { 168 return new Line(el, self.duration, self.easing); 169 } else if(el.tagName === 'polyline') { 170 return new Polyline(el, self.duration, self.easing); 171 } 172 }); 173 }; 174 175 /* 176 * Sets initial styles on all elements to be animated 177 * 178 * @returns {void} 179 */ 180 181 Walkway.prototype.setInitialStyles = function() { 182 this.paths.forEach(function(n) { 183 n.el.style.strokeDasharray = n.length + ' ' + n.length; 184 n.el.style.strokeDashoffset = n.length; 185 }); 186 }; 187 188 /* 189 * The general update loop for the animations. 190 * Once individal paths are finished they are spliced 191 * from the array. Once the array is empty the animation is stopped. 192 * 193 * @returns {void} 194 */ 195 196 Walkway.prototype.draw = function(callback) { 197 var counter = this.paths.length; 198 var path; 199 200 if (counter === 0) { 201 if (callback && typeof(callback) === 'function') { 202 callback(); 203 } 204 return window.cancelAnimationFrame(this.id); 205 } 206 207 while (counter--) { 208 path = this.paths[counter]; 209 var done = path.update(); 210 211 if (done) { 212 this.paths.splice(counter, 1); 213 } 214 } 215 216 this.id = window.requestAnimationFrame(this.draw.bind(this, callback)); 217 }; 218 219 /* 220 * This contains the general update logic for all supported svg 221 * elements. It *must* be called using .call or .apply in order 222 * to pass the correct context for the element. 223 * 224 * @returns {boolean} true if the animation is complete, false otherwise 225 */ 226 227 function generalUpdate(element) { 228 if (!element.animationStarted) { 229 element.animationStart = Date.now(); 230 element.animationStarted = true; 231 } 232 233 var progress = element.easing((Date.now() - element.animationStart) / element.duration); 234 var value = Math.ceil(element.length * (1 - progress)); 235 element.el.style.strokeDashoffset = value < 0 ? 0 : Math.abs(value); 236 237 return progress >= 1 ? true : false; 238 } 239 240 /* 241 * Constructor for new path instance 242 * 243 * @param {node} path actual dom node of the path 244 * @param {string} duration how long the animation should take to complete 245 * @param {string} easing the type of easing used - default is easeInOutCubic. 246 * @returns {Path} 247 */ 248 249 function Path(path, duration, easing) { 250 this.el = path; 251 this.length = path.getTotalLength(); // total length of the path 252 this.duration = duration; 253 this.easing = easing; 254 this.animationStart = null; 255 this.animationStarted = false; 256 } 257 258 /* 259 * Updates path style until the animation is complete 260 * 261 * @returns {boolean} Returns true if the path animation is finished, false otherwise 262 */ 263 264 Path.prototype.update = function() { 265 return generalUpdate(this); 266 }; 267 268 /* 269 * Constructor for new Line instance 270 * 271 * @param {node} line actual dom node of the path 272 * @param {string} duration how long the animation should take to complete 273 * @param {string} easing the type of easing used - default is easeInOutCubic. 274 * @returns {line} 275 */ 276 277 function Line(line, duration, easing) { 278 this.el = line; 279 this.length = getLineLength(line); 280 this.duration = duration; 281 this.easing = easing; 282 this.animationStart = null; 283 this.animationStarted = false;
284 } 285 286 /* 287 * Updates line style until the animation is complete 288 * 289 * @returns {boolean} Returns true if the line animation is finished, false otherwise 290 */ 291 292 Line.prototype.update = function() { 293 return generalUpdate(this); 294 }; 295 296 /* 297 * Constructor for new Polyline instance 298 * 299 * @param {node} polyline actual dom node of the path 300 * @param {string} duration how long the animation should take to complete 301 * @param {string} easing the type of easing used - default is easeInOutCubic. 302 * @returns {polyline} 303 */ 304 305 function Polyline(polyline, duration, easing) { 306 this.el = polyline; 307 this.length = getPolylineLength(polyline); 308 this.duration = duration; 309 this.easing = easing; 310 this.animationStart = null; 311 this.animationStarted = false; 312 } 313 314 /* 315 * Updates polyline style until the animation is complete 316 * 317 * @returns {boolean} Returns true if the line animation is finished, false otherwise 318 */ 319 320 Polyline.prototype.update = function() { 321 return generalUpdate(this); 322 }; 323 324 /* 325 * Calculates the length of a polyline using pythagoras theorem for each line segment 326 * 327 * @param {node} polyline The polyline element to calculate length of 328 * @returns {Number} Length of the polyline 329 */ 330 331 function getPolylineLength(polyline) { 332 var dist = 0; 333 var x1, x2, y1, y2; 334 var i; 335 var points = polyline.points.numberOfItems; 336 337 for (i = 1; i < points; i++){ 338 x1 = polyline.points.getItem(i - 1).x; 339 x2 = polyline.points.getItem(i).x; 340 y1 = polyline.points.getItem(i - 1).y; 341 y2 = polyline.points.getItem(i).y; 342 343 dist += Math.sqrt(Math.pow((x1 - x2), 2) + Math.pow((y1 - y2), 2)); 344 } 345 346 return dist; 347 } 348 349 /* 350 * Calculates the length a line using pythagoras theorem 351 * 352 * @param {node} line The line element to calculate length of 353 * @returns {Number} Length of the line 354 */ 355 356 function getLineLength(line) { 357 var x1 = line.getAttribute('x1'); 358 var x2 = line.getAttribute('x2'); 359 var y1 = line.getAttribute('y1'); 360 var y2 = line.getAttribute('y2'); 361 362 return Math.sqrt(Math.pow((x1 - x2), 2) + Math.pow((y1 - y2), 2)); 363 } 364 365 return Walkway; 366}));
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.