Advertisement
Guest User

particles.js

a guest
Nov 23rd, 2016
48
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 43.50 KB | None | 0 0
  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. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement