PageSourceSearch

https://envision22.netlify.app/animation.js

js envision22.netlify.app collected 2026-10-03 10:42:16 UTC 50,122 bytes, 1,699 lines download raw bytes

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

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.