particles-js-rails 2.0.0

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