vendor: 51,060 bytes, lines 1-1522
1/* ----------------------------------------------- 2/* Author : Vincent Garreau - vincentgarreau.com 3/* MIT license: http://opensource.org/licenses/MIT 4/* Demo / Generator : vincentgarreau.com/particles.js 5/* GitHub : github.com/VincentGarreau/particles.js 6/* How to use? : Check the GitHub README 7/* v2.0.0 8/* ----------------------------------------------- */ 9 10var pJS = function(tag_id, params) { 11 12 var canvas_el = document.querySelector('#' + tag_id + ' > .particles-js-canvas-el'); 13 14 /* particles.js variables with default values */ 15 this.pJS = { 16 canvas: { 17 el: canvas_el, 18 w: canvas_el.offsetWidth, 19 h: canvas_el.offsetHeight 20 }, 21 particles: { 22 number: { 23 value: 400, 24 density: { 25 enable: true, 26 value_area: 800 27 } 28 }, 29 color: { 30 value: '#fff' 31 }, 32 shape: { 33 type: 'circle', 34 stroke: { 35 width: 0, 36 color: '#ff0000' 37 }, 38 polygon: { 39 nb_sides: 5 40 }, 41 image: { 42 src: '', 43 width: 100, 44 height: 100 45 } 46 }, 47 opacity: { 48 value: 1, 49 random: false, 50 anim: { 51 enable: false, 52 speed: 2, 53 opacity_min: 0, 54 sync: false 55 } 56 }, 57 size: { 58 value: 20, 59 random: false, 60 anim: { 61 enable: false, 62 speed: 20, 63 size_min: 0, 64 sync: false 65 } 66 }, 67 line_linked: { 68 enable: true, 69 distance: 100, 70 color: '#fff', 71 opacity: 1, 72 width: 1 73 }, 74 move: { 75 enable: true, 76 speed: 2, 77 direction: 'none', 78 random: false, 79 straight: false, 80 out_mode: 'out', 81 bounce: false, 82 attract: { 83 enable: false, 84 rotateX: 3000, 85 rotateY: 3000 86 } 87 }, 88 array: [] 89 }, 90 interactivity: { 91 detect_on: 'canvas', 92 events: { 93 onhover: { 94 enable: true, 95 mode: 'grab' 96 }, 97 onclick: { 98 enable: true, 99 mode: 'push' 100 }, 101 resize: true 102 }, 103 modes: { 104 grab: { 105 distance: 100, 106 line_linked: { 107 opacity: 1 108 } 109 }, 110 bubble: { 111 distance: 200, 112 size: 80, 113 duration: 0.4 114 }, 115 repulse: { 116 distance: 200, 117 duration: 0.4 118 }, 119 push: { 120 particles_nb: 4 121 }, 122 remove: { 123 particles_nb: 2 124 } 125 }, 126 mouse: {} 127 }, 128 retina_detect: false, 129 fn: { 130 interact: {}, 131 modes: {}, 132 vendors: {} 133 }, 134 tmp: {} 135 }; 136 137 var pJS = this.pJS; 138 139 /* params settings */ 140 if (params) { 141 Object.deepExtend(pJS, params); 142 } 143 144 pJS.tmp.obj = { 145 size_value: pJS.particles.size.value, 146 size_anim_speed: pJS.particles.size.anim.speed, 147 move_speed: pJS.particles.move.speed, 148 line_linked_distance: pJS.particles.line_linked.distance, 149 line_linked_width: pJS.particles.line_linked.width, 150 mode_grab_distance: pJS.interactivity.modes.grab.distance, 151 mode_bubble_distance: pJS.interactivity.modes.bubble.distance, 152 mode_bubble_size: pJS.interactivity.modes.bubble.size, 153 mode_repulse_distance: pJS.interactivity.modes.repulse.distance 154 }; 155 156 157 pJS.fn.retinaInit = function() { 158 159 if (pJS.retina_detect && window.devicePixelRatio > 1) { 160 pJS.canvas.pxratio = window.devicePixelRatio; 161 pJS.tmp.retina = true; 162 } else { 163 pJS.canvas.pxratio = 1; 164 pJS.tmp.retina = false; 165 } 166 167 pJS.canvas.w = pJS.canvas.el.offsetWidth * pJS.canvas.pxratio; 168 pJS.canvas.h = pJS.canvas.el.offsetHeight * pJS.canvas.pxratio; 169 170 pJS.particles.size.value = pJS.tmp.obj.size_value * pJS.canvas.pxratio; 171 pJS.particles.size.anim.speed = pJS.tmp.obj.size_anim_speed * pJS.canvas.pxratio; 172 pJS.particles.move.speed = pJS.tmp.obj.move_speed * pJS.canvas.pxratio; 173 pJS.particles.line_linked.distance = pJS.tmp.obj.line_linked_distance * pJS.canvas.pxratio; 174 pJS.interactivity.modes.grab.distance = pJS.tmp.obj.mode_grab_distance * pJS.canvas.pxratio; 175 pJS.interactivity.modes.bubble.distance = pJS.tmp.obj.mode_bubble_distance * pJS.canvas.pxratio; 176 pJS.particles.line_linked.width = pJS.tmp.obj.line_linked_width * pJS.canvas.pxratio; 177 pJS.interactivity.modes.bubble.size = pJS.tmp.obj.mode_bubble_size * pJS.canvas.pxratio; 178 pJS.interactivity.modes.repulse.distance = pJS.tmp.obj.mode_repulse_distance * pJS.canvas.pxratio; 179 180 }; 181 182 183 184 /* ---------- pJS functions - canvas ------------ */ 185 186 pJS.fn.canvasInit = function() { 187 pJS.canvas.ctx = pJS.canvas.el.getContext('2d'); 188 }; 189 190 pJS.fn.canvasSize = function() { 191 192 pJS.canvas.el.width = pJS.canvas.w; 193 pJS.canvas.el.height = pJS.canvas.h; 194 195 if (pJS && pJS.interactivity.events.resize) { 196 197 window.addEventListener('resize', function() { 198 199 pJS.canvas.w = pJS.canvas.el.offsetWidth; 200 pJS.canvas.h = pJS.canvas.el.offsetHeight; 201 202 /* resize canvas */ 203 if (pJS.tmp.retina) { 204 pJS.canvas.w *= pJS.canvas.pxratio; 205 pJS.canvas.h *= pJS.canvas.pxratio; 206 } 207 208 pJS.canvas.el.width = pJS.canvas.w; 209 pJS.canvas.el.height = pJS.canvas.h; 210 211 /* repaint canvas on anim disabled */ 212 if (!pJS.particles.move.enable) { 213 pJS.fn.particlesEmpty(); 214 pJS.fn.particlesCreate(); 215 pJS.fn.particlesDraw(); 216 pJS.fn.vendors.densityAutoParticles(); 217 } 218 219 /* density particles enabled */ 220 pJS.fn.vendors.densityAutoParticles(); 221 222 }); 223 224 } 225 226 }; 227 228 229 pJS.fn.canvasPaint = function() { 230 pJS.canvas.ctx.fillRect(0, 0, pJS.canvas.w, pJS.canvas.h); 231 }; 232 233 pJS.fn.canvasClear = function() { 234 pJS.canvas.ctx.clearRect(0, 0, pJS.canvas.w, pJS.canvas.h); 235 }; 236 237 238 /* --------- pJS functions - particles ----------- */ 239 240 pJS.fn.particle = function(color, opacity, position) { 241 242 /* size */ 243 this.radius = (pJS.particles.size.random ? Math.random() : 1) * pJS.particles.size.value; 244 if (pJS.particles.size.anim.enable) { 245 this.size_status = false; 246 this.vs = pJS.particles.size.anim.speed / 100; 247 if (!pJS.particles.size.anim.sync) { 248 this.vs = this.vs * Math.random(); 249 } 250 } 251 252 /* position */ 253 this.x = position ? position.x : Math.random() * pJS.canvas.w; 254 this.y = position ? position.y : Math.random() * pJS.canvas.h; 255 256 /* check position - into the canvas */ 257 if (this.x > pJS.canvas.w - this.radius * 2) this.x = this.x - this.radius; 258 else if (this.x < this.radius * 2) this.x = this.x + this.radius; 259 if (this.y > pJS.canvas.h - this.radius * 2) this.y = this.y - this.radius; 260 else if (this.y < this.radius * 2) this.y = this.y + this.radius; 261 262 /* check position - avoid overlap */ 263 if (pJS.particles.move.bounce) { 264 pJS.fn.vendors.checkOverlap(this, position); 265 } 266 267 /* color */ 268 this.color = {}; 269 if (typeof(color.value) == 'object') { 270 271 if (color.value instanceof Array) { 272 var color_selected = color.value[Math.floor(Math.random() * pJS.particles.color.value.length)]; 273 this.color.rgb = hexToRgb(color_selected); 274 } else { 275 if (color.value.r != undefined && color.value.g != undefined && color.value.b != undefined) { 276 this.color.rgb = { 277 r: color.value.r, 278 g: color.value.g, 279 b: color.value.b 280 } 281 } 282 if (color.value.h != undefined && color.value.s != undefined && color.value.l != undefined) { 283 this.color.hsl = { 284 h: color.value.h, 285 s: color.value.s, 286 l: color.value.l 287 } 288 } 289 } 290 291 } else if (color.value == 'random') { 292 this.color.rgb = { 293 r: (Math.floor(Math.random() * (255 - 0 + 1)) + 0), 294 g: (Math.floor(Math.random() * (255 - 0 + 1)) + 0), 295 b: (Math.floor(Math.random() * (255 - 0 + 1)) + 0) 296 } 297 } else if (typeof(color.value) == 'string') { 298 this.color = color; 299 this.color.rgb = hexToRgb(this.color.value); 300 } 301 302 /* opacity */ 303 this.opacity = (pJS.particles.opacity.random ? Math.random() : 1) * pJS.particles.opacity.value; 304 if (pJS.particles.opacity.anim.enable) { 305 this.opacity_status = false; 306 this.vo = pJS.particles.opacity.anim.speed / 100; 307 if (!pJS.particles.opacity.anim.sync) { 308 this.vo = this.vo * Math.random(); 309 } 310 } 311 312 /* animation - velocity for speed */ 313 var velbase = {} 314 switch (pJS.particles.move.direction) { 315 case 'top': 316 velbase = { x: 0, y: -1 }; 317 break; 318 case 'top-right': 319 velbase = { x: 0.5, y: -0.5 }; 320 break; 321 case 'right': 322 velbase = { x: 1, y: -0 }; 323 break; 324 case 'bottom-right': 325 velbase = { x: 0.5, y: 0.5 }; 326 break; 327 case 'bottom': 328 velbase = { x: 0, y: 1 }; 329 break; 330 case 'bottom-left': 331 velbase = { x: -0.5, y: 1 }; 332 break; 333 case 'left': 334 velbase = { x: -1, y: 0 }; 335 break; 336 case 'top-left': 337 velbase = { x: -0.5, y: -0.5 }; 338 break; 339 default: 340 velbase = { x: 0, y: 0 }; 341 break; 342 } 343 344 if (pJS.particles.move.straight) { 345 this.vx = velbase.x; 346 this.vy = velbase.y; 347 if (pJS.particles.move.random) { 348 this.vx = this.vx * (Math.random()); 349 this.vy = this.vy * (Math.random()); 350 } 351 } else { 352 this.vx = velbase.x + Math.random() - 0.5; 353 this.vy = velbase.y + Math.random() - 0.5; 354 } 355 356 // var theta = 2.0 * Math.PI * Math.random(); 357 // this.vx = Math.cos(theta); 358 // this.vy = Math.sin(theta); 359 360 this.vx_i = this.vx; 361 this.vy_i = this.vy; 362 363 364 365 /* if shape is image */ 366 367 var shape_type = pJS.particles.shape.type; 368 if (typeof(shape_type) == 'object') { 369 if (shape_type instanceof Array) { 370 var shape_selected = shape_type[Math.floor(Math.random() * shape_type.length)]; 371 this.shape = shape_selected; 372 } 373 } else { 374 this.shape = shape_type; 375 } 376 377 if (this.shape == 'image') { 378 var sh = pJS.particles.shape; 379 this.img = { 380 src: sh.image.src, 381 ratio: sh.image.width / sh.image.height 382 } 383 if (!this.img.ratio) this.img.ratio = 1; 384 if (pJS.tmp.img_type == 'svg' && pJS.tmp.source_svg != undefined) { 385 pJS.fn.vendors.createSvgImg(this); 386 if (pJS.tmp.pushing) { 387 this.img.loaded = false; 388 } 389 } 390 } 391 392 393 394 }; 395 396 397 pJS.fn.particle.prototype.draw = function() { 398 399 var p = this; 400 401 if (p.radius_bubble != undefined) { 402 var radius = p.radius_bubble; 403 } else { 404 var radius = p.radius; 405 } 406 407 if (p.opacity_bubble != undefined) { 408 var opacity = p.opacity_bubble; 409 } else { 410 var opacity = p.opacity; 411 } 412 413 if (p.color.rgb) { 414 var color_value = 'rgba(' + p.color.rgb.r + ',' + p.color.rgb.g + ',' + p.color.rgb.b + ',' + opacity + ')'; 415 } else { 416 var color_value = 'hsla(' + p.color.hsl.h + ',' + p.color.hsl.s + '%,' + p.color.hsl.l + '%,' + opacity + ')'; 417 } 418 419 pJS.canvas.ctx.fillStyle = color_value; 420 pJS.canvas.ctx.beginPath(); 421 422 switch (p.shape) { 423 424 case 'circle': 425 pJS.canvas.ctx.arc(p.x, p.y, radius, 0, Math.PI * 2, false); 426 break; 427 428 case 'edge': 429 pJS.canvas.ctx.rect(p.x - radius, p.y - radius, radius * 2, radius * 2); 430 break; 431 432 case 'triangle': 433 pJS.fn.vendors.drawShape(pJS.canvas.ctx, p.x - radius, p.y + radius / 1.66, radius * 2, 3, 2); 434 break; 435 436 case 'polygon': 437 pJS.fn.vendors.drawShape( 438 pJS.canvas.ctx, 439 p.x - radius / (pJS.particles.shape.polygon.nb_sides / 3.5), // startX 440 p.y - radius / (2.66 / 3.5), // startY 441 radius * 2.66 / (pJS.particles.shape.polygon.nb_sides / 3), // sideLength 442 pJS.particles.shape.polygon.nb_sides, // sideCountNumerator 443 1 // sideCountDenominator 444 ); 445 break; 446 447 case 'star': 448 pJS.fn.vendors.drawShape( 449 pJS.canvas.ctx, 450 p.x - radius * 2 / (pJS.particles.shape.polygon.nb_sides / 4), // startX 451 p.y - radius / (2 * 2.66 / 3.5), // startY 452 radius * 2 * 2.66 / (pJS.particles.shape.polygon.nb_sides / 3), // sideLength 453 pJS.particles.shape.polygon.nb_sides, // sideCountNumerator 454 2 // sideCountDenominator 455 ); 456 break; 457 458 case 'image': 459 460 function draw() { 461 pJS.canvas.ctx.drawImage( 462 img_obj, 463 p.x - radius, 464 p.y - radius, 465 radius * 2, 466 radius * 2 / p.img.ratio 467 ); 468 } 469 470 if (pJS.tmp.img_type == 'svg') { 471 var img_obj = p.img.obj; 472 } else { 473 var img_obj = pJS.tmp.img_obj; 474 } 475 476 if (img_obj) { 477 draw(); 478 } 479 480 break; 481 482 } 483 484 pJS.canvas.ctx.closePath(); 485 486 if (pJS.particles.shape.stroke.width > 0) { 487 pJS.canvas.ctx.strokeStyle = pJS.particles.shape.stroke.color; 488 pJS.canvas.ctx.lineWidth = pJS.particles.shape.stroke.width; 489 pJS.canvas.ctx.stroke(); 490 } 491 492 pJS.canvas.ctx.fill(); 493 494 }; 495 496 497 pJS.fn.particlesCreate = function() { 498 for (var i = 0; i < pJS.particles.number.value; i++) { 499 pJS.particles.array.push(new pJS.fn.particle(pJS.particles.color, pJS.particles.opacity.value)); 500 } 501 }; 502 503 pJS.fn.particlesUpdate = function() { 504 505 for (var i = 0; i < pJS.particles.array.length; i++) { 506 507 /* the particle */ 508 var p = pJS.particles.array[i]; 509 510 // var d = ( dx = pJS.interactivity.mouse.click_pos_x - p.x ) * dx + ( dy = pJS.interactivity.mouse.click_pos_y - p.y ) * dy; 511 // var f = -BANG_SIZE / d; 512 // if ( d < BANG_SIZE ) { 513 // var t = Math.atan2( dy, dx ); 514 // p.vx = f * Math.cos(t); 515 // p.vy = f * Math.sin(t); 516 // } 517 518 /* move the particle */ 519 if (pJS.particles.move.enable) { 520 var ms = pJS.particles.move.speed / 2; 521 p.x += p.vx * ms; 522 p.y += p.vy * ms; 523 } 524 525 /* change opacity status */ 526 if (pJS.particles.opacity.anim.enable) { 527 if (p.opacity_status == true) { 528 if (p.opacity >= pJS.particles.opacity.value) p.opacity_status = false; 529 p.opacity += p.vo; 530 } else { 531 if (p.opacity <= pJS.particles.opacity.anim.opacity_min) p.opacity_status = true; 532 p.opacity -= p.vo; 533 } 534 if (p.opacity < 0) p.opacity = 0; 535 } 536 537 /* change size */ 538 if (pJS.particles.size.anim.enable) { 539 if (p.size_status == true) { 540 if (p.radius >= pJS.particles.size.value) p.size_status = false; 541 p.radius += p.vs; 542 } else { 543 if (p.radius <= pJS.particles.size.anim.size_min) p.size_status = true; 544 p.radius -= p.vs; 545 } 546 if (p.radius < 0) p.radius = 0; 547 } 548 549 /* change particle position if it is out of canvas */ 550 if (pJS.particles.move.out_mode == 'bounce') { 551 var new_pos = { 552 x_left: p.radius, 553 x_right: pJS.canvas.w, 554 y_top: p.radius, 555 y_bottom: pJS.canvas.h 556 } 557 } else { 558 var new_pos = { 559 x_left: -p.radius, 560 x_right: pJS.canvas.w + p.radius, 561 y_top: -p.radius, 562 y_bottom: pJS.canvas.h + p.radius 563 } 564 } 565 566 if (p.x - p.radius > pJS.canvas.w) { 567 p.x = new_pos.x_left; 568 p.y = Math.random() * pJS.canvas.h; 569 } else if (p.x + p.radius < 0) { 570 p.x = new_pos.x_right; 571 p.y = Math.random() * pJS.canvas.h; 572 } 573 if (p.y - p.radius > pJS.canvas.h) { 574 p.y = new_pos.y_top; 575 p.x = Math.random() * pJS.canvas.w; 576 } else if (p.y + p.radius < 0) { 577 p.y = new_pos.y_bottom; 578 p.x = Math.random() * pJS.canvas.w; 579 } 580 581 /* out of canvas modes */ 582 switch (pJS.particles.move.out_mode) { 583 case 'bounce': 584 if (p.x + p.radius > pJS.canvas.w) p.vx = -p.vx; 585 else if (p.x - p.radius < 0) p.vx = -p.vx; 586 if (p.y + p.radius > pJS.canvas.h) p.vy = -p.vy; 587 else if (p.y - p.radius < 0) p.vy = -p.vy; 588 break; 589 } 590 591 /* events */ 592 if (isInArray('grab', pJS.interactivity.events.onhover.mode)) { 593 pJS.fn.modes.grabParticle(p); 594 } 595 596 if (isInArray('bubble', pJS.interactivity.events.onhover.mode) || isInArray('bubble', pJS.interactivity.events.onclick.mode)) { 597 pJS.fn.modes.bubbleParticle(p); 598 } 599 600 if (isInArray('repulse', pJS.interactivity.events.onhover.mode) || isInArray('repulse', pJS.interactivity.events.onclick.mode)) { 601 pJS.fn.modes.repulseParticle(p); 602 } 603 604 /* interaction auto between particles */ 605 if (pJS.particles.line_linked.enable || pJS.particles.move.attract.enable) { 606 for (var j = i + 1; j < pJS.particles.array.length; j++) { 607 var p2 = pJS.particles.array[j]; 608 609 /* link particles */ 610 if (pJS.particles.line_linked.enable) { 611 pJS.fn.interact.linkParticles(p, p2); 612 } 613 614 /* attract particles */ 615 if (pJS.particles.move.attract.enable) { 616 pJS.fn.interact.attractParticles(p, p2); 617 } 618 619 /* bounce particles */ 620 if (pJS.particles.move.bounce) { 621 pJS.fn.interact.bounceParticles(p, p2); 622 } 623 624 } 625 } 626 627 628 } 629 630 }; 631 632 pJS.fn.particlesDraw = function() { 633 634 /* clear canvas */ 635 pJS.canvas.ctx.clearRect(0, 0, pJS.canvas.w, pJS.canvas.h); 636 637 /* update each particles param */ 638 pJS.fn.particlesUpdate(); 639 640 /* draw each particle */ 641 for (var i = 0; i < pJS.particles.array.length; i++) { 642 var p = pJS.particles.array[i]; 643 p.draw(); 644 } 645 646 }; 647 648 pJS.fn.particlesEmpty = function() { 649 pJS.particles.array = []; 650 }; 651 652 pJS.fn.particlesRefresh = function() { 653 654 /* init all */ 655 cancelRequestAnimFrame(pJS.fn.checkAnimFrame); 656 cancelRequestAnimFrame(pJS.fn.drawAnimFrame); 657 pJS.tmp.source_svg = undefined; 658 pJS.tmp.img_obj = undefined; 659 pJS.tmp.count_svg = 0; 660 pJS.fn.particlesEmpty(); 661 pJS.fn.canvasClear(); 662 663 /* restart */ 664 pJS.fn.vendors.start(); 665 666 }; 667 668 669 /* ---------- pJS functions - particles interaction ------------ */ 670 671 pJS.fn.interact.linkParticles = function(p1, p2) { 672 673 var dx = p1.x - p2.x, 674 dy = p1.y - p2.y, 675 dist = Math.sqrt(dx * dx + dy * dy); 676 677 /* draw a line between p1 and p2 if the distance between them is under the config distance */ 678 if (dist <= pJS.particles.line_linked.distance) { 679 680 var opacity_line = pJS.particles.line_linked.opacity - (dist / (1 / pJS.particles.line_linked.opacity)) / pJS.particles.line_linked.distance; 681 682 if (opacity_line > 0) { 683 684 /* style */ 685 var color_line = pJS.particles.line_linked.color_rgb_line; 686 pJS.canvas.ctx.strokeStyle = 'rgba(' + color_line.r + ',' + color_line.g + ',' + color_line.b + ',' + opacity_line + ')'; 687 pJS.canvas.ctx.lineWidth = pJS.particles.line_linked.width; 688 //pJS.canvas.ctx.lineCap = 'round'; /* performance issue */ 689 690 /* path */ 691 pJS.canvas.ctx.beginPath(); 692 pJS.canvas.ctx.moveTo(p1.x, p1.y); 693 pJS.canvas.ctx.lineTo(p2.x, p2.y); 694 pJS.canvas.ctx.stroke(); 695 pJS.canvas.ctx.closePath(); 696 697 } 698 699 } 700 701 }; 702 703 704 pJS.fn.interact.attractParticles = function(p1, p2) { 705 706 /* condensed particles */ 707 var dx = p1.x - p2.x, 708 dy = p1.y - p2.y, 709 dist = Math.sqrt(dx * dx + dy * dy); 710 711 if (dist <= pJS.particles.line_linked.distance) { 712 713 var ax = dx / (pJS.particles.move.attract.rotateX * 1000), 714 ay = dy / (pJS.particles.move.attract.rotateY * 1000); 715 716 p1.vx -= ax; 717 p1.vy -= ay; 718 719 p2.vx += ax; 720 p2.vy += ay; 721 722 } 723 724 725 } 726 727 728 pJS.fn.interact.bounceParticles = function(p1, p2) { 729 730 var dx = p1.x - p2.x, 731 dy = p1.y - p2.y, 732 dist = Math.sqrt(dx * dx + dy * dy), 733 dist_p = p1.radius + p2.radius; 734 735 if (dist <= dist_p) { 736 p1.vx = -p1.vx; 737 p1.vy = -p1.vy; 738 739 p2.vx = -p2.vx; 740 p2.vy = -p2.vy; 741 } 742 743 } 744 745 746 /* ---------- pJS functions - modes events ------------ */ 747 748 pJS.fn.modes.pushParticles = function(nb, pos) { 749 750 pJS.tmp.pushing = true; 751 752 for (var i = 0; i < nb; i++) { 753 pJS.particles.array.push( 754 new pJS.fn.particle( 755 pJS.particles.color, 756 pJS.particles.opacity.value, { 757 'x': pos ? pos.pos_x : Math.random() * pJS.canvas.w, 758 'y': pos ? pos.pos_y : Math.random() * pJS.canvas.h 759 } 760 ) 761 ) 762 if (i == nb - 1) { 763 if (!pJS.particles.move.enable) { 764 pJS.fn.particlesDraw(); 765 } 766 pJS.tmp.pushing = false; 767 } 768 } 769 770 }; 771 772 773 pJS.fn.modes.removeParticles = function(nb) { 774 775 pJS.particles.array.splice(0, nb); 776 if (!pJS.particles.move.enable) { 777 pJS.fn.particlesDraw(); 778 } 779 780 }; 781 782 783 pJS.fn.modes.bubbleParticle = function(p) { 784 785 /* on hover event */ 786 if (pJS.interactivity.events.onhover.enable && isInArray('bubble', pJS.interactivity.events.onhover.mode)) { 787 788 var dx_mouse = p.x - pJS.interactivity.mouse.pos_x, 789 dy_mouse = p.y - pJS.interactivity.mouse.pos_y, 790 dist_mouse = Math.sqrt(dx_mouse * dx_mouse + dy_mouse * dy_mouse), 791 ratio = 1 - dist_mouse / pJS.interactivity.modes.bubble.distance; 792 793 function init() { 794 p.opacity_bubble = p.opacity; 795 p.radius_bubble = p.radius; 796 } 797 798 /* mousemove - check ratio */ 799 if (dist_mouse <= pJS.interactivity.modes.bubble.distance) { 800 801 if (ratio >= 0 && pJS.interactivity.status == 'mousemove') { 802 803 /* size */ 804 if (pJS.interactivity.modes.bubble.size != pJS.particles.size.value) { 805 806 if (pJS.interactivity.modes.bubble.size > pJS.particles.size.value) { 807 var size = p.radius + (pJS.interactivity.modes.bubble.size * ratio); 808 if (size >= 0) { 809 p.radius_bubble = size; 810 } 811 } else { 812 var dif = p.radius - pJS.interactivity.modes.bubble.size, 813 size = p.radius - (dif * ratio); 814 if (size > 0) { 815 p.radius_bubble = size; 816 } else { 817 p.radius_bubble = 0; 818 } 819 } 820 821 } 822 823 /* opacity */ 824 if (pJS.interactivity.modes.bubble.opacity != pJS.particles.opacity.value) { 825 826 if (pJS.interactivity.modes.bubble.opacity > pJS.particles.opacity.value) { 827 var opacity = pJS.interactivity.modes.bubble.opacity * ratio; 828 if (opacity > p.opacity && opacity <= pJS.interactivity.modes.bubble.opacity) { 829 p.opacity_bubble = opacity; 830 } 831 } else { 832 var opacity = p.opacity - (pJS.particles.opacity.value - pJS.interactivity.modes.bubble.opacity) * ratio; 833 if (opacity < p.opacity && opacity >= pJS.interactivity.modes.bubble.opacity) { 834 p.opacity_bubble = opacity; 835 } 836 } 837 838 } 839 840 } 841 842 } else { 843 init(); 844 } 845 846 847 /* mouseleave */ 848 if (pJS.interactivity.status == 'mouseleave') { 849 init(); 850 } 851 852 } 853 854 /* on click event */ 855 else if (pJS.interactivity.events.onclick.enable && isInArray('bubble', pJS.interactivity.events.onclick.mode)) { 856 857 858 if (pJS.tmp.bubble_clicking) { 859 var dx_mouse = p.x - pJS.interactivity.mouse.click_pos_x, 860 dy_mouse = p.y - pJS.interactivity.mouse.click_pos_y, 861 dist_mouse = Math.sqrt(dx_mouse * dx_mouse + dy_mouse * dy_mouse), 862 time_spent = (new Date().getTime() - pJS.interactivity.mouse.click_time) / 1000; 863 864 if (time_spent > pJS.interactivity.modes.bubble.duration) { 865 pJS.tmp.bubble_duration_end = true; 866 } 867 868 if (time_spent > pJS.interactivity.modes.bubble.duration * 2) { 869 pJS.tmp.bubble_clicking = false; 870 pJS.tmp.bubble_duration_end = false; 871 } 872 } 873 874 875 function process(bubble_param, particles_param, p_obj_bubble, p_obj, id) { 876 877 if (bubble_param != particles_param) { 878 879 if (!pJS.tmp.bubble_duration_end) { 880 if (dist_mouse <= pJS.interactivity.modes.bubble.distance) { 881 if (p_obj_bubble != undefined) var obj = p_obj_bubble; 882 else var obj = p_obj; 883 if (obj != bubble_param) { 884 var value = p_obj - (time_spent * (p_obj - bubble_param) / pJS.interactivity.modes.bubble.duration); 885 if (id == 'size') p.radius_bubble = value; 886 if (id == 'opacity') p.opacity_bubble = value; 887 } 888 } else { 889 if (id == 'size') p.radius_bubble = undefined; 890 if (id == 'opacity') p.opacity_bubble = undefined; 891 } 892 } else { 893 if (p_obj_bubble != undefined) { 894 var value_tmp = p_obj - (time_spent * (p_obj - bubble_param) / pJS.interactivity.modes.bubble.duration), 895 dif = bubble_param - value_tmp; 896 value = bubble_param + dif; 897 if (id == 'size') p.radius_bubble = value; 898 if (id == 'opacity') p.opacity_bubble = value; 899 } 900 } 901 902 } 903 904 } 905 906 if (pJS.tmp.bubble_clicking) { 907 /* size */ 908 process(pJS.interactivity.modes.bubble.size, pJS.particles.size.value, p.radius_bubble, p.radius, 'size'); 909 /* opacity */ 910 process(pJS.interactivity.modes.bubble.opacity, pJS.particles.opacity.value, p.opacity_bubble, p.opacity, 'opacity'); 911 } 912 913 } 914 915 }; 916 917 918 pJS.fn.modes.repulseParticle = function(p) { 919 920 if (pJS.interactivity.events.onhover.enable && isInArray('repulse', pJS.interactivity.events.onhover.mode) && pJS.interactivity.status == 'mousemove') { 921 922 var dx_mouse = p.x - pJS.interactivity.mouse.pos_x, 923 dy_mouse = p.y - pJS.interactivity.mouse.pos_y, 924 dist_mouse = Math.sqrt(dx_mouse * dx_mouse + dy_mouse * dy_mouse); 925 926 var normVec = { x: dx_mouse / dist_mouse, y: dy_mouse / dist_mouse }, 927 repulseRadius = pJS.interactivity.modes.repulse.distance, 928 velocity = 100, 929 repulseFactor = clamp((1 / repulseRadius) * (-1 * Math.pow(dist_mouse / repulseRadius, 2) + 1) * repulseRadius * velocity, 0, 50); 930 931 var pos = { 932 x: p.x + normVec.x * repulseFactor, 933 y: p.y + normVec.y * repulseFactor 934 } 935 936 if (pJS.particles.move.out_mode == 'bounce') { 937 if (pos.x - p.radius > 0 && pos.x + p.radius < pJS.canvas.w) p.x = pos.x; 938 if (pos.y - p.radius > 0 && pos.y + p.radius < pJS.canvas.h) p.y = pos.y; 939 } else { 940 p.x = pos.x; 941 p.y = pos.y; 942 } 943 944 } else if (pJS.interactivity.events.onclick.enable && isInArray('repulse', pJS.interactivity.events.onclick.mode)) { 945 946 if (!pJS.tmp.repulse_finish) { 947 pJS.tmp.repulse_count++; 948 if (pJS.tmp.repulse_count == pJS.particles.array.length) { 949 pJS.tmp.repulse_finish = true; 950 } 951 } 952 953 if (pJS.tmp.repulse_clicking) { 954 955 var repulseRadius = Math.pow(pJS.interactivity.modes.repulse.distance / 6, 3); 956 957 var dx = pJS.interactivity.mouse.click_pos_x - p.x, 958 dy = pJS.interactivity.mouse.click_pos_y - p.y, 959 d = dx * dx + dy * dy; 960 961 var force = -repulseRadius / d * 1; 962 963 function process() { 964 965 var f = Math.atan2(dy, dx); 966 p.vx = force * Math.cos(f); 967 p.vy = force * Math.sin(f); 968 969 if (pJS.particles.move.out_mode == 'bounce') { 970 var pos = { 971 x: p.x + p.vx, 972 y: p.y + p.vy 973 } 974 if (pos.x + p.radius > pJS.canvas.w) p.vx = -p.vx; 975 else if (pos.x - p.radius < 0) p.vx = -p.vx; 976 if (pos.y + p.radius > pJS.canvas.h) p.vy = -p.vy; 977 else if (pos.y - p.radius < 0) p.vy = -p.vy; 978 } 979 980 } 981 982 // default 983 if (d <= repulseRadius) { 984 process(); 985 } 986 987 // bang - slow motion mode 988 // if(!pJS.tmp.repulse_finish){ 989 // if(d <= repulseRadius){ 990 // process(); 991 // } 992 // }else{ 993 // process(); 994 // } 995 996 997 } else { 998 999 if (pJS.tmp.repulse_clicking == false) { 1000 1001 p.vx = p.vx_i; 1002 p.vy = p.vy_i; 1003 1004 } 1005 1006 } 1007 1008 } 1009 1010 } 1011 1012 1013 pJS.fn.modes.grabParticle = function(p) { 1014 1015 if (pJS.interactivity.events.onhover.enable && pJS.interactivity.status == 'mousemove') { 1016 1017 var dx_mouse = p.x - pJS.interactivity.mouse.pos_x, 1018 dy_mouse = p.y - pJS.interactivity.mouse.pos_y, 1019 dist_mouse = Math.sqrt(dx_mouse * dx_mouse + dy_mouse * dy_mouse); 1020 1021 /* draw a line between the cursor and the particle if the distance between them is under the config distance */ 1022 if (dist_mouse <= pJS.interactivity.modes.grab.distance) { 1023 1024 var opacity_line = pJS.interactivity.modes.grab.line_linked.opacity - (dist_mouse / (1 / pJS.interactivity.modes.grab.line_linked.opacity)) / pJS.interactivity.modes.grab.distance; 1025 1026 if (opacity_line > 0) { 1027 1028 /* style */ 1029 var color_line = pJS.particles.line_linked.color_rgb_line; 1030 pJS.canvas.ctx.strokeStyle = 'rgba(' + color_line.r + ',' + color_line.g + ',' + color_line.b + ',' + opacity_line + ')'; 1031 pJS.canvas.ctx.lineWidth = pJS.particles.line_linked.width; 1032 //pJS.canvas.ctx.lineCap = 'round'; /* performance issue */ 1033 1034 /* path */ 1035 pJS.canvas.ctx.beginPath(); 1036 pJS.canvas.ctx.moveTo(p.x, p.y); 1037 pJS.canvas.ctx.lineTo(pJS.interactivity.mouse.pos_x, pJS.interactivity.mouse.pos_y); 1038 pJS.canvas.ctx.stroke(); 1039 pJS.canvas.ctx.closePath(); 1040 1041 } 1042 1043 } 1044 1045 } 1046 1047 }; 1048 1049 1050 1051 /* ---------- pJS functions - vendors ------------ */ 1052 1053 pJS.fn.vendors.eventsListeners = function() { 1054 1055 /* events target element */ 1056 if (pJS.interactivity.detect_on == 'window') { 1057 pJS.interactivity.el = window; 1058 } else { 1059 pJS.interactivity.el = pJS.canvas.el; 1060 } 1061 1062 1063 /* detect mouse pos - on hover / click event */ 1064 if (pJS.interactivity.events.onhover.enable || pJS.interactivity.events.onclick.enable) { 1065 1066 /* el on mousemove */ 1067 pJS.interactivity.el.addEventListener('mousemove', function(e) { 1068 1069 if (pJS.interactivity.el == window) { 1070 var pos_x = e.clientX, 1071 pos_y = e.clientY; 1072 } else { 1073 var pos_x = e.offsetX || e.clientX, 1074 pos_y = e.offsetY || e.clientY; 1075 } 1076 1077 pJS.interactivity.mouse.pos_x = pos_x; 1078 pJS.interactivity.mouse.pos_y = pos_y; 1079 1080 if (pJS.tmp.retina) { 1081 pJS.interactivity.mouse.pos_x *= pJS.canvas.pxratio; 1082 pJS.interactivity.mouse.pos_y *= pJS.canvas.pxratio; 1083 } 1084 1085 pJS.interactivity.status = 'mousemove'; 1086 1087 }); 1088 1089 /* el on onmouseleave */ 1090 pJS.interactivity.el.addEventListener('mouseleave', function(e) { 1091 1092 pJS.interactivity.mouse.pos_x = null; 1093 pJS.interactivity.mouse.pos_y = null; 1094 pJS.interactivity.status = 'mouseleave'; 1095 1096 }); 1097 1098 } 1099 1100 /* on click event */ 1101 if (pJS.interactivity.events.onclick.enable) { 1102 1103 pJS.interactivity.el.addEventListener('click', function() { 1104 1105 pJS.interactivity.mouse.click_pos_x = pJS.interactivity.mouse.pos_x; 1106 pJS.interactivity.mouse.click_pos_y = pJS.interactivity.mouse.pos_y; 1107 pJS.interactivity.mouse.click_time = new Date().getTime(); 1108 1109 if (pJS.interactivity.events.onclick.enable) { 1110 1111 switch (pJS.interactivity.events.onclick.mode) { 1112 1113 case 'push': 1114 if (pJS.particles.move.enable) { 1115 pJS.fn.modes.pushParticles(pJS.interactivity.modes.push.particles_nb, pJS.interactivity.mouse); 1116 } else { 1117 if (pJS.interactivity.modes.push.particles_nb == 1) { 1118 pJS.fn.modes.pushParticles(pJS.interactivity.modes.push.particles_nb, pJS.interactivity.mouse); 1119 } else if (pJS.interactivity.modes.push.particles_nb > 1) { 1120 pJS.fn.modes.pushParticles(pJS.interactivity.modes.push.particles_nb); 1121 } 1122 } 1123 break; 1124 1125 case 'remove': 1126 pJS.fn.modes.removeParticles(pJS.interactivity.modes.remove.particles_nb); 1127 break; 1128 1129 case 'bubble': 1130 pJS.tmp.bubble_clicking = true; 1131 break; 1132 1133 case 'repulse': 1134 pJS.tmp.repulse_clicking = true; 1135 pJS.tmp.repulse_count = 0; 1136 pJS.tmp.repulse_finish = false; 1137 setTimeout(function() { 1138 pJS.tmp.repulse_clicking = false; 1139 }, pJS.interactivity.modes.repulse.duration * 1000) 1140 break; 1141 1142 } 1143 1144 } 1145 1146 }); 1147 1148 } 1149 1150 1151 }; 1152 1153 pJS.fn.vendors.densityAutoParticles = function() { 1154 1155 if (pJS.particles.number.density.enable) { 1156 1157 /* calc area */ 1158 var area = pJS.canvas.el.width * pJS.canvas.el.height / 1000; 1159 if (pJS.tmp.retina) { 1160 area = area / (pJS.canvas.pxratio * 2); 1161 } 1162 1163 /* calc number of particles based on density area */ 1164 var nb_particles = area * pJS.particles.number.value / pJS.particles.number.density.value_area; 1165 1166 /* add or remove X particles */ 1167 var missing_particles = pJS.particles.array.length - nb_particles; 1168 if (missing_particles < 0) pJS.fn.modes.pushParticles(Math.abs(missing_particles)); 1169 else pJS.fn.modes.removeParticles(missing_particles); 1170 1171 } 1172 1173 }; 1174 1175 1176 pJS.fn.vendors.checkOverlap = function(p1, position) { 1177 for (var i = 0; i < pJS.particles.array.length; i++) { 1178 var p2 = pJS.particles.array[i]; 1179 1180 var dx = p1.x - p2.x, 1181 dy = p1.y - p2.y, 1182 dist = Math.sqrt(dx * dx + dy * dy); 1183 1184 if (dist <= p1.radius + p2.radius) { 1185 p1.x = position ? position.x : Math.random() * pJS.canvas.w; 1186 p1.y = position ? position.y : Math.random() * pJS.canvas.h; 1187 pJS.fn.vendors.checkOverlap(p1); 1188 } 1189 } 1190 }; 1191 1192 1193 pJS.fn.vendors.createSvgImg = function(p) { 1194 1195 /* set color to svg element */ 1196 var svgXml = pJS.tmp.source_svg, 1197 rgbHex = /#([0-9A-F]{3,6})/gi, 1198 coloredSvgXml = svgXml.replace(rgbHex, function(m, r, g, b) { 1199 if (p.color.rgb) { 1200 var color_value = 'rgba(' + p.color.rgb.r + ',' + p.color.rgb.g + ',' + p.color.rgb.b + ',' + p.opacity + ')'; 1201 } else { 1202 var color_value = 'hsla(' + p.color.hsl.h + ',' + p.color.hsl.s + '%,' + p.color.hsl.l + '%,' + p.opacity + ')'; 1203 } 1204 return color_value; 1205 }); 1206 1207 /* prepare to create img with colored svg */ 1208 var svg = new Blob([coloredSvgXml], { type: 'image/svg+xml;charset=utf-8' }), 1209 DOMURL = window.URL || window.webkitURL || window, 1210 url = DOMURL.createObjectURL(svg); 1211 1212 /* create particle img obj */ 1213 var img = new Image(); 1214 img.addEventListener('load', function() { 1215 p.img.obj = img; 1216 p.img.loaded = true; 1217 DOMURL.revokeObjectURL(url); 1218 pJS.tmp.count_svg++; 1219 }); 1220 img.src = url; 1221 1222 }; 1223 1224 1225 pJS.fn.vendors.destroypJS = function() { 1226 cancelAnimationFrame(pJS.fn.drawAnimFrame); 1227 canvas_el.remove(); 1228 pJSDom = null; 1229 }; 1230 1231 1232 pJS.fn.vendors.drawShape = function(c, startX, startY, sideLength, sideCountNumerator, sideCountDenominator) { 1233 1234 // By Programming Thomas - https://programmingthomas.wordpress.com/2013/04/03/n-sided-shapes/ 1235 var sideCount = sideCountNumerator * sideCountDenominator; 1236 var decimalSides = sideCountNumerator / sideCountDenominator; 1237 var interiorAngleDegrees = (180 * (decimalSides - 2)) / decimalSides; 1238 var interiorAngle = Math.PI - Math.PI * interiorAngleDegrees / 180; // convert to radians 1239 c.save(); 1240 c.beginPath(); 1241 c.translate(startX, startY); 1242 c.moveTo(0, 0); 1243 for (var i = 0; i < sideCount; i++) { 1244 c.lineTo(sideLength, 0); 1245 c.translate(sideLength, 0); 1246 c.rotate(interiorAngle); 1247 } 1248 //c.stroke(); 1249 c.fill(); 1250 c.restore(); 1251 1252 }; 1253 1254 pJS.fn.vendors.exportImg = function() { 1255 window.open(pJS.canvas.el.toDataURL('image/png'), '_blank'); 1256 }; 1257 1258 1259 pJS.fn.vendors.loadImg = function(type) { 1260 1261 pJS.tmp.img_error = undefined; 1262 1263 if (pJS.particles.shape.image.src != '') { 1264 1265 if (type == 'svg') { 1266 1267 var xhr = new XMLHttpRequest(); 1268 xhr.open('GET', pJS.particles.shape.image.src); 1269 xhr.onreadystatechange = function(data) { 1270 if (xhr.readyState == 4) { 1271 if (xhr.status == 200) { 1272 pJS.tmp.source_svg = data.currentTarget.response; 1273 pJS.fn.vendors.checkBeforeDraw(); 1274 } else { 1275 console.log('Error pJS - Image not found'); 1276 pJS.tmp.img_error = true; 1277 } 1278 } 1279 } 1280 xhr.send(); 1281 1282 } else { 1283 1284 var img = new Image(); 1285 img.addEventListener('load', function() { 1286 pJS.tmp.img_obj = img; 1287 pJS.fn.vendors.checkBeforeDraw(); 1288 }); 1289 img.src = pJS.particles.shape.image.src; 1290 1291 } 1292 1293 } else { 1294 console.log('Error pJS - No image.src'); 1295 pJS.tmp.img_error = true; 1296 } 1297 1298 }; 1299 1300 1301 pJS.fn.vendors.draw = function() { 1302 1303 if (pJS.particles.shape.type == 'image') { 1304 1305 if (pJS.tmp.img_type == 'svg') { 1306 1307 if (pJS.tmp.count_svg >= pJS.particles.number.value) { 1308 pJS.fn.particlesDraw(); 1309 if (!pJS.particles.move.enable) cancelRequestAnimFrame(pJS.fn.drawAnimFrame); 1310 else pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw); 1311 } else { 1312 //console.log('still loading...'); 1313 if (!pJS.tmp.img_error) pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw); 1314 } 1315 1316 } else { 1317 1318 if (pJS.tmp.img_obj != undefined) { 1319 pJS.fn.particlesDraw(); 1320 if (!pJS.particles.move.enable) cancelRequestAnimFrame(pJS.fn.drawAnimFrame); 1321 else pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw); 1322 } else { 1323 if (!pJS.tmp.img_error) pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw); 1324 } 1325 1326 } 1327 1328 } else { 1329 pJS.fn.particlesDraw(); 1330 if (!pJS.particles.move.enable) cancelRequestAnimFrame(pJS.fn.drawAnimFrame); 1331 else pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw); 1332 } 1333 1334 }; 1335 1336 1337 pJS.fn.vendors.checkBeforeDraw = function() { 1338 1339 // if shape is image 1340 if (pJS.particles.shape.type == 'image') { 1341 1342 if (pJS.tmp.img_type == 'svg' && pJS.tmp.source_svg == undefined) { 1343 pJS.tmp.checkAnimFrame = requestAnimFrame(check); 1344 } else { 1345 //console.log('images loaded! cancel check'); 1346 cancelRequestAnimFrame(pJS.tmp.checkAnimFrame); 1347 if (!pJS.tmp.img_error) { 1348 pJS.fn.vendors.init(); 1349 pJS.fn.vendors.draw(); 1350 } 1351 1352 } 1353 1354 } else { 1355 pJS.fn.vendors.init(); 1356 pJS.fn.vendors.draw(); 1357 } 1358 1359 }; 1360 1361 1362 pJS.fn.vendors.init = function() { 1363 1364 /* init canvas + particles */ 1365 pJS.fn.retinaInit(); 1366 pJS.fn.canvasInit(); 1367 pJS.fn.canvasSize(); 1368 pJS.fn.canvasPaint(); 1369 pJS.fn.particlesCreate(); 1370 pJS.fn.vendors.densityAutoParticles(); 1371 1372 /* particles.line_linked - convert hex colors to rgb */ 1373 pJS.particles.line_linked.color_rgb_line = hexToRgb(pJS.particles.line_linked.color); 1374 1375 }; 1376 1377 1378 pJS.fn.vendors.start = function() { 1379 1380 if (isInArray('image', pJS.particles.shape.type)) { 1381 pJS.tmp.img_type = pJS.particles.shape.image.src.substr(pJS.particles.shape.image.src.length - 3); 1382 pJS.fn.vendors.loadImg(pJS.tmp.img_type); 1383 } else { 1384 pJS.fn.vendors.checkBeforeDraw(); 1385 } 1386 1387 }; 1388 1389 1390 1391 1392 /* ---------- pJS - start ------------ */ 1393 1394 1395 pJS.fn.vendors.eventsListeners(); 1396 1397 pJS.fn.vendors.start(); 1398 1399 1400 1401}; 1402 1403/* ---------- global functions - vendors ------------ */ 1404 1405Object.deepExtend = function(destination, source) { 1406 for (var property in source) { 1407 if (source[property] && source[property].constructor && 1408 source[property].constructor === Object) { 1409 destination[property] = destination[property] || {}; 1410 arguments.callee(destination[property], source[property]); 1411 } else { 1412 destination[property] = source[property]; 1413 } 1414 } 1415 return destination; 1416}; 1417 1418window.requestAnimFrame = (function() { 1419 return window.requestAnimationFrame || 1420 window.webkitRequestAnimationFrame || 1421 window.mozRequestAnimationFrame || 1422 window.oRequestAnimationFrame || 1423 window.msRequestAnimationFrame || 1424 function(callback) { 1425 window.setTimeout(callback, 1000 / 60); 1426 }; 1427})(); 1428 1429window.cancelRequestAnimFrame = (function() { 1430 return window.cancelAnimationFrame || 1431 window.webkitCancelRequestAnimationFrame || 1432 window.mozCancelRequestAnimationFrame || 1433 window.oCancelRequestAnimationFrame || 1434 window.msCancelRequestAnimationFrame || 1435 clearTimeout 1436})(); 1437 1438function hexToRgb(hex) { 1439 // By Tim Down - http://stackoverflow.com/a/5624139/3493650 1440 // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF") 1441 var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i; 1442 hex = hex.replace(shorthandRegex, function(m, r, g, b) { 1443 return r + r + g + g + b + b; 1444 }); 1445 var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); 1446 return result ? { 1447 r: parseInt(result[1], 16), 1448 g: parseInt(result[2], 16), 1449 b: parseInt(result[3], 16) 1450 } : null; 1451}; 1452 1453function clamp(number, min, max) { 1454 return Math.min(Math.max(number, min), max); 1455}; 1456 1457function isInArray(value, array) { 1458 return array.indexOf(value) > -1; 1459} 1460 1461 1462/* ---------- particles.js functions - start ------------ */ 1463 1464window.pJSDom = []; 1465 1466window.particlesJS = function(tag_id, params) { 1467 1468 //console.log(params); 1469 1470 /* no string id? so it's object params, and set the id with default id */ 1471 if (typeof(tag_id) != 'string') { 1472 params = tag_id; 1473 tag_id = 'particles-js'; 1474 } 1475 1476 /* no id? set the id to default id */ 1477 if (!tag_id) { 1478 tag_id = 'particles-js'; 1479 } 1480 1481 /* pJS elements */ 1482 var pJS_tag = document.getElementById(tag_id), 1483 pJS_canvas_class = 'particles-js-canvas-el', 1484 exist_canvas = pJS_tag.getElementsByClassName(pJS_canvas_class); 1485 1486 /* remove canvas if exists into the pJS target tag */ 1487 if (exist_canvas.length) { 1488 while (exist_canvas.length > 0) { 1489 pJS_tag.removeChild(exist_canvas[0]); 1490 } 1491 } 1492 1493 /* create canvas element */ 1494 var canvas_el = document.createElement('canvas'); 1495 canvas_el.className = pJS_canvas_class; 1496 1497 /* set size canvas */ 1498 canvas_el.style.width = "100%"; 1499 canvas_el.style.height = "100%"; 1500 1501 /* append canvas */ 1502 var canvas = document.getElementById(tag_id).appendChild(canvas_el); 1503 1504 /* launch particle.js */ 1505 if (canvas != null) { 1506 pJSDom.push(new pJS(tag_id, params)); 1507 } 1508 1509}; 1510 1511window.particlesJS.load = function(tag_id, path_config_json, callback) { 1512 1513 /* load json config */ 1514 var xhr = new XMLHttpRequest(); 1515 xhr.open('GET', path_config_json); 1516 xhr.onreadystatechange = function(data) { 1517 if (xhr.readyState == 4) { 1518 if (xhr.status == 200) { 1519 var params = JSON.parse(data.currentTarget.response); 1520 window.particlesJS(tag_id, params); 1521 if (callback) callback(); 1522 } else {
1523 console.log('Error pJS - XMLHttpRequest status: ' + xhr.status); 1524 console.log('Error pJS - File config not found'); 1525 } 1526 } 1527 }; 1528 xhr.send(); 1529 1530};
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.