├── .gitignore ├── LICENSE ├── README.md ├── dist ├── loading-bar.css ├── loading-bar.js ├── loading-bar.min.css ├── loading-bar.min.js └── loading-bar.zip ├── gen-dist ├── gulpfile.ls ├── img └── sample.gif ├── index.html ├── lib ├── angularjs-binding.js ├── loading-bar.d.ts ├── loading-bar.js └── presets.js ├── package-lock.json ├── package.json └── src ├── angularjs-binding.ls ├── loading-bar.ls ├── loading-bar.styl └── presets.ls /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | .*.swp 3 | node_modules 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017, loading.io 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | loading-Bar 2 | ============= 3 | 4 | loading-Bar is a highly flexible, open sourced progress bar library based on SVG. For demo and documentation, check out the official website: [https://loading.io/progress/](https://loading.io/progress/) 5 | 6 | 7 | 8 | Example 9 | ============= 10 | 11 | ![progress bar sample](https://raw.githubusercontent.com/loadingio/loading-bar/master/img/sample.gif) 12 | 13 | 14 | 15 | Usage 16 | ============= 17 | 18 | download and include the required [JS](https://raw.githubusercontent.com/loadingio/loading-bar/master/dist/loading-bar.js) and [CSS](https://raw.githubusercontent.com/loadingio/loading-bar/master/dist/loading-bar.css) files: 19 | 20 | 21 | 22 |
23 | 24 | 25 | Building 26 | ============= 27 | 28 | ### Install prerequisites 29 | 30 | ``` 31 | sudo npm install -g gulp 32 | ``` 33 | 34 | ### Build 35 | 36 | ``` 37 | git clone https://github.com/loadingio/loading-bar 38 | cd loading-bar 39 | npm install 40 | gulp 41 | ``` 42 | 43 | Built files will be written into `./build` directory 44 | 45 | 46 | LICENSE 47 | ============= 48 | 49 | MIT License 50 | -------------------------------------------------------------------------------- /dist/loading-bar.css: -------------------------------------------------------------------------------- 1 | .ldBar { 2 | position: relative; 3 | } 4 | .ldBar.label-center > .ldBar-label { 5 | position: absolute; 6 | top: 50%; 7 | left: 50%; 8 | -webkit-transform: translate(-50%, -50%); 9 | transform: translate(-50%, -50%); 10 | text-shadow: 0 0 3px #fff; 11 | } 12 | .ldBar-label:after { 13 | content: "%"; 14 | display: inline; 15 | } 16 | .ldBar.no-percent .ldBar-label:after { 17 | content: ""; 18 | } 19 | -------------------------------------------------------------------------------- /dist/loading-bar.js: -------------------------------------------------------------------------------- 1 | (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o\n "; 16 | }, 17 | gradient: function(dir, dur){ 18 | var colors, ret, len, gx, gy, x, y, i$, i, idx; 19 | dir == null && (dir = 45); 20 | dur == null && (dur = 1); 21 | colors = slice$.call(arguments, 2); 22 | ret = [this.head("0 0 100 100")]; 23 | len = colors.length * 4 + 1; 24 | dir = dir * Math.PI / 180; 25 | gx = Math.pow(Math.cos(dir), 2); 26 | gy = Math.sqrt(gx - Math.pow(gx, 2)); 27 | if (dir > Math.PI * 0.25) { 28 | gy = Math.pow(Math.sin(dir), 2); 29 | gx = Math.sqrt(gy - Math.pow(gy, 2)); 30 | } 31 | x = gx * 100; 32 | y = gy * 100; 33 | ret.push(""); 34 | for (i$ = 0; i$ < len; ++i$) { 35 | i = i$; 36 | idx = i * 100 / (len - 1); 37 | ret.push(""); 38 | } 39 | ret.push("\n\n"); 40 | return wrap(ret.join("")); 41 | }, 42 | stripe: function(c1, c2, dur){ 43 | var ret, i; 44 | c1 == null && (c1 = '#b4b4b4'); 45 | c2 == null && (c2 = '#e6e6e6'); 46 | dur == null && (dur = 1); 47 | ret = [this.head("0 0 100 100")]; 48 | ret = ret.concat([ 49 | "", "", (function(){ 50 | var i$, results$ = []; 51 | for (i$ = 0; i$ < 13; ++i$) { 52 | i = i$; 53 | results$.push(("")); 54 | } 55 | return results$; 56 | }()).join(""), "" 57 | ].join("")); 58 | return wrap(ret); 59 | }, 60 | bubble: function(c1, c2, count, dur, size, sw){ 61 | var ret, i$, i, idx, x, r, d; 62 | c1 == null && (c1 = '#39d'); 63 | c2 == null && (c2 = '#9cf'); 64 | count == null && (count = 15); 65 | dur == null && (dur = 1); 66 | size == null && (size = 6); 67 | sw == null && (sw = 1); 68 | ret = [this.head("0 0 200 200"), ""]; 69 | for (i$ = 0; i$ < count; ++i$) { 70 | i = i$; 71 | idx = -(i / count) * dur; 72 | x = Math.random() * 184 + 8; 73 | r = (Math.random() * 0.7 + 0.3) * size; 74 | d = dur * (1 + Math.random() * 0.5); 75 | ret.push(["", "", "", "", "", ""].join("")); 76 | } 77 | return wrap(ret.join("") + ""); 78 | } 79 | }; 80 | handler = { 81 | queue: {}, 82 | running: false, 83 | main: function(timestamp){ 84 | var keepon, removed, k, ref$, func, ret, this$ = this; 85 | keepon = false; 86 | removed = []; 87 | for (k in ref$ = this.queue) { 88 | func = ref$[k]; 89 | ret = func(timestamp); 90 | if (!ret) { 91 | removed.push(func); 92 | } 93 | keepon = keepon || ret; 94 | } 95 | for (k in ref$ = this.queue) { 96 | func = ref$[k]; 97 | if (removed.indexOf(func) >= 0) { 98 | delete this.queue[k]; 99 | } 100 | } 101 | if (keepon) { 102 | return requestAnimationFrame(function(it){ 103 | return this$.main(it); 104 | }); 105 | } else { 106 | return this.running = false; 107 | } 108 | }, 109 | add: function(key, f){ 110 | var this$ = this; 111 | if (!this.queue[key]) { 112 | this.queue[key] = f; 113 | } 114 | if (!this.running) { 115 | this.running = true; 116 | return requestAnimationFrame(function(it){ 117 | return this$.main(it); 118 | }); 119 | } 120 | } 121 | }; 122 | window.ldBar = ldBar = function(selector, option){ 123 | var xmlns, root, cls, idPrefix, id, domTree, newNode, x$, config, attr, that, isStroke, parseRes, dom, svg, text, group, length, path0, path1, patimg, img, ret, size, this$ = this; 124 | option == null && (option = {}); 125 | xmlns = { 126 | xlink: "http://www.w3.org/1999/xlink" 127 | }; 128 | root = toString$.call(selector).slice(8, -1) === 'String' ? document.querySelector(selector) : selector; 129 | if (!root.ldBar) { 130 | root.ldBar = this; 131 | } else { 132 | return root.ldBar; 133 | } 134 | cls = root.getAttribute('class') || ''; 135 | if (!~cls.indexOf('ldBar')) { 136 | root.setAttribute('class', cls + " ldBar"); 137 | } 138 | idPrefix = "ldBar-" + Math.random().toString(16).substring(2); 139 | id = { 140 | key: idPrefix, 141 | clip: idPrefix + "-clip", 142 | filter: idPrefix + "-filter", 143 | pattern: idPrefix + "-pattern", 144 | mask: idPrefix + "-mask", 145 | maskPath: idPrefix + "-mask-path" 146 | }; 147 | domTree = function(n, o){ 148 | var k, v; 149 | n = newNode(n); 150 | for (k in o) { 151 | v = o[k]; 152 | if (k !== 'attr') { 153 | n.appendChild(domTree(k, v || {})); 154 | } 155 | } 156 | n.attrs(o.attr || {}); 157 | return n; 158 | }; 159 | newNode = function(n){ 160 | return document.createElementNS("http://www.w3.org/2000/svg", n); 161 | }; 162 | x$ = document.body.__proto__.__proto__.__proto__; 163 | x$.text = function(t){ 164 | return this.appendChild(document.createTextNode(t)); 165 | }; 166 | x$.attrs = function(o){ 167 | var k, v, ret, results$ = []; 168 | for (k in o) { 169 | v = o[k]; 170 | ret = /([^:]+):([^:]+)/.exec(k); 171 | if (!ret || !xmlns[ret[1]]) { 172 | results$.push(this.setAttribute(k, v)); 173 | } else { 174 | results$.push(this.setAttributeNS(xmlns[ret[1]], k, v)); 175 | } 176 | } 177 | return results$; 178 | }; 179 | x$.styles = function(o){ 180 | var k, v, results$ = []; 181 | for (k in o) { 182 | v = o[k]; 183 | results$.push(this.style[k] = v); 184 | } 185 | return results$; 186 | }; 187 | x$.append = function(n){ 188 | var r; 189 | return this.appendChild(r = document.createElementNS("http://www.w3.og/2000/svg", n)); 190 | }; 191 | x$.attr = function(n, v){ 192 | if (v != null) { 193 | return this.setAttribute(n, v); 194 | } else { 195 | return this.getAttribute(n); 196 | } 197 | }; 198 | config = { 199 | "type": 'stroke', 200 | "img": '', 201 | "path": 'M10 10L90 10M90 8M90 12', 202 | "fill-dir": 'btt', 203 | "fill": '#25b', 204 | "fill-background": '#ddd', 205 | "fill-background-extrude": 3, 206 | "pattern-size": null, 207 | "stroke-dir": 'normal', 208 | "stroke": '#25b', 209 | "stroke-width": '3', 210 | "stroke-trail": '#ddd', 211 | "stroke-trail-width": 0.5, 212 | "duration": 1, 213 | "easing": 'linear', 214 | "value": 0, 215 | "img-size": null, 216 | "bbox": null, 217 | "set-dim": true, 218 | "aspect-ratio": "xMidYMid", 219 | "transition-in": false, 220 | "min": 0, 221 | "max": 100, 222 | "precision": 0, 223 | "padding": undefined 224 | }; 225 | config["preset"] = root.attr("data-preset") || option["preset"]; 226 | if (config.preset != null) { 227 | import$(config, presets[config.preset]); 228 | } 229 | for (attr in config) { 230 | if (that = that = root.attr("data-" + attr)) { 231 | config[attr] = that; 232 | } 233 | } 234 | import$(config, option); 235 | if (config.img) { 236 | config.path = null; 237 | } 238 | isStroke = config.type === 'stroke'; 239 | parseRes = function(v){ 240 | var parser, ret; 241 | parser = /data:ldbar\/res,([^()]+)\(([^)]+)\)/; 242 | ret = parser.exec(v); 243 | if (!ret) { 244 | return v; 245 | } 246 | return ret = make[ret[1]].apply(make, ret[2].split(',')); 247 | }; 248 | config.fill = parseRes(config.fill); 249 | config.stroke = parseRes(config.stroke); 250 | if (config["set-dim"] === 'false') { 251 | config["set-dim"] = false; 252 | } 253 | dom = { 254 | attr: { 255 | "xmlns:xlink": 'http://www.w3.org/1999/xlink', 256 | preserveAspectRatio: config["aspect-ratio"], 257 | width: "100%", 258 | height: "100%" 259 | }, 260 | defs: { 261 | filter: { 262 | attr: { 263 | id: id.filter, 264 | x: -1, 265 | y: -1, 266 | width: 3, 267 | height: 3 268 | }, 269 | feMorphology: { 270 | attr: { 271 | operator: +config["fill-background-extrude"] >= 0 ? 'dilate' : 'erode', 272 | radius: Math.abs(+config["fill-background-extrude"]) 273 | } 274 | }, 275 | feColorMatrix: { 276 | attr: { 277 | values: '0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0', 278 | result: "cm" 279 | } 280 | } 281 | }, 282 | mask: { 283 | attr: { 284 | id: id.mask 285 | }, 286 | image: { 287 | attr: { 288 | "xlink:href": config.img, 289 | filter: "url(#" + id.filter + ")", 290 | x: 0, 291 | y: 0, 292 | width: 100, 293 | height: 100, 294 | preserveAspectRatio: config["aspect-ratio"] 295 | } 296 | } 297 | }, 298 | g: { 299 | mask: { 300 | attr: { 301 | id: id.maskPath 302 | }, 303 | path: { 304 | attr: { 305 | d: config.path || "", 306 | fill: '#fff', 307 | stroke: '#fff', 308 | filter: "url(#" + id.filter + ")" 309 | } 310 | } 311 | } 312 | }, 313 | clipPath: { 314 | attr: { 315 | id: id.clip 316 | }, 317 | rect: { 318 | attr: { 319 | 'class': 'mask', 320 | fill: '#000' 321 | } 322 | } 323 | }, 324 | pattern: { 325 | attr: { 326 | id: id.pattern, 327 | patternUnits: 'userSpaceOnUse', 328 | x: 0, 329 | y: 0, 330 | width: 300, 331 | height: 300 332 | }, 333 | image: { 334 | attr: { 335 | x: 0, 336 | y: 0, 337 | width: 300, 338 | height: 300 339 | } 340 | } 341 | } 342 | } 343 | }; 344 | svg = domTree('svg', dom); 345 | text = document.createElement('div'); 346 | text.setAttribute('class', 'ldBar-label'); 347 | root.appendChild(svg); 348 | root.appendChild(text); 349 | group = [0, 0]; 350 | length = 0; 351 | this.fit = function(){ 352 | var that, box, d, rect; 353 | if (that = config["bbox"]) { 354 | box = that.split(' ').map(function(it){ 355 | return +it.trim(); 356 | }); 357 | box = { 358 | x: box[0], 359 | y: box[1], 360 | width: box[2], 361 | height: box[3] 362 | }; 363 | } else { 364 | box = group[1].getBBox(); 365 | } 366 | if (!box || box.width === 0 || box.height === 0) { 367 | box = { 368 | x: 0, 369 | y: 0, 370 | width: 100, 371 | height: 100 372 | }; 373 | } 374 | d = Math.max.apply(null, ['stroke-width', 'stroke-trail-width', 'fill-background-extrude'].map(function(it){ 375 | return config[it]; 376 | })) * 1.5; 377 | if (config["padding"] != null) { 378 | d = +config["padding"]; 379 | } 380 | svg.attrs({ 381 | viewBox: [box.x - d, box.y - d, box.width + d * 2, box.height + d * 2].join(" ") 382 | }); 383 | if (config["set-dim"]) { 384 | ['width', 'height'].map(function(it){ 385 | if (!root.style[it] || this$.fit[it]) { 386 | root.style[it] = (box[it] + d * 2) + "px"; 387 | return this$.fit[it] = true; 388 | } 389 | }); 390 | } 391 | rect = group[0].querySelector('rect'); 392 | if (rect) { 393 | return rect.attrs({ 394 | x: box.x - d, 395 | y: box.y - d, 396 | width: box.width + d * 2, 397 | height: box.height + d * 2 398 | }); 399 | } 400 | }; 401 | if (config.path) { 402 | if (isStroke) { 403 | group[0] = domTree('g', { 404 | path: { 405 | attr: { 406 | d: config.path, 407 | fill: 'none', 408 | 'class': 'baseline' 409 | } 410 | } 411 | }); 412 | } else { 413 | group[0] = domTree('g', { 414 | rect: { 415 | attr: { 416 | x: 0, 417 | y: 0, 418 | width: 100, 419 | height: 100, 420 | mask: "url(#" + id.maskPath + ")", 421 | fill: config["fill-background"], 422 | 'class': 'frame' 423 | } 424 | } 425 | }); 426 | } 427 | svg.appendChild(group[0]); 428 | group[1] = domTree('g', { 429 | path: { 430 | attr: { 431 | d: config.path, 432 | 'class': isStroke ? 'mainline' : 'solid', 433 | "clip-path": config.type === 'fill' ? "url(#" + id.clip + ")" : '' 434 | } 435 | } 436 | }); 437 | svg.appendChild(group[1]); 438 | path0 = group[0].querySelector(isStroke ? 'path' : 'rect'); 439 | path1 = group[1].querySelector('path'); 440 | if (isStroke) { 441 | path1.attrs({ 442 | fill: 'none' 443 | }); 444 | } 445 | patimg = svg.querySelector('pattern image'); 446 | img = new Image(); 447 | img.addEventListener('load', function(){ 448 | var box, that; 449 | box = (that = config["pattern-size"]) 450 | ? { 451 | width: +that, 452 | height: +that 453 | } 454 | : img.width && img.height 455 | ? { 456 | width: img.width, 457 | height: img.height 458 | } 459 | : { 460 | width: 300, 461 | height: 300 462 | }; 463 | svg.querySelector('pattern').attrs({ 464 | width: box.width, 465 | height: box.height 466 | }); 467 | return patimg.attrs({ 468 | width: box.width, 469 | height: box.height 470 | }); 471 | }); 472 | if (/.+\..+|^data:/.exec(!isStroke 473 | ? config.fill 474 | : config.stroke)) { 475 | img.src = !isStroke 476 | ? config.fill 477 | : config.stroke; 478 | patimg.attrs({ 479 | "xlink:href": img.src 480 | }); 481 | } 482 | if (isStroke) { 483 | path0.attrs({ 484 | stroke: config["stroke-trail"], 485 | "stroke-width": config["stroke-trail-width"] 486 | }); 487 | path1.attrs({ 488 | "stroke-width": config["stroke-width"], 489 | stroke: /.+\..+|^data:/.exec(config.stroke) 490 | ? "url(#" + id.pattern + ")" 491 | : config.stroke 492 | }); 493 | } 494 | if (config.fill && !isStroke) { 495 | path1.attrs({ 496 | fill: /.+\..+|^data:/.exec(config.fill) 497 | ? "url(#" + id.pattern + ")" 498 | : config.fill 499 | }); 500 | } 501 | length = path1.getTotalLength(); 502 | this.fit(); 503 | this.inited = true; 504 | } else if (config.img) { 505 | if (config["img-size"]) { 506 | ret = config["img-size"].split(','); 507 | size = { 508 | width: +ret[0], 509 | height: +ret[1] 510 | }; 511 | } else { 512 | size = { 513 | width: 100, 514 | height: 100 515 | }; 516 | } 517 | group[0] = domTree('g', { 518 | rect: { 519 | attr: { 520 | x: 0, 521 | y: 0, 522 | width: 100, 523 | height: 100, 524 | mask: "url(#" + id.mask + ")", 525 | fill: config["fill-background"] 526 | } 527 | } 528 | }); 529 | svg.querySelector('mask image').attrs({ 530 | width: size.width, 531 | height: size.height 532 | }); 533 | group[1] = domTree('g', { 534 | image: { 535 | attr: { 536 | width: size.width, 537 | height: size.height, 538 | x: 0, 539 | y: 0, 540 | preserveAspectRatio: config["aspect-ratio"], 541 | "clip-path": config.type === 'fill' ? "url(#" + id.clip + ")" : '', 542 | "xlink:href": config.img, 543 | 'class': 'solid' 544 | } 545 | } 546 | }); 547 | img = new Image(); 548 | img.addEventListener('load', function(){ 549 | var ret, size, v; 550 | if (config["img-size"]) { 551 | ret = config["img-size"].split(','); 552 | size = { 553 | width: +ret[0], 554 | height: +ret[1] 555 | }; 556 | } else if (img.width && img.height) { 557 | size = { 558 | width: img.width, 559 | height: img.height 560 | }; 561 | } else { 562 | size = { 563 | width: 100, 564 | height: 100 565 | }; 566 | } 567 | svg.querySelector('mask image').attrs({ 568 | width: size.width, 569 | height: size.height 570 | }); 571 | group[1].querySelector('image').attrs({ 572 | width: size.width, 573 | height: size.height 574 | }); 575 | this$.fit(); 576 | v = this$.value; 577 | this$.value = undefined; 578 | this$.set(v, true); 579 | return this$.inited = true; 580 | }); 581 | img.src = config.img; 582 | svg.appendChild(group[0]); 583 | svg.appendChild(group[1]); 584 | } 585 | svg.attrs({ 586 | width: '100%', 587 | height: '100%' 588 | }); 589 | this.transition = { 590 | value: { 591 | src: 0, 592 | des: 0 593 | }, 594 | time: {}, 595 | ease: function(t, b, c, d){ 596 | t = t / (d * 0.5); 597 | if (t < 1) { 598 | return c * 0.5 * t * t + b; 599 | } 600 | t = t - 1; 601 | return -c * 0.5 * (t * (t - 2) - 1) + b; 602 | }, 603 | handler: function(time, doTransition){ 604 | var ref$, min, max, prec, dv, dt, dur, v, p, node, style, box, dir; 605 | doTransition == null && (doTransition = true); 606 | if (this.time.src == null) { 607 | this.time.src = time; 608 | } 609 | ref$ = [config["min"], config["max"], 1 / config["precision"]], min = ref$[0], max = ref$[1], prec = ref$[2]; 610 | ref$ = [this.value.des - this.value.src, (time - this.time.src) * 0.001, +config["duration"] || 1], dv = ref$[0], dt = ref$[1], dur = ref$[2]; 611 | v = doTransition 612 | ? this.ease(dt, this.value.src, dv, dur) 613 | : this.value.des; 614 | if (config.precision) { 615 | v = Math.round(v * prec) / prec; 616 | } else if (doTransition) { 617 | v = Math.round(v); 618 | } 619 | v >= min || (v = min); 620 | v <= max || (v = max); 621 | text.textContent = v; 622 | p = 100.0 * (v - min) / (max - min); 623 | if (isStroke) { 624 | node = path1; 625 | style = { 626 | "stroke-dasharray": config["stroke-dir"] === 'reverse' 627 | ? "0 " + length * (100 - p) * 0.01 + " " + length * p * 0.01 + " 0" 628 | : p * 0.01 * length + " " + ((100 - p) * 0.01 * length + 1) 629 | }; 630 | } else { 631 | box = group[1].getBBox(); 632 | dir = config["fill-dir"]; 633 | style = dir === 'btt' || !dir 634 | ? { 635 | y: box.y + box.height * (100 - p) * 0.01, 636 | height: box.height * p * 0.01, 637 | x: box.x, 638 | width: box.width 639 | } 640 | : dir === 'ttb' 641 | ? { 642 | y: box.y, 643 | height: box.height * p * 0.01, 644 | x: box.x, 645 | width: box.width 646 | } 647 | : dir === 'ltr' 648 | ? { 649 | y: box.y, 650 | height: box.height, 651 | x: box.x, 652 | width: box.width * p * 0.01 653 | } 654 | : dir === 'rtl' ? { 655 | y: box.y, 656 | height: box.height, 657 | x: box.x + box.width * (100 - p) * 0.01, 658 | width: box.width * p * 0.01 659 | } : void 8; 660 | node = svg.querySelector('rect'); 661 | } 662 | node.attrs(style); 663 | if (dt >= dur) { 664 | delete this.time.src; 665 | return false; 666 | } 667 | return true; 668 | }, 669 | start: function(src, des, doTransition){ 670 | var ref$, this$ = this; 671 | ref$ = this.value; 672 | ref$.src = src; 673 | ref$.des = des; 674 | !!(root.offsetWidth || root.offsetHeight || root.getClientRects().length); 675 | if (!doTransition || !(root.offsetWidth || root.offsetHeight || root.getClientRects().length)) { 676 | this.time.src = 0; 677 | this.handler(1000, false); 678 | return; 679 | } 680 | return handler.add(id.key, function(time){ 681 | return this$.handler(time); 682 | }); 683 | } 684 | }; 685 | this.set = function(v, doTransition){ 686 | var src, des; 687 | doTransition == null && (doTransition = true); 688 | src = this.value || 0; 689 | if (v != null) { 690 | this.value = v; 691 | } else { 692 | v = this.value; 693 | } 694 | des = this.value; 695 | return this.transition.start(src, des, doTransition); 696 | }; 697 | this.set(+config.value || 0, config["transition-in"]) || false; 698 | return this; 699 | }; 700 | return window.addEventListener('load', function(){ 701 | var i$, ref$, len$, node, results$ = []; 702 | for (i$ = 0, len$ = (ref$ = document.querySelectorAll('.ldBar')).length; i$ < len$; ++i$) { 703 | node = ref$[i$]; 704 | if (!node.ldBar) { 705 | results$.push(node.ldBar = new ldBar(node)); 706 | } 707 | } 708 | return results$; 709 | }, false); 710 | })(); 711 | module.exports = ldBar; 712 | function import$(obj, src){ 713 | var own = {}.hasOwnProperty; 714 | for (var key in src) if (own.call(src, key)) obj[key] = src[key]; 715 | return obj; 716 | } 717 | 718 | },{"./presets":2}],2:[function(require,module,exports){ 719 | // Generated by LiveScript 1.3.1 720 | var presets, out$ = typeof exports != 'undefined' && exports || this; 721 | out$.presets = presets = { 722 | rainbow: { 723 | "type": 'stroke', 724 | "path": 'M10 10L90 10', 725 | "stroke": 'data:ldbar/res,gradient(0,1,#a551df,#fd51ad,#ff7f82,#ffb874,#ffeb90)', 726 | "bbox": "10 10 80 10" 727 | }, 728 | energy: { 729 | "type": 'fill', 730 | "path": 'M15 5L85 5A5 5 0 0 1 85 15L15 15A5 5 0 0 1 15 5', 731 | "stroke": '#f00', 732 | "fill": 'data:ldbar/res,gradient(45,2,#4e9,#8fb,#4e9)', 733 | "fill-dir": "ltr", 734 | "fill-background": '#444', 735 | "fill-background-extrude": 1, 736 | "bbox": "10 5 80 10" 737 | }, 738 | stripe: { 739 | "type": 'fill', 740 | "path": 'M15 5L85 5A5 5 0 0 1 85 15L15 15A5 5 0 0 1 15 5', 741 | "stroke": '#f00', 742 | "fill": 'data:ldbar/res,stripe(#25b,#58e,1)', 743 | "fill-dir": "ltr", 744 | "fill-background": '#ddd', 745 | "fill-background-extrude": 1, 746 | "bbox": "10 5 80 10" 747 | }, 748 | text: { 749 | "type": 'fill', 750 | "img": "data:image/svg+xml,LOADING", 751 | "fill-background-extrude": 1.3, 752 | "pattern-size": 100, 753 | "fill-dir": "ltr", 754 | "img-size": "70,20", 755 | "bbox": "0 0 70 20" 756 | }, 757 | line: { 758 | "type": 'stroke', 759 | "path": 'M10 10L90 10', 760 | "stroke": '#25b', 761 | "stroke-width": 3, 762 | "stroke-trail": '#ddd', 763 | "stroke-trail-width": 1, 764 | "bbox": "10 10 80 10" 765 | }, 766 | fan: { 767 | "type": 'stroke', 768 | "path": 'M10 90A40 40 0 0 1 90 90', 769 | "fill-dir": 'btt', 770 | "fill": '#25b', 771 | "fill-background": '#ddd', 772 | "fill-background-extrude": 3, 773 | "stroke-dir": 'normal', 774 | "stroke": '#25b', 775 | "stroke-width": '3', 776 | "stroke-trail": '#ddd', 777 | "stroke-trail-width": 0.5, 778 | "bbox": "10 50 80 40" 779 | }, 780 | circle: { 781 | "type": 'stroke', 782 | "path": 'M50 10A40 40 0 0 1 50 90A40 40 0 0 1 50 10', 783 | "fill-dir": 'btt', 784 | "fill": '#25b', 785 | "fill-background": '#ddd', 786 | "fill-background-extrude": 3, 787 | "stroke-dir": 'normal', 788 | "stroke": '#25b', 789 | "stroke-width": '3', 790 | "stroke-trail": '#ddd', 791 | "stroke-trail-width": 0.5, 792 | "bbox": "10 10 80 80" 793 | }, 794 | bubble: { 795 | "type": 'fill', 796 | "path": 'M50 10A40 40 0 0 1 50 90A40 40 0 0 1 50 10', 797 | "fill-dir": 'btt', 798 | "fill": 'data:ldbar/res,bubble(#39d,#cef)', 799 | "pattern-size": "150", 800 | "fill-background": '#ddd', 801 | "fill-background-extrude": 2, 802 | "stroke-dir": 'normal', 803 | "stroke": '#25b', 804 | "stroke-width": '3', 805 | "stroke-trail": '#ddd', 806 | "stroke-trail-width": 0.5, 807 | "bbox": "10 10 80 80" 808 | } 809 | }; 810 | 811 | },{}]},{},[1]); 812 | -------------------------------------------------------------------------------- /dist/loading-bar.min.css: -------------------------------------------------------------------------------- 1 | .ldBar{position:relative}.ldBar.label-center>.ldBar-label{position:absolute;top:50%;left:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);text-shadow:0 0 3px #fff}.ldBar-label:after{content:"%";display:inline}.ldBar.no-percent .ldBar-label:after{content:""} 2 | -------------------------------------------------------------------------------- /dist/loading-bar.min.js: -------------------------------------------------------------------------------- 1 | (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o\n '},gradient:function(dir,dur){var colors,ret,len,gx,gy,x,y,i$,i,idx;dir==null&&(dir=45);dur==null&&(dur=1);colors=slice$.call(arguments,2);ret=[this.head("0 0 100 100")];len=colors.length*4+1;dir=dir*Math.PI/180;gx=Math.pow(Math.cos(dir),2);gy=Math.sqrt(gx-Math.pow(gx,2));if(dir>Math.PI*.25){gy=Math.pow(Math.sin(dir),2);gx=Math.sqrt(gy-Math.pow(gy,2))}x=gx*100;y=gy*100;ret.push('');for(i$=0;i$')}ret.push('\n\n');return wrap(ret.join(""))},stripe:function(c1,c2,dur){var ret,i;c1==null&&(c1="#b4b4b4");c2==null&&(c2="#e6e6e6");dur==null&&(dur=1);ret=[this.head("0 0 100 100")];ret=ret.concat(['',"",function(){var i$,results$=[];for(i$=0;i$<13;++i$){i=i$;results$.push(''))}return results$}().join(""),''].join(""));return wrap(ret)},bubble:function(c1,c2,count,dur,size,sw){var ret,i$,i,idx,x,r,d;c1==null&&(c1="#39d");c2==null&&(c2="#9cf");count==null&&(count=15);dur==null&&(dur=1);size==null&&(size=6);sw==null&&(sw=1);ret=[this.head("0 0 200 200"),''];for(i$=0;i$','',"",'','',""].join(""))}return wrap(ret.join("")+"")}};handler={queue:{},running:false,main:function(timestamp){var keepon,removed,k,ref$,func,ret,this$=this;keepon=false;removed=[];for(k in ref$=this.queue){func=ref$[k];ret=func(timestamp);if(!ret){removed.push(func)}keepon=keepon||ret}for(k in ref$=this.queue){func=ref$[k];if(removed.indexOf(func)>=0){delete this.queue[k]}}if(keepon){return requestAnimationFrame(function(it){return this$.main(it)})}else{return this.running=false}},add:function(key,f){var this$=this;if(!this.queue[key]){this.queue[key]=f}if(!this.running){this.running=true;return requestAnimationFrame(function(it){return this$.main(it)})}}};window.ldBar=ldBar=function(selector,option){var xmlns,root,cls,idPrefix,id,domTree,newNode,x$,config,attr,that,isStroke,parseRes,dom,svg,text,group,length,path0,path1,patimg,img,ret,size,this$=this;option==null&&(option={});xmlns={xlink:"http://www.w3.org/1999/xlink"};root=toString$.call(selector).slice(8,-1)==="String"?document.querySelector(selector):selector;if(!root.ldBar){root.ldBar=this}else{return root.ldBar}cls=root.getAttribute("class")||"";if(!~cls.indexOf("ldBar")){root.setAttribute("class",cls+" ldBar")}idPrefix="ldBar-"+Math.random().toString(16).substring(2);id={key:idPrefix,clip:idPrefix+"-clip",filter:idPrefix+"-filter",pattern:idPrefix+"-pattern",mask:idPrefix+"-mask",maskPath:idPrefix+"-mask-path"};domTree=function(n,o){var k,v;n=newNode(n);for(k in o){v=o[k];if(k!=="attr"){n.appendChild(domTree(k,v||{}))}}n.attrs(o.attr||{});return n};newNode=function(n){return document.createElementNS("http://www.w3.org/2000/svg",n)};x$=document.body.__proto__.__proto__.__proto__;x$.text=function(t){return this.appendChild(document.createTextNode(t))};x$.attrs=function(o){var k,v,ret,results$=[];for(k in o){v=o[k];ret=/([^:]+):([^:]+)/.exec(k);if(!ret||!xmlns[ret[1]]){results$.push(this.setAttribute(k,v))}else{results$.push(this.setAttributeNS(xmlns[ret[1]],k,v))}}return results$};x$.styles=function(o){var k,v,results$=[];for(k in o){v=o[k];results$.push(this.style[k]=v)}return results$};x$.append=function(n){var r;return this.appendChild(r=document.createElementNS("http://www.w3.og/2000/svg",n))};x$.attr=function(n,v){if(v!=null){return this.setAttribute(n,v)}else{return this.getAttribute(n)}};config={type:"stroke",img:"",path:"M10 10L90 10M90 8M90 12","fill-dir":"btt",fill:"#25b","fill-background":"#ddd","fill-background-extrude":3,"pattern-size":null,"stroke-dir":"normal",stroke:"#25b","stroke-width":"3","stroke-trail":"#ddd","stroke-trail-width":.5,duration:1,easing:"linear",value:0,"img-size":null,bbox:null,"set-dim":true,"aspect-ratio":"xMidYMid","transition-in":false,min:0,max:100,precision:0,padding:undefined};config["preset"]=root.attr("data-preset")||option["preset"];if(config.preset!=null){import$(config,presets[config.preset])}for(attr in config){if(that=that=root.attr("data-"+attr)){config[attr]=that}}import$(config,option);if(config.img){config.path=null}isStroke=config.type==="stroke";parseRes=function(v){var parser,ret;parser=/data:ldbar\/res,([^()]+)\(([^)]+)\)/;ret=parser.exec(v);if(!ret){return v}return ret=make[ret[1]].apply(make,ret[2].split(","))};config.fill=parseRes(config.fill);config.stroke=parseRes(config.stroke);if(config["set-dim"]==="false"){config["set-dim"]=false}dom={attr:{"xmlns:xlink":"http://www.w3.org/1999/xlink",preserveAspectRatio:config["aspect-ratio"],width:"100%",height:"100%"},defs:{filter:{attr:{id:id.filter,x:-1,y:-1,width:3,height:3},feMorphology:{attr:{operator:+config["fill-background-extrude"]>=0?"dilate":"erode",radius:Math.abs(+config["fill-background-extrude"])}},feColorMatrix:{attr:{values:"0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0",result:"cm"}}},mask:{attr:{id:id.mask},image:{attr:{"xlink:href":config.img,filter:"url(#"+id.filter+")",x:0,y:0,width:100,height:100,preserveAspectRatio:config["aspect-ratio"]}}},g:{mask:{attr:{id:id.maskPath},path:{attr:{d:config.path||"",fill:"#fff",stroke:"#fff",filter:"url(#"+id.filter+")"}}}},clipPath:{attr:{id:id.clip},rect:{attr:{class:"mask",fill:"#000"}}},pattern:{attr:{id:id.pattern,patternUnits:"userSpaceOnUse",x:0,y:0,width:300,height:300},image:{attr:{x:0,y:0,width:300,height:300}}}}};svg=domTree("svg",dom);text=document.createElement("div");text.setAttribute("class","ldBar-label");root.appendChild(svg);root.appendChild(text);group=[0,0];length=0;this.fit=function(){var that,box,d,rect;if(that=config["bbox"]){box=that.split(" ").map(function(it){return+it.trim()});box={x:box[0],y:box[1],width:box[2],height:box[3]}}else{box=group[1].getBBox()}if(!box||box.width===0||box.height===0){box={x:0,y:0,width:100,height:100}}d=Math.max.apply(null,["stroke-width","stroke-trail-width","fill-background-extrude"].map(function(it){return config[it]}))*1.5;if(config["padding"]!=null){d=+config["padding"]}svg.attrs({viewBox:[box.x-d,box.y-d,box.width+d*2,box.height+d*2].join(" ")});if(config["set-dim"]){["width","height"].map(function(it){if(!root.style[it]||this$.fit[it]){root.style[it]=box[it]+d*2+"px";return this$.fit[it]=true}})}rect=group[0].querySelector("rect");if(rect){return rect.attrs({x:box.x-d,y:box.y-d,width:box.width+d*2,height:box.height+d*2})}};if(config.path){if(isStroke){group[0]=domTree("g",{path:{attr:{d:config.path,fill:"none",class:"baseline"}}})}else{group[0]=domTree("g",{rect:{attr:{x:0,y:0,width:100,height:100,mask:"url(#"+id.maskPath+")",fill:config["fill-background"],class:"frame"}}})}svg.appendChild(group[0]);group[1]=domTree("g",{path:{attr:{d:config.path,class:isStroke?"mainline":"solid","clip-path":config.type==="fill"?"url(#"+id.clip+")":""}}});svg.appendChild(group[1]);path0=group[0].querySelector(isStroke?"path":"rect");path1=group[1].querySelector("path");if(isStroke){path1.attrs({fill:"none"})}patimg=svg.querySelector("pattern image");img=new Image;img.addEventListener("load",function(){var box,that;box=(that=config["pattern-size"])?{width:+that,height:+that}:img.width&&img.height?{width:img.width,height:img.height}:{width:300,height:300};svg.querySelector("pattern").attrs({width:box.width,height:box.height});return patimg.attrs({width:box.width,height:box.height})});if(/.+\..+|^data:/.exec(!isStroke?config.fill:config.stroke)){img.src=!isStroke?config.fill:config.stroke;patimg.attrs({"xlink:href":img.src})}if(isStroke){path0.attrs({stroke:config["stroke-trail"],"stroke-width":config["stroke-trail-width"]});path1.attrs({"stroke-width":config["stroke-width"],stroke:/.+\..+|^data:/.exec(config.stroke)?"url(#"+id.pattern+")":config.stroke})}if(config.fill&&!isStroke){path1.attrs({fill:/.+\..+|^data:/.exec(config.fill)?"url(#"+id.pattern+")":config.fill})}length=path1.getTotalLength();this.fit();this.inited=true}else if(config.img){if(config["img-size"]){ret=config["img-size"].split(",");size={width:+ret[0],height:+ret[1]}}else{size={width:100,height:100}}group[0]=domTree("g",{rect:{attr:{x:0,y:0,width:100,height:100,mask:"url(#"+id.mask+")",fill:config["fill-background"]}}});svg.querySelector("mask image").attrs({width:size.width,height:size.height});group[1]=domTree("g",{image:{attr:{width:size.width,height:size.height,x:0,y:0,preserveAspectRatio:config["aspect-ratio"],"clip-path":config.type==="fill"?"url(#"+id.clip+")":"","xlink:href":config.img,class:"solid"}}});img=new Image;img.addEventListener("load",function(){var ret,size,v;if(config["img-size"]){ret=config["img-size"].split(",");size={width:+ret[0],height:+ret[1]}}else if(img.width&&img.height){size={width:img.width,height:img.height}}else{size={width:100,height:100}}svg.querySelector("mask image").attrs({width:size.width,height:size.height});group[1].querySelector("image").attrs({width:size.width,height:size.height});this$.fit();v=this$.value;this$.value=undefined;this$.set(v,true);return this$.inited=true});img.src=config.img;svg.appendChild(group[0]);svg.appendChild(group[1])}svg.attrs({width:"100%",height:"100%"});this.transition={value:{src:0,des:0},time:{},ease:function(t,b,c,d){t=t/(d*.5);if(t<1){return c*.5*t*t+b}t=t-1;return-c*.5*(t*(t-2)-1)+b},handler:function(time,doTransition){var ref$,min,max,prec,dv,dt,dur,v,p,node,style,box,dir;doTransition==null&&(doTransition=true);if(this.time.src==null){this.time.src=time}ref$=[config["min"],config["max"],1/config["precision"]],min=ref$[0],max=ref$[1],prec=ref$[2];ref$=[this.value.des-this.value.src,(time-this.time.src)*.001,+config["duration"]||1],dv=ref$[0],dt=ref$[1],dur=ref$[2];v=doTransition?this.ease(dt,this.value.src,dv,dur):this.value.des;if(config.precision){v=Math.round(v*prec)/prec}else if(doTransition){v=Math.round(v)}v>=min||(v=min);v<=max||(v=max);text.textContent=v;p=100*(v-min)/(max-min);if(isStroke){node=path1;style={"stroke-dasharray":config["stroke-dir"]==="reverse"?"0 "+length*(100-p)*.01+" "+length*p*.01+" 0":p*.01*length+" "+((100-p)*.01*length+1)}}else{box=group[1].getBBox();dir=config["fill-dir"];style=dir==="btt"||!dir?{y:box.y+box.height*(100-p)*.01,height:box.height*p*.01,x:box.x,width:box.width}:dir==="ttb"?{y:box.y,height:box.height*p*.01,x:box.x,width:box.width}:dir==="ltr"?{y:box.y,height:box.height,x:box.x,width:box.width*p*.01}:dir==="rtl"?{y:box.y,height:box.height,x:box.x+box.width*(100-p)*.01,width:box.width*p*.01}:void 8;node=svg.querySelector("rect")}node.attrs(style);if(dt>=dur){delete this.time.src;return false}return true},start:function(src,des,doTransition){var ref$,this$=this;ref$=this.value;ref$.src=src;ref$.des=des;!!(root.offsetWidth||root.offsetHeight||root.getClientRects().length);if(!doTransition||!(root.offsetWidth||root.offsetHeight||root.getClientRects().length)){this.time.src=0;this.handler(1e3,false);return}return handler.add(id.key,function(time){return this$.handler(time)})}};this.set=function(v,doTransition){var src,des;doTransition==null&&(doTransition=true);src=this.value||0;if(v!=null){this.value=v}else{v=this.value}des=this.value;return this.transition.start(src,des,doTransition)};this.set(+config.value||0,config["transition-in"])||false;return this};return window.addEventListener("load",function(){var i$,ref$,len$,node,results$=[];for(i$=0,len$=(ref$=document.querySelectorAll(".ldBar")).length;i$LOADING',"fill-background-extrude":1.3,"pattern-size":100,"fill-dir":"ltr","img-size":"70,20",bbox:"0 0 70 20"},line:{type:"stroke",path:"M10 10L90 10",stroke:"#25b","stroke-width":3,"stroke-trail":"#ddd","stroke-trail-width":1,bbox:"10 10 80 10"},fan:{type:"stroke",path:"M10 90A40 40 0 0 1 90 90","fill-dir":"btt",fill:"#25b","fill-background":"#ddd","fill-background-extrude":3,"stroke-dir":"normal",stroke:"#25b","stroke-width":"3","stroke-trail":"#ddd","stroke-trail-width":.5,bbox:"10 50 80 40"},circle:{type:"stroke",path:"M50 10A40 40 0 0 1 50 90A40 40 0 0 1 50 10","fill-dir":"btt",fill:"#25b","fill-background":"#ddd","fill-background-extrude":3,"stroke-dir":"normal",stroke:"#25b","stroke-width":"3","stroke-trail":"#ddd","stroke-trail-width":.5,bbox:"10 10 80 80"},bubble:{type:"fill",path:"M50 10A40 40 0 0 1 50 90A40 40 0 0 1 50 10","fill-dir":"btt",fill:"data:ldbar/res,bubble(#39d,#cef)","pattern-size":"150","fill-background":"#ddd","fill-background-extrude":2,"stroke-dir":"normal",stroke:"#25b","stroke-width":"3","stroke-trail":"#ddd","stroke-trail-width":.5,bbox:"10 10 80 80"}}},{}]},{},[1]); 2 | -------------------------------------------------------------------------------- /dist/loading-bar.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/loadingio/loading-bar/af5271ef7c675783fe870b5a60d6057f32f73e47/dist/loading-bar.zip -------------------------------------------------------------------------------- /gen-dist: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | mkdir -p dist 3 | echo "build src/loading-bar.ls ..." 4 | ./node_modules/.bin/lsc -cbp src/loading-bar.ls > dist/loading-bar-raw.js 5 | echo "build src/presets.ls ..." 6 | ./node_modules/.bin/lsc -cbp src/presets.ls > dist/presets.js 7 | echo "build src/loading-bar.styl -> dist/loading-bar.css ..." 8 | ./node_modules/.bin/stylus -p src/loading-bar.styl > dist/loading-bar.css 9 | echo "bundle loading-bar ..." 10 | ./node_modules/.bin/browserify dist/loading-bar-raw.js > dist/loading-bar.js 11 | rm -f dist/loading-bar-raw.js 12 | rm -f dist/presets.js 13 | 14 | echo "minifying loading-bar.js ..." 15 | ./node_modules/.bin/uglifyjs dist/loading-bar.js > dist/loading-bar.min.js 16 | echo "minifying loading-bar.css ..." 17 | ./node_modules/.bin/uglifycss dist/loading-bar.css > dist/loading-bar.min.css 18 | 19 | echo "zip loading-bar.js and loading-bar.css ..." 20 | rm -f dist/loading-bar.zip 21 | zip -r dist/loading-bar.zip dist/loading-bar.js dist/loading-bar.css dist/loading-bar.min.js dist/loading-bar.min.css 22 | 23 | echo "done." 24 | 25 | -------------------------------------------------------------------------------- /gulpfile.ls: -------------------------------------------------------------------------------- 1 | argv = require 'yargs' .argv 2 | only-compile = false 3 | 4 | 5 | require! <[ watchify gulp browserify glob path fs globby touch gulp-livescript]> 6 | require! 'prelude-ls': {union, join, keys, map, unique} 7 | require! 'vinyl-source-stream': source 8 | require! 'vinyl-buffer': buffer 9 | require! 'gulp-watch': watch 10 | require! 'gulp-pug': pug 11 | require! 'gulp-stylus': stylus 12 | require! 'node-notifier': notifier 13 | require! 'gulp-concat': cat 14 | require! 'gulp-uglify': uglify 15 | require! 'gulp-flatten': flatten 16 | require! 'gulp-tap': tap 17 | require! 'gulp-cached': cache 18 | require! 'gulp-sourcemaps': sourcemaps 19 | require! 'browserify-livescript' 20 | require! 'run-sequence' 21 | require! 'through2':through 22 | require! 'optimize-js' 23 | require! 'gulp-if-else': if-else 24 | require! 'gulp-rename': rename 25 | require! 'gulp-zip': zip 26 | require! 'gulp-remove-files': remove-files 27 | 28 | # Build Settings 29 | notification-enabled = yes 30 | 31 | # Project Folder Structure 32 | src-path = "#{__dirname}/src" 33 | build-path = "#{__dirname}/build" 34 | out-dir = argv.out-dir or build-path 35 | 36 | on-error = (source, msg) -> 37 | msg = try 38 | msg.to-string! 39 | catch 40 | "unknown message: #{e}" 41 | console-msg = "GULP ERROR: #{source} : #{msg}" 42 | console.log console-msg 43 | 44 | log-info = (source, msg) -> 45 | msg = try 46 | msg.to-string! 47 | catch 48 | "unknown message: #{e}" 49 | console-msg = "GULP INFO: #{source} : #{msg}" 50 | console.log console-msg 51 | 52 | ls-entry-file = "#{src-path}/loading-bar.ls" 53 | 54 | for-browserify = 55 | "#{src-path}/*.ls" 56 | ... 57 | 58 | 59 | # Organize Tasks 60 | gulp.task \default, -> 61 | do function run-all 62 | gulp.start do 63 | \lib 64 | \browserify 65 | \css 66 | \zip 67 | \compressjs 68 | ... 69 | 70 | watch for-browserify, -> 71 | gulp.start \browserify 72 | watch ["#{src-path}/*.styl"], -> 73 | gulp.start \css 74 | watch ["#{src-path}/*.ls"], -> 75 | gulp.start \lib 76 | watch ["#{out-dir}/*.js", "#{out-dir}/*.css"], -> 77 | gulp.start \zip 78 | watch ["#{out-dir}/loading-bar.js"], -> 79 | gulp.start \compressjs 80 | 81 | 82 | browserify-cache = {} 83 | bundler = browserify do 84 | entries: ls-entry-file 85 | debug: true 86 | paths: 87 | src-path 88 | ... 89 | extensions: <[ .ls ]> 90 | cache: browserify-cache 91 | package-cache: {} 92 | plugin: 93 | watchify unless only-compile 94 | ... 95 | 96 | bundler.transform browserify-livescript 97 | 98 | first-browserify-done = no 99 | 100 | function bundle 101 | bundler 102 | .bundle! 103 | .on \error, (err) -> 104 | msg = try 105 | err.message 106 | catch 107 | err 108 | on-error \browserify, msg 109 | @emit \end 110 | .pipe source "loading-bar.js" 111 | .pipe buffer! 112 | #.pipe sourcemaps.init {+load-maps, +large-files} 113 | .pipe if-else only-compile, uglify 114 | #.pipe rename basename: 'app' 115 | #.pipe sourcemaps.write '.' 116 | .pipe gulp.dest out-dir 117 | .pipe tap (file) -> 118 | log-info \browserify, "Browserify finished #{if out-dir isnt build-path then "out-dir: #{out-dir}"}" 119 | console.log "------------------------------------------" 120 | first-browserify-done := yes 121 | 122 | gulp.task \browserify, -> 123 | bundle! 124 | 125 | gulp.task \lib, -> 126 | gulp.src \src/*.ls 127 | .pipe gulp-livescript bare: true 128 | .pipe gulp.dest 'lib' 129 | 130 | gulp.task \css, -> 131 | gulp.src \src/loading-bar.styl 132 | .pipe stylus({compress: true}) 133 | .pipe gulp.dest out-dir 134 | .pipe tap (file) -> 135 | log-info \css, "Stylus -> CSS finished #{if out-dir isnt build-path then "out-dir: #{out-dir}"}" 136 | console.log "------------------------------------------" 137 | 138 | gulp.task \zip, -> 139 | gulp.src ["#out-dir/*.js","#out-dir/*.css", "!build/*.min.*"] 140 | .pipe zip("loading-bar.zip") 141 | .pipe gulp.dest out-dir 142 | 143 | 144 | gulp.task \compressjs, -> 145 | gulp.src ["#out-dir/*.js", "!build/*.min.*"] 146 | .pipe uglify! 147 | .pipe rename suffix: \.min 148 | .pipe gulp.dest out-dir 149 | -------------------------------------------------------------------------------- /img/sample.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/loadingio/loading-bar/af5271ef7c675783fe870b5a60d6057f32f73e47/img/sample.gif -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | loading bar 2 | -------------------------------------------------------------------------------- /lib/angularjs-binding.js: -------------------------------------------------------------------------------- 1 | var x$; 2 | x$ = angular.module('loadingio', []); 3 | x$.directive('ldbar', ['$compile', '$timeout'].concat(function($compile, $timeout){ 4 | return { 5 | restrict: 'A', 6 | scope: { 7 | model: '=ngModel', 8 | config: '=config' 9 | }, 10 | link: function(s, e, a, c){ 11 | var bar; 12 | if (e[0]) { 13 | bar = !e[0].ldBar 14 | ? new ldBar(e[0], s.config || {}) 15 | : e[0].ldBar; 16 | } 17 | return s.$watch('model', function(n, o){ 18 | return bar.set(n); 19 | }); 20 | } 21 | }; 22 | })); -------------------------------------------------------------------------------- /lib/loading-bar.d.ts: -------------------------------------------------------------------------------- 1 | export = ldBar; 2 | declare class ldBar { 3 | constructor(element: any, options: object); 4 | set(value: number): void; 5 | } 6 | -------------------------------------------------------------------------------- /lib/loading-bar.js: -------------------------------------------------------------------------------- 1 | var presets, simpleStr, wrap, slice$ = [].slice, toString$ = {}.toString; 2 | presets = require('./presets').presets; 3 | simpleStr = function(arr){ 4 | return arr.join(''); 5 | }; 6 | wrap = function(content){ 7 | return "data:image/svg+xml;base64," + btoa(content); 8 | }; 9 | (function(){ 10 | var make, handler, ldBar; 11 | make = { 12 | head: function(viewBox){ 13 | return "\n "; 14 | }, 15 | gradient: function(dir, dur){ 16 | var colors, ret, len, gx, gy, x, y, i$, i, idx; 17 | dir == null && (dir = 45); 18 | dur == null && (dur = 1); 19 | colors = slice$.call(arguments, 2); 20 | ret = [this.head("0 0 100 100")]; 21 | len = colors.length * 4 + 1; 22 | dir = dir * Math.PI / 180; 23 | gx = Math.pow(Math.cos(dir), 2); 24 | gy = Math.sqrt(gx - Math.pow(gx, 2)); 25 | if (dir > Math.PI * 0.25) { 26 | gy = Math.pow(Math.sin(dir), 2); 27 | gx = Math.sqrt(gy - Math.pow(gy, 2)); 28 | } 29 | x = gx * 100; 30 | y = gy * 100; 31 | ret.push(""); 32 | for (i$ = 0; i$ < len; ++i$) { 33 | i = i$; 34 | idx = i * 100 / (len - 1); 35 | ret.push(""); 36 | } 37 | ret.push("\n\n"); 38 | return wrap(ret.join("")); 39 | }, 40 | stripe: function(c1, c2, dur){ 41 | var ret, i; 42 | c1 == null && (c1 = '#b4b4b4'); 43 | c2 == null && (c2 = '#e6e6e6'); 44 | dur == null && (dur = 1); 45 | ret = [this.head("0 0 100 100")]; 46 | ret = ret.concat([ 47 | "", "", (function(){ 48 | var i$, results$ = []; 49 | for (i$ = 0; i$ < 13; ++i$) { 50 | i = i$; 51 | results$.push(("")); 52 | } 53 | return results$; 54 | }()).join(""), "" 55 | ].join("")); 56 | return wrap(ret); 57 | }, 58 | bubble: function(c1, c2, count, dur, size, sw){ 59 | var ret, i$, i, idx, x, r, d; 60 | c1 == null && (c1 = '#39d'); 61 | c2 == null && (c2 = '#9cf'); 62 | count == null && (count = 15); 63 | dur == null && (dur = 1); 64 | size == null && (size = 6); 65 | sw == null && (sw = 1); 66 | ret = [this.head("0 0 200 200"), ""]; 67 | for (i$ = 0; i$ < count; ++i$) { 68 | i = i$; 69 | idx = -(i / count) * dur; 70 | x = Math.random() * 184 + 8; 71 | r = (Math.random() * 0.7 + 0.3) * size; 72 | d = dur * (1 + Math.random() * 0.5); 73 | ret.push(["", "", "", "", "", ""].join("")); 74 | } 75 | return wrap(ret.join("") + ""); 76 | } 77 | }; 78 | handler = { 79 | queue: {}, 80 | running: false, 81 | main: function(timestamp){ 82 | var keepon, removed, k, ref$, func, ret, this$ = this; 83 | keepon = false; 84 | removed = []; 85 | for (k in ref$ = this.queue) { 86 | func = ref$[k]; 87 | ret = func(timestamp); 88 | if (!ret) { 89 | removed.push(func); 90 | } 91 | keepon = keepon || ret; 92 | } 93 | for (k in ref$ = this.queue) { 94 | func = ref$[k]; 95 | if (removed.indexOf(func) >= 0) { 96 | delete this.queue[k]; 97 | } 98 | } 99 | if (keepon) { 100 | return requestAnimationFrame(function(it){ 101 | return this$.main(it); 102 | }); 103 | } else { 104 | return this.running = false; 105 | } 106 | }, 107 | add: function(key, f){ 108 | var this$ = this; 109 | if (!this.queue[key]) { 110 | this.queue[key] = f; 111 | } 112 | if (!this.running) { 113 | this.running = true; 114 | return requestAnimationFrame(function(it){ 115 | return this$.main(it); 116 | }); 117 | } 118 | } 119 | }; 120 | window.ldBar = ldBar = function(selector, option){ 121 | var xmlns, root, cls, idPrefix, id, domTree, newNode, x$, config, attr, that, isStroke, parseRes, dom, svg, text, group, length, path0, path1, patimg, img, ret, size, this$ = this; 122 | option == null && (option = {}); 123 | xmlns = { 124 | xlink: "http://www.w3.org/1999/xlink" 125 | }; 126 | root = toString$.call(selector).slice(8, -1) === 'String' ? document.querySelector(selector) : selector; 127 | if (!root.ldBar) { 128 | root.ldBar = this; 129 | } else { 130 | return root.ldBar; 131 | } 132 | cls = root.getAttribute('class') || ''; 133 | if (!~cls.indexOf('ldBar')) { 134 | root.setAttribute('class', cls + " ldBar"); 135 | } 136 | idPrefix = "ldBar-" + Math.random().toString(16).substring(2); 137 | id = { 138 | key: idPrefix, 139 | clip: idPrefix + "-clip", 140 | filter: idPrefix + "-filter", 141 | pattern: idPrefix + "-pattern", 142 | mask: idPrefix + "-mask", 143 | maskPath: idPrefix + "-mask-path" 144 | }; 145 | domTree = function(n, o){ 146 | var k, v; 147 | n = newNode(n); 148 | for (k in o) { 149 | v = o[k]; 150 | if (k !== 'attr') { 151 | n.appendChild(domTree(k, v || {})); 152 | } 153 | } 154 | n.attrs(o.attr || {}); 155 | return n; 156 | }; 157 | newNode = function(n){ 158 | return document.createElementNS("http://www.w3.org/2000/svg", n); 159 | }; 160 | x$ = document.body.__proto__.__proto__.__proto__; 161 | x$.text = function(t){ 162 | return this.appendChild(document.createTextNode(t)); 163 | }; 164 | x$.attrs = function(o){ 165 | var k, v, ret, results$ = []; 166 | for (k in o) { 167 | v = o[k]; 168 | ret = /([^:]+):([^:]+)/.exec(k); 169 | if (!ret || !xmlns[ret[1]]) { 170 | results$.push(this.setAttribute(k, v)); 171 | } else { 172 | results$.push(this.setAttributeNS(xmlns[ret[1]], k, v)); 173 | } 174 | } 175 | return results$; 176 | }; 177 | x$.styles = function(o){ 178 | var k, v, results$ = []; 179 | for (k in o) { 180 | v = o[k]; 181 | results$.push(this.style[k] = v); 182 | } 183 | return results$; 184 | }; 185 | x$.append = function(n){ 186 | var r; 187 | return this.appendChild(r = document.createElementNS("http://www.w3.og/2000/svg", n)); 188 | }; 189 | x$.attr = function(n, v){ 190 | if (v != null) { 191 | return this.setAttribute(n, v); 192 | } else { 193 | return this.getAttribute(n); 194 | } 195 | }; 196 | config = { 197 | "type": 'stroke', 198 | "img": '', 199 | "path": 'M10 10L90 10M90 8M90 12', 200 | "fill-dir": 'btt', 201 | "fill": '#25b', 202 | "fill-background": '#ddd', 203 | "fill-background-extrude": 3, 204 | "pattern-size": null, 205 | "stroke-dir": 'normal', 206 | "stroke": '#25b', 207 | "stroke-width": '3', 208 | "stroke-trail": '#ddd', 209 | "stroke-trail-width": 0.5, 210 | "duration": 1, 211 | "easing": 'linear', 212 | "value": 0, 213 | "img-size": null, 214 | "bbox": null, 215 | "set-dim": true, 216 | "aspect-ratio": "xMidYMid", 217 | "transition-in": false, 218 | "min": 0, 219 | "max": 100, 220 | "precision": 0, 221 | "padding": undefined 222 | }; 223 | config["preset"] = root.attr("data-preset") || option["preset"]; 224 | if (config.preset != null) { 225 | import$(config, presets[config.preset]); 226 | } 227 | for (attr in config) { 228 | if (that = that = root.attr("data-" + attr)) { 229 | config[attr] = that; 230 | } 231 | } 232 | import$(config, option); 233 | if (config.img) { 234 | config.path = null; 235 | } 236 | isStroke = config.type === 'stroke'; 237 | parseRes = function(v){ 238 | var parser, ret; 239 | parser = /data:ldbar\/res,([^()]+)\(([^)]+)\)/; 240 | ret = parser.exec(v); 241 | if (!ret) { 242 | return v; 243 | } 244 | return ret = make[ret[1]].apply(make, ret[2].split(',')); 245 | }; 246 | config.fill = parseRes(config.fill); 247 | config.stroke = parseRes(config.stroke); 248 | if (config["set-dim"] === 'false') { 249 | config["set-dim"] = false; 250 | } 251 | dom = { 252 | attr: { 253 | "xmlns:xlink": 'http://www.w3.org/1999/xlink', 254 | preserveAspectRatio: config["aspect-ratio"], 255 | width: "100%", 256 | height: "100%" 257 | }, 258 | defs: { 259 | filter: { 260 | attr: { 261 | id: id.filter, 262 | x: -1, 263 | y: -1, 264 | width: 3, 265 | height: 3 266 | }, 267 | feMorphology: { 268 | attr: { 269 | operator: +config["fill-background-extrude"] >= 0 ? 'dilate' : 'erode', 270 | radius: Math.abs(+config["fill-background-extrude"]) 271 | } 272 | }, 273 | feColorMatrix: { 274 | attr: { 275 | values: '0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0', 276 | result: "cm" 277 | } 278 | } 279 | }, 280 | mask: { 281 | attr: { 282 | id: id.mask 283 | }, 284 | image: { 285 | attr: { 286 | "xlink:href": config.img, 287 | filter: "url(#" + id.filter + ")", 288 | x: 0, 289 | y: 0, 290 | width: 100, 291 | height: 100, 292 | preserveAspectRatio: config["aspect-ratio"] 293 | } 294 | } 295 | }, 296 | g: { 297 | mask: { 298 | attr: { 299 | id: id.maskPath 300 | }, 301 | path: { 302 | attr: { 303 | d: config.path || "", 304 | fill: '#fff', 305 | stroke: '#fff', 306 | filter: "url(#" + id.filter + ")" 307 | } 308 | } 309 | } 310 | }, 311 | clipPath: { 312 | attr: { 313 | id: id.clip 314 | }, 315 | rect: { 316 | attr: { 317 | 'class': 'mask', 318 | fill: '#000' 319 | } 320 | } 321 | }, 322 | pattern: { 323 | attr: { 324 | id: id.pattern, 325 | patternUnits: 'userSpaceOnUse', 326 | x: 0, 327 | y: 0, 328 | width: 300, 329 | height: 300 330 | }, 331 | image: { 332 | attr: { 333 | x: 0, 334 | y: 0, 335 | width: 300, 336 | height: 300 337 | } 338 | } 339 | } 340 | } 341 | }; 342 | svg = domTree('svg', dom); 343 | text = document.createElement('div'); 344 | text.setAttribute('class', 'ldBar-label'); 345 | root.appendChild(svg); 346 | root.appendChild(text); 347 | group = [0, 0]; 348 | length = 0; 349 | this.fit = function(){ 350 | var that, box, d, rect; 351 | if (that = config["bbox"]) { 352 | box = that.split(' ').map(function(it){ 353 | return +it.trim(); 354 | }); 355 | box = { 356 | x: box[0], 357 | y: box[1], 358 | width: box[2], 359 | height: box[3] 360 | }; 361 | } else { 362 | box = group[1].getBBox(); 363 | } 364 | if (!box || box.width === 0 || box.height === 0) { 365 | box = { 366 | x: 0, 367 | y: 0, 368 | width: 100, 369 | height: 100 370 | }; 371 | } 372 | d = Math.max.apply(null, ['stroke-width', 'stroke-trail-width', 'fill-background-extrude'].map(function(it){ 373 | return config[it]; 374 | })) * 1.5; 375 | if (config["padding"] != null) { 376 | d = +config["padding"]; 377 | } 378 | svg.attrs({ 379 | viewBox: [box.x - d, box.y - d, box.width + d * 2, box.height + d * 2].join(" ") 380 | }); 381 | if (config["set-dim"]) { 382 | ['width', 'height'].map(function(it){ 383 | if (!root.style[it] || this$.fit[it]) { 384 | root.style[it] = (box[it] + d * 2) + "px"; 385 | return this$.fit[it] = true; 386 | } 387 | }); 388 | } 389 | rect = group[0].querySelector('rect'); 390 | if (rect) { 391 | return rect.attrs({ 392 | x: box.x - d, 393 | y: box.y - d, 394 | width: box.width + d * 2, 395 | height: box.height + d * 2 396 | }); 397 | } 398 | }; 399 | if (config.path) { 400 | if (isStroke) { 401 | group[0] = domTree('g', { 402 | path: { 403 | attr: { 404 | d: config.path, 405 | fill: 'none', 406 | 'class': 'baseline' 407 | } 408 | } 409 | }); 410 | } else { 411 | group[0] = domTree('g', { 412 | rect: { 413 | attr: { 414 | x: 0, 415 | y: 0, 416 | width: 100, 417 | height: 100, 418 | mask: "url(#" + id.maskPath + ")", 419 | fill: config["fill-background"], 420 | 'class': 'frame' 421 | } 422 | } 423 | }); 424 | } 425 | svg.appendChild(group[0]); 426 | group[1] = domTree('g', { 427 | path: { 428 | attr: { 429 | d: config.path, 430 | 'class': isStroke ? 'mainline' : 'solid', 431 | "clip-path": config.type === 'fill' ? "url(#" + id.clip + ")" : '' 432 | } 433 | } 434 | }); 435 | svg.appendChild(group[1]); 436 | path0 = group[0].querySelector(isStroke ? 'path' : 'rect'); 437 | path1 = group[1].querySelector('path'); 438 | if (isStroke) { 439 | path1.attrs({ 440 | fill: 'none' 441 | }); 442 | } 443 | patimg = svg.querySelector('pattern image'); 444 | img = new Image(); 445 | img.addEventListener('load', function(){ 446 | var box, that; 447 | box = (that = config["pattern-size"]) 448 | ? { 449 | width: +that, 450 | height: +that 451 | } 452 | : img.width && img.height 453 | ? { 454 | width: img.width, 455 | height: img.height 456 | } 457 | : { 458 | width: 300, 459 | height: 300 460 | }; 461 | svg.querySelector('pattern').attrs({ 462 | width: box.width, 463 | height: box.height 464 | }); 465 | return patimg.attrs({ 466 | width: box.width, 467 | height: box.height 468 | }); 469 | }); 470 | if (/.+\..+|^data:/.exec(!isStroke 471 | ? config.fill 472 | : config.stroke)) { 473 | img.src = !isStroke 474 | ? config.fill 475 | : config.stroke; 476 | patimg.attrs({ 477 | "xlink:href": img.src 478 | }); 479 | } 480 | if (isStroke) { 481 | path0.attrs({ 482 | stroke: config["stroke-trail"], 483 | "stroke-width": config["stroke-trail-width"] 484 | }); 485 | path1.attrs({ 486 | "stroke-width": config["stroke-width"], 487 | stroke: /.+\..+|^data:/.exec(config.stroke) 488 | ? "url(#" + id.pattern + ")" 489 | : config.stroke 490 | }); 491 | } 492 | if (config.fill && !isStroke) { 493 | path1.attrs({ 494 | fill: /.+\..+|^data:/.exec(config.fill) 495 | ? "url(#" + id.pattern + ")" 496 | : config.fill 497 | }); 498 | } 499 | length = path1.getTotalLength(); 500 | this.fit(); 501 | this.inited = true; 502 | } else if (config.img) { 503 | if (config["img-size"]) { 504 | ret = config["img-size"].split(','); 505 | size = { 506 | width: +ret[0], 507 | height: +ret[1] 508 | }; 509 | } else { 510 | size = { 511 | width: 100, 512 | height: 100 513 | }; 514 | } 515 | group[0] = domTree('g', { 516 | rect: { 517 | attr: { 518 | x: 0, 519 | y: 0, 520 | width: 100, 521 | height: 100, 522 | mask: "url(#" + id.mask + ")", 523 | fill: config["fill-background"] 524 | } 525 | } 526 | }); 527 | svg.querySelector('mask image').attrs({ 528 | width: size.width, 529 | height: size.height 530 | }); 531 | group[1] = domTree('g', { 532 | image: { 533 | attr: { 534 | width: size.width, 535 | height: size.height, 536 | x: 0, 537 | y: 0, 538 | preserveAspectRatio: config["aspect-ratio"], 539 | "clip-path": config.type === 'fill' ? "url(#" + id.clip + ")" : '', 540 | "xlink:href": config.img, 541 | 'class': 'solid' 542 | } 543 | } 544 | }); 545 | img = new Image(); 546 | img.addEventListener('load', function(){ 547 | var ret, size; 548 | if (config["img-size"]) { 549 | ret = config["img-size"].split(','); 550 | size = { 551 | width: +ret[0], 552 | height: +ret[1] 553 | }; 554 | } else if (img.width && img.height) { 555 | size = { 556 | width: img.width, 557 | height: img.height 558 | }; 559 | } else { 560 | size = { 561 | width: 100, 562 | height: 100 563 | }; 564 | } 565 | svg.querySelector('mask image').attrs({ 566 | width: size.width, 567 | height: size.height 568 | }); 569 | group[1].querySelector('image').attrs({ 570 | width: size.width, 571 | height: size.height 572 | }); 573 | this$.fit(); 574 | this$.set(undefined, false); 575 | return this$.inited = true; 576 | }); 577 | img.src = config.img; 578 | svg.appendChild(group[0]); 579 | svg.appendChild(group[1]); 580 | } 581 | svg.attrs({ 582 | width: '100%', 583 | height: '100%' 584 | }); 585 | this.transition = { 586 | value: { 587 | src: 0, 588 | des: 0 589 | }, 590 | time: {}, 591 | ease: function(t, b, c, d){ 592 | t = t / (d * 0.5); 593 | if (t < 1) { 594 | return c * 0.5 * t * t + b; 595 | } 596 | t = t - 1; 597 | return -c * 0.5 * (t * (t - 2) - 1) + b; 598 | }, 599 | handler: function(time, doTransition){ 600 | var ref$, min, max, prec, dv, dt, dur, v, p, node, style, box, dir; 601 | doTransition == null && (doTransition = true); 602 | if (this.time.src == null) { 603 | this.time.src = time; 604 | } 605 | ref$ = [config["min"], config["max"], 1 / config["precision"]], min = ref$[0], max = ref$[1], prec = ref$[2]; 606 | ref$ = [this.value.des - this.value.src, (time - this.time.src) * 0.001, +config["duration"] || 1], dv = ref$[0], dt = ref$[1], dur = ref$[2]; 607 | v = doTransition 608 | ? this.ease(dt, this.value.src, dv, dur) 609 | : this.value.des; 610 | if (config.precision) { 611 | v = Math.round(v * prec) / prec; 612 | } else if (doTransition) { 613 | v = Math.round(v); 614 | } 615 | v >= min || (v = min); 616 | v <= max || (v = max); 617 | text.textContent = v; 618 | p = 100.0 * (v - min) / (max - min); 619 | if (isStroke) { 620 | node = path1; 621 | style = { 622 | "stroke-dasharray": config["stroke-dir"] === 'reverse' 623 | ? "0 " + length * (100 - p) * 0.01 + " " + length * p * 0.01 + " 0" 624 | : p * 0.01 * length + " " + ((100 - p) * 0.01 * length + 1) 625 | }; 626 | } else { 627 | box = group[1].getBBox(); 628 | dir = config["fill-dir"]; 629 | style = dir === 'btt' || !dir 630 | ? { 631 | y: box.y + box.height * (100 - p) * 0.01, 632 | height: box.height * p * 0.01, 633 | x: box.x, 634 | width: box.width 635 | } 636 | : dir === 'ttb' 637 | ? { 638 | y: box.y, 639 | height: box.height * p * 0.01, 640 | x: box.x, 641 | width: box.width 642 | } 643 | : dir === 'ltr' 644 | ? { 645 | y: box.y, 646 | height: box.height, 647 | x: box.x, 648 | width: box.width * p * 0.01 649 | } 650 | : dir === 'rtl' ? { 651 | y: box.y, 652 | height: box.height, 653 | x: box.x + box.width * (100 - p) * 0.01, 654 | width: box.width * p * 0.01 655 | } : void 8; 656 | node = svg.querySelector('rect'); 657 | } 658 | node.attrs(style); 659 | if (dt >= dur) { 660 | delete this.time.src; 661 | return false; 662 | } 663 | return true; 664 | }, 665 | start: function(src, des, doTransition){ 666 | var ref$, this$ = this; 667 | ref$ = this.value; 668 | ref$.src = src; 669 | ref$.des = des; 670 | !!(root.offsetWidth || root.offsetHeight || root.getClientRects().length); 671 | if (!doTransition || !(root.offsetWidth || root.offsetHeight || root.getClientRects().length)) { 672 | this.time.src = 0; 673 | this.handler(1000, false); 674 | return; 675 | } 676 | return handler.add(id.key, function(time){ 677 | return this$.handler(time); 678 | }); 679 | } 680 | }; 681 | this.set = function(v, doTransition){ 682 | var src, des; 683 | doTransition == null && (doTransition = true); 684 | src = this.value || 0; 685 | if (v != null) { 686 | this.value = v; 687 | } else { 688 | v = this.value; 689 | } 690 | des = this.value; 691 | return this.transition.start(src, des, doTransition); 692 | }; 693 | this.set(+config.value || 0, config["transition-in"]) || false; 694 | return this; 695 | }; 696 | return window.addEventListener('load', function(){ 697 | var i$, ref$, len$, node, results$ = []; 698 | for (i$ = 0, len$ = (ref$ = document.querySelectorAll('.ldBar')).length; i$ < len$; ++i$) { 699 | node = ref$[i$]; 700 | if (!node.ldBar) { 701 | results$.push(node.ldBar = new ldBar(node)); 702 | } 703 | } 704 | return results$; 705 | }, false); 706 | })(); 707 | module.exports = ldBar; 708 | function import$(obj, src){ 709 | var own = {}.hasOwnProperty; 710 | for (var key in src) if (own.call(src, key)) obj[key] = src[key]; 711 | return obj; 712 | } -------------------------------------------------------------------------------- /lib/presets.js: -------------------------------------------------------------------------------- 1 | var presets, out$ = typeof exports != 'undefined' && exports || this; 2 | out$.presets = presets = { 3 | rainbow: { 4 | "type": 'stroke', 5 | "path": 'M10 10L90 10', 6 | "stroke": 'data:ldbar/res,gradient(0,1,#a551df,#fd51ad,#ff7f82,#ffb874,#ffeb90)', 7 | "bbox": "10 10 80 10" 8 | }, 9 | energy: { 10 | "type": 'fill', 11 | "path": 'M15 5L85 5A5 5 0 0 1 85 15L15 15A5 5 0 0 1 15 5', 12 | "stroke": '#f00', 13 | "fill": 'data:ldbar/res,gradient(45,2,#4e9,#8fb,#4e9)', 14 | "fill-dir": "ltr", 15 | "fill-background": '#444', 16 | "fill-background-extrude": 1, 17 | "bbox": "10 5 80 10" 18 | }, 19 | stripe: { 20 | "type": 'fill', 21 | "path": 'M15 5L85 5A5 5 0 0 1 85 15L15 15A5 5 0 0 1 15 5', 22 | "stroke": '#f00', 23 | "fill": 'data:ldbar/res,stripe(#25b,#58e,1)', 24 | "fill-dir": "ltr", 25 | "fill-background": '#ddd', 26 | "fill-background-extrude": 1, 27 | "bbox": "10 5 80 10" 28 | }, 29 | text: { 30 | "type": 'fill', 31 | "img": "data:image/svg+xml,LOADING", 32 | "fill-background-extrude": 1.3, 33 | "pattern-size": 100, 34 | "fill-dir": "ltr", 35 | "img-size": "70,20", 36 | "bbox": "0 0 70 20" 37 | }, 38 | line: { 39 | "type": 'stroke', 40 | "path": 'M10 10L90 10', 41 | "stroke": '#25b', 42 | "stroke-width": 3, 43 | "stroke-trail": '#ddd', 44 | "stroke-trail-width": 1, 45 | "bbox": "10 10 80 10" 46 | }, 47 | fan: { 48 | "type": 'stroke', 49 | "path": 'M10 90A40 40 0 0 1 90 90', 50 | "fill-dir": 'btt', 51 | "fill": '#25b', 52 | "fill-background": '#ddd', 53 | "fill-background-extrude": 3, 54 | "stroke-dir": 'normal', 55 | "stroke": '#25b', 56 | "stroke-width": '3', 57 | "stroke-trail": '#ddd', 58 | "stroke-trail-width": 0.5, 59 | "bbox": "10 50 80 40" 60 | }, 61 | circle: { 62 | "type": 'stroke', 63 | "path": 'M50 10A40 40 0 0 1 50 90A40 40 0 0 1 50 10', 64 | "fill-dir": 'btt', 65 | "fill": '#25b', 66 | "fill-background": '#ddd', 67 | "fill-background-extrude": 3, 68 | "stroke-dir": 'normal', 69 | "stroke": '#25b', 70 | "stroke-width": '3', 71 | "stroke-trail": '#ddd', 72 | "stroke-trail-width": 0.5, 73 | "bbox": "10 10 80 80" 74 | }, 75 | bubble: { 76 | "type": 'fill', 77 | "path": 'M50 10A40 40 0 0 1 50 90A40 40 0 0 1 50 10', 78 | "fill-dir": 'btt', 79 | "fill": 'data:ldbar/res,bubble(#39d,#cef)', 80 | "pattern-size": "150", 81 | "fill-background": '#ddd', 82 | "fill-background-extrude": 2, 83 | "stroke-dir": 'normal', 84 | "stroke": '#25b', 85 | "stroke-width": '3', 86 | "stroke-trail": '#ddd', 87 | "stroke-trail-width": 0.5, 88 | "bbox": "10 10 80 80" 89 | } 90 | }; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@loadingio/loading-bar", 3 | "version": "0.1.1", 4 | "description": " ====== Progress Bar Library by loading.io ====== ", 5 | "main": "lib/loading-bar.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/loadingio/loading-bar.git" 12 | }, 13 | "keywords": [ 14 | "progress-bar" 15 | ], 16 | "author": "tkirby", 17 | "license": "MIT", 18 | "bugs": { 19 | "url": "https://github.com/loadingio/loading-bar/issues" 20 | }, 21 | "devDependencies": { 22 | "LiveScript": ">=1.2.0", 23 | "browserify": "^13.1.1", 24 | "browserify-livescript": "git+https://github.com/ceremcem/browserify-livescript.git", 25 | "globby": "^6.1.0", 26 | "gulp": "^3.9.1", 27 | "gulp-cached": "^1.1.1", 28 | "gulp-concat": "^2.6.1", 29 | "gulp-flatten": "^0.3.1", 30 | "gulp-if-else": "^1.0.3", 31 | "gulp-pug": "^3.3.0", 32 | "gulp-stylus": "^2.6.0", 33 | "gulp-rename": "^1.2.2", 34 | "gulp-sourcemaps": "^2.6.1", 35 | "gulp-tap": "^1.0.1", 36 | "gulp-uglify": "^3.0.0", 37 | "gulp-watch": "^4.3.11", 38 | "node-notifier": "^5.1.2", 39 | "optimize-js": "^1.0.3", 40 | "run-sequence": "^2.1.0", 41 | "touch": "^3.1.0", 42 | "vinyl-buffer": "^1.0.0", 43 | "vinyl-source-stream": "^1.1.0", 44 | "gulp-livescript": "^3.0.1", 45 | "gulp-zip": "^4.0.0", 46 | "uglify-js": "=3.2.0", 47 | "uglifycss": "0.0.29", 48 | "watchify": "^3.9.0" 49 | }, 50 | "homepage": "https://github.com/loadingio/loading-bar#readme", 51 | "dependencies": { 52 | "gulp-remove-files": "0.0.3" 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/angularjs-binding.ls: -------------------------------------------------------------------------------- 1 | angular.module \loadingio, [] 2 | ..directive \ldbar, <[$compile $timeout]> ++ ($compile, $timeout) -> do 3 | restrict: \A 4 | scope: do 5 | model: \=ngModel 6 | config: \=config 7 | link: (s,e,a,c) -> 8 | if e.0 => bar = if !e.0.ldBar => new ldBar(e.0, s.config or {}) else e.0.ldBar 9 | s.$watch 'model', (n,o) -> bar.set n 10 | 11 | -------------------------------------------------------------------------------- /src/loading-bar.ls: -------------------------------------------------------------------------------- 1 | require! "./presets": {presets} 2 | 3 | simple-str = (arr) -> arr.join '' 4 | wrap = (content) -> "data:image/svg+xml;base64," + btoa(content) 5 | 6 | do -> 7 | make = 8 | head: (viewBox) -> """ 9 | 10 | 11 | """ 12 | 13 | gradient: (dir = 45, dur = 1, ...colors) -> 14 | ret = [@head "0 0 100 100"] 15 | len = colors.length * 4 + 1 16 | dir = dir * Math.PI / 180 17 | gx = Math.cos(dir) ** 2 18 | gy = Math.sqrt(gx - gx ** 2) 19 | if dir > Math.PI * 0.25 => 20 | gy = Math.sin(dir) ** 2 21 | gx = Math.sqrt(gy - gy ** 2) 22 | x = gx * 100 23 | y = gy * 100 24 | ret.push """""" 25 | for i from 0 til len => 26 | idx = i * 100 / (len - 1) 27 | ret.push """""" 28 | ret.push """ 29 | 30 | 31 | 33 | """ 34 | wrap ret.join("") 35 | 36 | stripe: (c1=\#b4b4b4, c2=\#e6e6e6, dur = 1) -> 37 | ret = [@head "0 0 100 100"] 38 | ret ++= [ 39 | """""" 40 | """""" 41 | ["""""" for i from 0 til 13].join("") 44 | """""" 46 | ].join("") 47 | wrap ret 48 | 49 | bubble: (c1 = \#39d, c2 = \#9cf, count = 15, dur = 1, size = 6, sw=1) -> 50 | ret = [@head("0 0 200 200"), """"""] 51 | for i from 0 til count => 52 | idx = -(i / count) * dur 53 | x = Math.random! * 184 + 8 54 | r = ( Math.random! * 0.7 + 0.3 ) * size 55 | d = dur * (1 + Math.random! * 0.5) 56 | ret.push [ 57 | """""" 58 | """""" 60 | """""" 61 | """""" 62 | """""" 64 | """""" 65 | ].join("") 66 | wrap(ret.join("") + "") 67 | 68 | handler = 69 | queue: {} 70 | running: false 71 | main: (timestamp) -> 72 | keepon = false 73 | removed = [] 74 | for k,func of @queue => 75 | ret = func timestamp 76 | if !ret => removed.push func 77 | keepon = keepon or ret 78 | for k,func of @queue => if removed.indexOf(func) >= 0 => delete @queue[k] 79 | if keepon => requestAnimationFrame (~> @main it) 80 | else @running = false 81 | add: (key, f) -> 82 | if !@queue[key] => @queue[key] = f 83 | if !@running => 84 | @running = true 85 | requestAnimationFrame (~> @main it) 86 | 87 | 88 | window.ldBar = ldBar = (selector, option = {}) -> 89 | xmlns = xlink: "http://www.w3.org/1999/xlink" 90 | root = if typeof! selector is \String 91 | document.querySelector selector 92 | else 93 | selector 94 | 95 | if !root.ldBar => root.ldBar = @ 96 | else return root.ldBar 97 | 98 | cls = root.getAttribute(\class) or '' 99 | if !~cls.indexOf('ldBar') => root.setAttribute \class, "#cls ldBar" 100 | id-prefix = "ldBar-#{Math.random!toString 16 .substring 2}" 101 | id = 102 | key: id-prefix 103 | clip: "#{id-prefix}-clip" 104 | filter: "#{id-prefix}-filter" 105 | pattern: "#{id-prefix}-pattern" 106 | mask: "#{id-prefix}-mask" 107 | mask-path: "#{id-prefix}-mask-path" 108 | domTree = (n,o) -> 109 | n = newNode n 110 | for k,v of o => if k != \attr => n.appendChild domTree(k, v or {}) 111 | n.attrs(o.attr or {}) 112 | n 113 | newNode = (n) -> document.createElementNS "http://www.w3.org/2000/svg", n 114 | document.body.__proto__.__proto__.__proto__ 115 | ..text = (t) -> @appendChild document.createTextNode(t) 116 | ..attrs = (o) -> for k,v of o => 117 | ret = /([^:]+):([^:]+)/.exec(k) 118 | if !ret or !xmlns[ret.1] => @setAttribute k, v 119 | else @setAttributeNS xmlns[ret.1], k, v 120 | ..styles = (o) -> for k,v of o => @style[k] = v 121 | ..append = (n) -> @appendChild r = document.createElementNS "http://www.w3.og/2000/svg", n 122 | ..attr = (n,v) -> if v? => @setAttribute n, v else @getAttribute n 123 | config = 124 | "type": 'stroke' 125 | "img": '' 126 | "path": 'M10 10L90 10M90 8M90 12' 127 | "fill-dir": \btt 128 | "fill": \#25b 129 | "fill-background": \#ddd 130 | "fill-background-extrude": 3 131 | "pattern-size": null 132 | "stroke-dir": \normal 133 | "stroke": \#25b 134 | "stroke-width": \3 135 | "stroke-trail": \#ddd 136 | "stroke-trail-width": 0.5 137 | "duration": 1 138 | "easing": \linear 139 | "value": 0 140 | "img-size": null 141 | "bbox": null 142 | "set-dim": true 143 | "aspect-ratio": "xMidYMid" 144 | "transition-in": false 145 | "min": 0 146 | "max": 100 147 | "precision": 0 148 | "padding": undefined 149 | 150 | config["preset"] = root.attr("data-preset") or option["preset"] 151 | 152 | if config.preset? 153 | # use the default preset 154 | config <<< presets[config.preset] 155 | 156 | # overwrite if there are arguments passed via data-* attributes 157 | for attr of config 158 | if that = root.attr "data-#{attr}" 159 | config[attr] = that 160 | 161 | config <<< option 162 | if config.img => config.path = null 163 | 164 | is-stroke = config.type == \stroke 165 | parse-res = (v) -> 166 | parser = /data:ldbar\/res,([^()]+)\(([^)]+)\)/ 167 | ret = parser.exec(v) 168 | if !ret => return v 169 | ret = make[ret.1].apply make, ret.2.split(\,) 170 | config.fill = parse-res config.fill 171 | config.stroke = parse-res config.stroke 172 | if config["set-dim"] == \false => config["set-dim"] = false 173 | 174 | dom = 175 | attr: 176 | "xmlns:xlink": \http://www.w3.org/1999/xlink 177 | preserveAspectRatio: config["aspect-ratio"] 178 | width: "100%", height: "100%" 179 | defs: 180 | filter: 181 | attr: id: id.filter, x: -1, y: -1, width: 3, height: 3 182 | feMorphology: attr: 183 | operator: (if +config["fill-background-extrude"]>=0 => \dilate else \erode) 184 | radius: Math.abs(+config["fill-background-extrude"]) 185 | feColorMatrix: attr: {values: '0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0', result: "cm"} 186 | mask: 187 | attr: id: id.mask 188 | image: attr: 189 | "xlink:href": config.img 190 | filter: "url(\##{id.filter})" 191 | x: 0, y: 0, width: 100, height: 100, preserveAspectRatio: config["aspect-ratio"] 192 | 193 | g: 194 | mask: 195 | attr: id: id.mask-path 196 | path: attr: 197 | d: config.path or "" 198 | fill: \#fff 199 | stroke: \#fff 200 | filter: "url(\##{id.filter})" 201 | 202 | clipPath: 203 | attr: id: id.clip 204 | rect: {attr: class: \mask, fill: \#000} 205 | pattern: 206 | attr: 207 | id: id.pattern, patternUnits: \userSpaceOnUse 208 | x:0, y: 0, width: 300, height: 300 209 | image: attr: x: 0, y: 0, width: 300, height: 300 210 | 211 | svg = domTree \svg, dom 212 | text = document.createElement \div 213 | text.setAttribute \class, \ldBar-label 214 | root.appendChild svg 215 | root.appendChild text 216 | 217 | group = [0,0] 218 | length = 0 219 | 220 | @fit = ~> 221 | if config["bbox"] => 222 | box = that.split(' ').map(->+(it.trim!)) 223 | box = {x: box.0, y: box.1, width: box.2, height: box.3} 224 | else box = group.1.getBBox! 225 | if !box or box.width == 0 or box.height == 0 => box = {x: 0, y: 0, width: 100, height: 100} 226 | d = (Math.max.apply( 227 | null, <[stroke-width stroke-trail-width fill-background-extrude]>.map(->config[it])) 228 | ) * 1.5 229 | if config["padding"]? => d = +config["padding"] 230 | 231 | svg.attrs viewBox: [box.x - d, box.y - d, box.width + d * 2, box.height + d * 2].join(" ") 232 | if config["set-dim"] => <[width height]>.map ~> if !root.style[it] or @fit[it] => 233 | root.style[it] = "#{box[it] + d * 2}px" 234 | @fit[it] = true 235 | 236 | rect = group.0.querySelector \rect 237 | if rect => rect.attrs do 238 | x: box.x - d, y: box.y - d, width: box.width + d * 2, height: box.height + d * 2 239 | 240 | if config.path => 241 | if is-stroke => 242 | group.0 = domTree \g, path: attr: 243 | d: config.path 244 | fill: \none 245 | class: \baseline 246 | else 247 | group.0 = domTree \g, rect: attr: 248 | x: 0, y: 0, width: 100, height: 100 249 | mask: "url(\##{id.mask-path})", fill: config["fill-background"] 250 | class: \frame 251 | 252 | svg.appendChild group.0 253 | group.1 = domTree \g, path: attr: 254 | d: config.path, class: if is-stroke => \mainline else \solid 255 | "clip-path": if config.type == \fill => "url(\##{id.clip})" else '' 256 | svg.appendChild group.1 257 | path0 = group.0.querySelector (if is-stroke => \path else \rect) 258 | path1 = group.1.querySelector \path 259 | if is-stroke => path1.attrs fill: \none 260 | 261 | patimg = svg.querySelector 'pattern image' 262 | img = new Image! 263 | img.addEventListener \load, -> 264 | box = if config["pattern-size"] => {width: +that, height: +that} 265 | else if img.width and img.height => {width: img.width, height: img.height} 266 | else {width: 300, height: 300} 267 | svg.querySelector \pattern .attrs {width: box.width, height: box.height} 268 | patimg.attrs {width: box.width, height: box.height} 269 | if /.+\..+|^data:/.exec(if !is-stroke => config.fill else config.stroke) => 270 | img.src = if !is-stroke => config.fill else config.stroke 271 | patimg.attrs "xlink:href": img.src #if !is-stroke => config.fill else config.stroke 272 | 273 | if is-stroke => 274 | path0.attrs stroke: config["stroke-trail"], "stroke-width": config["stroke-trail-width"] 275 | path1.attrs do 276 | "stroke-width": config["stroke-width"] 277 | stroke: if /.+\..+|^data:/.exec(config.stroke) => "url(\##{id.pattern})" else config.stroke 278 | if config.fill and !is-stroke => 279 | path1.attrs do 280 | fill: if /.+\..+|^data:/.exec(config.fill) => "url(\##{id.pattern})" else config.fill 281 | 282 | length = path1.getTotalLength! 283 | @fit! 284 | @inited = true 285 | else if config.img => 286 | if config["img-size"] => 287 | ret = config["img-size"].split(\,) 288 | size = {width: +ret.0, height: +ret.1} 289 | else size = {width: 100, height: 100} 290 | 291 | group.0 = domTree \g, rect: attr: 292 | x: 0, y: 0, width: 100, height: 100, mask: "url(\##{id.mask})", fill: config["fill-background"] 293 | svg.querySelector 'mask image' .attrs do 294 | width: size.width, height: size.height 295 | group.1 = domTree \g, image: attr: 296 | width: size.width, height: size.height, x: 0, y: 0, preserveAspectRatio: config["aspect-ratio"] 297 | #width: 100, height: 100, x: 0, y: 0, preserveAspectRatio: "xMidYMid" 298 | "clip-path": if config.type == \fill => "url(\##{id.clip})" else '' 299 | "xlink:href": config.img, class: \solid 300 | img = new Image! 301 | img.addEventListener \load, ~> 302 | if config["img-size"] => 303 | ret = config["img-size"].split(\,) 304 | size = {width: +ret.0, height: +ret.1} 305 | else if img.width and img.height => size = {width: img.width, height: img.height} 306 | else size = {width: 100, height: 100} 307 | svg.querySelector 'mask image' .attrs do 308 | width: size.width, height: size.height 309 | group.1.querySelector 'image' .attrs do 310 | width: size.width, height: size.height 311 | 312 | @fit! 313 | 314 | # image is load, so we set value again. 315 | # if we need transition - we have to clean value so it will be treated as 0. 316 | v = @value 317 | @value = undefined 318 | @set v, true 319 | @inited = true 320 | img.src = config.img 321 | svg.appendChild group.0 322 | svg.appendChild group.1 323 | svg.attrs width: \100%, height: \100% #, viewBox: '0 0 100 100' 324 | 325 | @transition = 326 | value: 327 | src: 0 328 | des: 0 329 | time: {} 330 | 331 | ease: (t,b,c,d) -> 332 | t = t / (d * 0.5) 333 | if t < 1 => return c * 0.5 * t * t + b 334 | t = t - 1 335 | return -c * 0.5 * (t*(t - 2) - 1) + b 336 | 337 | handler: (time, doTransition = true) -> 338 | if !@time.src? => @time.src = time 339 | [min,max,prec] = [config["min"], config["max"],1/config["precision"]] 340 | [dv, dt, dur] = [@value.des - @value.src, (time - @time.src) * 0.001, +config["duration"] or 1] 341 | v = if doTransition => @ease(dt, @value.src, dv, dur) else @value.des 342 | if config.precision => v = Math.round(v * prec) / prec 343 | else if doTransition => v = Math.round(v) 344 | v >?= min 345 | v 349 | node = path1 350 | style = 351 | "stroke-dasharray": ( 352 | if config["stroke-dir"] == \reverse => 353 | "0 #{length * (100 - p) * 0.01} #{length * p * 0.01} 0" 354 | else => "#{p * 0.01 * length} #{(100 - p) * 0.01 * length + 1}" 355 | ) 356 | else 357 | box = group.1.getBBox! 358 | dir = config["fill-dir"] 359 | style = if dir == \btt or !dir => do 360 | y: box.y + box.height * (100 - p) * 0.01 361 | height: box.height * p * 0.01 362 | x: box.x, width: box.width 363 | else if dir == \ttb => do 364 | y: box.y, height: box.height * p * 0.01 365 | x: box.x, width: box.width 366 | else if dir == \ltr => do 367 | y: box.y, height: box.height 368 | x: box.x, width: box.width * p * 0.01 369 | else if dir == \rtl => do 370 | y: box.y, height: box.height 371 | x: box.x + box.width * (100 - p) * 0.01 372 | width: box.width * p * 0.01 373 | node = svg.querySelector \rect 374 | node.attrs style 375 | if dt >= dur => delete @time.src; return false 376 | return true 377 | start: (src, des, doTransition) -> 378 | @value <<< {src, des} 379 | !!( root.offsetWidth || root.offsetHeight || root.getClientRects!length ) 380 | if !doTransition or !( root.offsetWidth || root.offsetHeight || root.getClientRects!length ) => 381 | @time.src = 0 382 | @handler 1000, false 383 | return 384 | handler.add id.key, (time) ~> return @handler time 385 | 386 | @set = (v,doTransition = true) -> 387 | src = @value or 0 388 | if v? => @value = v else v = @value 389 | des = @value 390 | @transition.start src, des, doTransition 391 | 392 | @set (+config.value or 0), config["transition-in"] or false 393 | @ 394 | 395 | window.addEventListener \load, (-> 396 | for node in document.querySelectorAll(\.ldBar) => 397 | if !node.ldBar => node.ldBar = new ldBar node 398 | ), false 399 | 400 | module.exports = ldBar 401 | -------------------------------------------------------------------------------- /src/loading-bar.styl: -------------------------------------------------------------------------------- 1 | 2 | transform() 3 | -webkit-transform arguments 4 | transform arguments 5 | 6 | .ldBar 7 | position: relative 8 | &.label-center > .ldBar-label 9 | position: absolute 10 | top: 50% 11 | left: 50% 12 | transform(translate(-50%,-50%)) 13 | text-shadow: 0 0 3px rgba(255,255,255,1) 14 | .ldBar-label:after 15 | content: "%" 16 | display: inline 17 | .ldBar.no-percent 18 | .ldBar-label:after 19 | content: "" 20 | -------------------------------------------------------------------------------- /src/presets.ls: -------------------------------------------------------------------------------- 1 | export presets = 2 | rainbow: 3 | "type": 'stroke' 4 | "path": 'M10 10L90 10' 5 | "stroke": 'data:ldbar/res,gradient(0,1,#a551df,#fd51ad,#ff7f82,#ffb874,#ffeb90)' 6 | "bbox": "10 10 80 10" 7 | energy: 8 | "type": 'fill' 9 | "path": 'M15 5L85 5A5 5 0 0 1 85 15L15 15A5 5 0 0 1 15 5' 10 | "stroke": \#f00 11 | "fill": 'data:ldbar/res,gradient(45,2,#4e9,#8fb,#4e9)' 12 | "fill-dir": "ltr" 13 | "fill-background": \#444 14 | "fill-background-extrude": 1 15 | "bbox": "10 5 80 10" 16 | stripe: 17 | "type": 'fill' 18 | "path": 'M15 5L85 5A5 5 0 0 1 85 15L15 15A5 5 0 0 1 15 5' 19 | "stroke": \#f00 20 | "fill": 'data:ldbar/res,stripe(#25b,#58e,1)' 21 | "fill-dir": "ltr" 22 | "fill-background": \#ddd 23 | "fill-background-extrude": 1 24 | "bbox": "10 5 80 10" 25 | text: 26 | "type": 'fill' 27 | "img": """data:image/svg+xml,LOADING""" 28 | "fill-background-extrude": 1.3 29 | "pattern-size": 100 30 | "fill-dir": "ltr" 31 | "img-size": "70,20" 32 | "bbox": "0 0 70 20" 33 | line: 34 | "type": 'stroke' 35 | "path": 'M10 10L90 10' 36 | "stroke": \#25b 37 | "stroke-width": 3 38 | "stroke-trail": \#ddd 39 | "stroke-trail-width": 1 40 | "bbox": "10 10 80 10" 41 | fan: 42 | "type": 'stroke' 43 | "path": 'M10 90A40 40 0 0 1 90 90' 44 | "fill-dir": \btt 45 | "fill": \#25b 46 | "fill-background": \#ddd 47 | "fill-background-extrude": 3 48 | "stroke-dir": \normal 49 | "stroke": \#25b 50 | "stroke-width": \3 51 | "stroke-trail": \#ddd 52 | "stroke-trail-width": 0.5 53 | "bbox": "10 50 80 40" 54 | circle: 55 | "type": 'stroke' 56 | "path": 'M50 10A40 40 0 0 1 50 90A40 40 0 0 1 50 10' 57 | "fill-dir": \btt 58 | "fill": \#25b 59 | "fill-background": \#ddd 60 | "fill-background-extrude": 3 61 | "stroke-dir": \normal 62 | "stroke": \#25b 63 | "stroke-width": \3 64 | "stroke-trail": \#ddd 65 | "stroke-trail-width": 0.5 66 | "bbox": "10 10 80 80" 67 | bubble: 68 | "type": 'fill' 69 | "path": 'M50 10A40 40 0 0 1 50 90A40 40 0 0 1 50 10' 70 | "fill-dir": \btt 71 | "fill": 'data:ldbar/res,bubble(#39d,#cef)' 72 | "pattern-size": "150" 73 | "fill-background": \#ddd 74 | "fill-background-extrude": 2 75 | "stroke-dir": \normal 76 | "stroke": \#25b 77 | "stroke-width": \3 78 | "stroke-trail": \#ddd 79 | "stroke-trail-width": 0.5 80 | "bbox": "10 10 80 80" 81 | --------------------------------------------------------------------------------