├── ads.txt ├── .vscode └── settings.json ├── capstone.png ├── xgenerator.jpg ├── README.md ├── test └── index.html ├── assets ├── particlesjs-config.json ├── app.js ├── style.css └── particle.js ├── style.css ├── index.html └── script.js /ads.txt: -------------------------------------------------------------------------------- 1 | google.com, pub-5963862362731163, DIRECT, f08c47fec0942fa0 -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "liveServer.settings.port": 5502 3 | } -------------------------------------------------------------------------------- /capstone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carlcastanas/Capstone-Generator/HEAD/capstone.png -------------------------------------------------------------------------------- /xgenerator.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carlcastanas/Capstone-Generator/HEAD/xgenerator.jpg -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Capstone Title Generator 2 | This capstone title generator was made by myself, **Carl Andrew Castanas**. This little project was created for students who are having trouble coming up with a distinctive capstone title. This capstone title generator will help you come up with the best capstone title while lowering your stress levels.
3 | ![image](https://raw.githubusercontent.com/carlcastanas/Capstone-Generator/main/capstone.png?token=GHSAT0AAAAAABTDRDGNWHNX64347N54TGWAYSRM3KA) 4 | -------------------------------------------------------------------------------- /test/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Centering a Div 7 | 19 | 20 | 21 |
22 |
23 | 24 |

This div is centered horizontally

25 |

Lorem ipsum dolor sit amet, consectetur adipiscing elit.

26 |
27 |
28 | 29 | 30 | -------------------------------------------------------------------------------- /assets/particlesjs-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "particles": { 3 | "number": { 4 | "value": 361, 5 | "density": { 6 | "enable": true, 7 | "value_area": 962.0472365193136 8 | } 9 | }, 10 | "color": { 11 | "value": "#ffffff" 12 | }, 13 | "shape": { 14 | "type": "circle", 15 | "stroke": { 16 | "width": 0, 17 | "color": "#000000" 18 | }, 19 | "polygon": { 20 | "nb_sides": 5 21 | }, 22 | "image": { 23 | "src": "img/github.svg", 24 | "width": 100, 25 | "height": 100 26 | } 27 | }, 28 | "opacity": { 29 | "value": 1, 30 | "random": true, 31 | "anim": { 32 | "enable": true, 33 | "speed": 1, 34 | "opacity_min": 0, 35 | "sync": false 36 | } 37 | }, 38 | "size": { 39 | "value": 2, 40 | "random": true, 41 | "anim": { 42 | "enable": false, 43 | "speed": 4, 44 | "size_min": 0.3, 45 | "sync": false 46 | } 47 | }, 48 | "line_linked": { 49 | "enable": false, 50 | "distance": 150, 51 | "color": "#ffffff", 52 | "opacity": 0.4, 53 | "width": 1 54 | }, 55 | "move": { 56 | "enable": true, 57 | "speed": 1, 58 | "direction": "none", 59 | "random": true, 60 | "straight": false, 61 | "out_mode": "out", 62 | "bounce": false, 63 | "attract": { 64 | "enable": false, 65 | "rotateX": 600, 66 | "rotateY": 600 67 | } 68 | } 69 | }, 70 | "interactivity": { 71 | "detect_on": "canvas", 72 | "events": { 73 | "onhover": { 74 | "enable": true, 75 | "mode": "bubble" 76 | }, 77 | "onclick": { 78 | "enable": true, 79 | "mode": "repulse" 80 | }, 81 | "resize": true 82 | }, 83 | "modes": { 84 | "grab": { 85 | "distance": 400, 86 | "line_linked": { 87 | "opacity": 1 88 | } 89 | }, 90 | "bubble": { 91 | "distance": 250, 92 | "size": 0, 93 | "duration": 2, 94 | "opacity": 0, 95 | "speed": 3 96 | }, 97 | "repulse": { 98 | "distance": 400, 99 | "duration": 0.4 100 | }, 101 | "push": { 102 | "particles_nb": 4 103 | }, 104 | "remove": { 105 | "particles_nb": 2 106 | } 107 | } 108 | }, 109 | "retina_detect": true 110 | } -------------------------------------------------------------------------------- /assets/app.js: -------------------------------------------------------------------------------- 1 | particlesJS('particles-js', 2 | 3 | { 4 | "particles": { 5 | "number": { 6 | "value": 361, 7 | "density": { 8 | "enable": true, 9 | "value_area": 962.0472365193136 10 | } 11 | }, 12 | "color": { 13 | "value": "#ffffff" 14 | }, 15 | "shape": { 16 | "type": "circle", 17 | "stroke": { 18 | "width": 0, 19 | "color": "#000000" 20 | }, 21 | "polygon": { 22 | "nb_sides": 5 23 | }, 24 | "image": { 25 | "src": "img/github.svg", 26 | "width": 100, 27 | "height": 100 28 | } 29 | }, 30 | "opacity": { 31 | "value": 1, 32 | "random": true, 33 | "anim": { 34 | "enable": true, 35 | "speed": 1, 36 | "opacity_min": 0, 37 | "sync": false 38 | } 39 | }, 40 | "size": { 41 | "value": 2, 42 | "random": true, 43 | "anim": { 44 | "enable": false, 45 | "speed": 4, 46 | "size_min": 0.3, 47 | "sync": false 48 | } 49 | }, 50 | "line_linked": { 51 | "enable": false, 52 | "distance": 150, 53 | "color": "#ffffff", 54 | "opacity": 0.4, 55 | "width": 1 56 | }, 57 | "move": { 58 | "enable": true, 59 | "speed": 1, 60 | "direction": "none", 61 | "random": true, 62 | "straight": false, 63 | "out_mode": "out", 64 | "bounce": false, 65 | "attract": { 66 | "enable": false, 67 | "rotateX": 600, 68 | "rotateY": 600 69 | } 70 | } 71 | }, 72 | "interactivity": { 73 | "detect_on": "canvas", 74 | "events": { 75 | "onhover": { 76 | "enable": true, 77 | "mode": "bubble" 78 | }, 79 | "onclick": { 80 | "enable": true, 81 | "mode": "repulse" 82 | }, 83 | "resize": true 84 | }, 85 | "modes": { 86 | "grab": { 87 | "distance": 400, 88 | "line_linked": { 89 | "opacity": 1 90 | } 91 | }, 92 | "bubble": { 93 | "distance": 250, 94 | "size": 0, 95 | "duration": 2, 96 | "opacity": 0, 97 | "speed": 3 98 | }, 99 | "repulse": { 100 | "distance": 400, 101 | "duration": 0.4 102 | }, 103 | "push": { 104 | "particles_nb": 4 105 | }, 106 | "remove": { 107 | "particles_nb": 2 108 | } 109 | } 110 | }, 111 | "retina_detect": true 112 | } 113 | 114 | ); 115 | -------------------------------------------------------------------------------- /style.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-image: url("https://wallpaper.dog/large/10777778.jpg"); 3 | color: white; 4 | padding-top: 50px; 5 | font-size: 18px; 6 | font-family: 'Roboto Slab', serif; 7 | height: 100%; 8 | margin: 0; 9 | padding: 0; 10 | overflow: hidden; 11 | } 12 | @media screen and (max-width: 600px) { 13 | h1, #paragraph { 14 | display: none; 15 | } 16 | } 17 | #particles-js 18 | { 19 | width:100%; 20 | height:100%; 21 | position: absolute; 22 | background-image: none; 23 | } 24 | h1 { 25 | font-size: 4em; 26 | line-height: 70px; 27 | margin-bottom: 40px; 28 | font-weight: bold; 29 | } 30 | 31 | a:hover, a:focus, a:active { 32 | text-decoration: none; 33 | color: white; 34 | transition: color 0.8s; 35 | } 36 | 37 | .main-color { 38 | color: #eeeef3; 39 | text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.2); 40 | font-weight: bold; 41 | } 42 | 43 | #quote-box { 44 | background: rgba(0, 0, 0, 0.4); 45 | box-shadow: 0 8px 32px 0 rgba( 31, 38, 135, 0.37 ); 46 | backdrop-filter: blur( 3.5px ); 47 | -webkit-backdrop-filter: blur( 3.5px ); 48 | border-radius: 10px; 49 | border: 1px solid rgba( 255, 255, 255, 0.18 ); 50 | padding: 100px 40px; 51 | position: relative; 52 | margin-top: 20px; 53 | } 54 | 55 | #quote-left, #quote-right { 56 | color: #ffffffe9; 57 | font-size: 2em; 58 | position: absolute; 59 | } 60 | 61 | #quote-left { 62 | top: 30px; 63 | left: 30px; 64 | } 65 | 66 | #quote-right { 67 | bottom: 30px; 68 | right: 30px; 69 | } 70 | 71 | #facebook { 72 | color: #ffffffe9; 73 | font-size: 1.5em; 74 | position: absolute; 75 | } 76 | 77 | #tiktok { 78 | color: #ffffffe9; 79 | font-size: 1.5em; 80 | position: absolute; 81 | } 82 | 83 | #quote { 84 | font-size: 1.5em; 85 | text-align: center; 86 | } 87 | 88 | #author { 89 | position: absolute; 90 | font-size: 1.1em; 91 | left: 50px; 92 | bottom: 30px; 93 | } 94 | 95 | .btn { 96 | background: rgba( 0, 0, 0, 0.4 ); 97 | box-shadow: 0 8px 32px 0 rgba( 31, 38, 135, 0.37 ); 98 | backdrop-filter: blur( 3.5px ); 99 | -webkit-backdrop-filter: blur( 3.5px ); 100 | border-radius: 10px; 101 | color: #eeeef3; 102 | border: 1px solid rgba( 255, 255, 255, 0.18 ); 103 | transition: background 0.8s, color 0.8s; 104 | line-height: 30px; 105 | margin-top: 30px; 106 | } 107 | 108 | .btn:hover, .btn:active, .btn:focus { 109 | color: white !important; 110 | background-color: #181717 !important; 111 | box-shadow: none; 112 | } 113 | 114 | ul { 115 | list-style-type: none; 116 | padding: 0; 117 | margin: 10px 0 0 0; 118 | float: right; 119 | white-space: nowrap; 120 | overflow: hidden; 121 | } 122 | 123 | li { 124 | display: inline-block; 125 | margin: 0 0 0 1px; 126 | } 127 | 128 | #hidden { 129 | display: none; 130 | } 131 | -------------------------------------------------------------------------------- /assets/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-image: url("https://wallpaper.dog/large/10777778.jpg"); 3 | color: white; 4 | padding-top: 50px; 5 | font-size: 18px; 6 | font-family: 'Roboto Slab', serif; 7 | height: 100%; 8 | margin: 0; 9 | padding: 0; 10 | overflow: hidden; 11 | } 12 | @media screen and (max-width: 600px) { 13 | h1, #paragraph { 14 | display: none; 15 | } 16 | } 17 | #particles-js 18 | { 19 | width:100%; 20 | height:100%; 21 | position: absolute; 22 | background-image: none; 23 | } 24 | h1 { 25 | font-size: 4em; 26 | line-height: 70px; 27 | margin-bottom: 40px; 28 | font-weight: bold; 29 | } 30 | 31 | nav { 32 | 33 | top: 0; 34 | left: 0; 35 | width: 100%; 36 | padding: 20px; 37 | background-color: rgba(255, 255, 255, 0); /* Transparent background */ 38 | transition: background-color 0.3s ease-in-out; /* Smooth transition for background color */ 39 | } 40 | 41 | nav ul { 42 | list-style-type: none; 43 | margin: 0; 44 | padding: 0; 45 | text-align: center; 46 | } 47 | 48 | nav ul li { 49 | display: inline-block; 50 | margin: 0 10px; 51 | } 52 | 53 | nav ul li a { 54 | text-decoration: none; 55 | color: #333; 56 | transition: color 0.3s ease-in-out; /* Smooth transition for link color */ 57 | } 58 | 59 | nav ul li a:hover { 60 | color: #555; /* Change link color on hover */ 61 | } 62 | a:hover, a:focus, a:active { 63 | text-decoration: none; 64 | color: white; 65 | transition: color 0.8s; 66 | } 67 | 68 | /* dark-theme.css */ 69 | .swal2-popup { 70 | background: rgba( 0, 0, 0, 0.4 ); 71 | box-shadow: 0 8px 32px 0 rgba( 31, 38, 135, 0.37 ); 72 | backdrop-filter: blur( 3.5px ); 73 | -webkit-backdrop-filter: blur( 3.5px ); 74 | border-radius: 10px; 75 | color: #eeeef3; 76 | border: 1px solid rgba( 255, 255, 255, 0.18 ); 77 | transition: background 0.8s, color 0.8s; 78 | line-height: 30px; 79 | margin-top: 30px; 80 | } 81 | 82 | .swal2-title { 83 | color: #fff; 84 | } 85 | 86 | .swal2-content { 87 | color: #fff; 88 | } 89 | 90 | .swal2-icon { 91 | color: #fff; 92 | } 93 | 94 | .swal2-cancel { 95 | color: #fff; 96 | background-color: #555; 97 | } 98 | .swal2-popup .swal2-confirm { 99 | background: rgba(0, 0, 0, 0.536); 100 | backdrop-filter: blur( 3.5px ); 101 | -webkit-backdrop-filter: blur( 3.5px ); 102 | border-radius: 15px; 103 | color: #eeeef3; 104 | border: 1px solid rgba( 255, 255, 255, 0.18 ); 105 | transition: background 0.8s, color 0.8s; 106 | line-height: 30px; 107 | padding: 5px 15px; 108 | 109 | } 110 | 111 | .swal2-popup .swal2-confirm:hover { 112 | background: rgba(255, 255, 255, 0.4); 113 | backdrop-filter: blur( 3.5px ); 114 | -webkit-backdrop-filter: blur( 3.5px ); 115 | border-radius: 25px; 116 | color: #000000; 117 | border: 1px solid rgba( 255, 255, 255, 0.18 ); 118 | transition: background 0.8s, color 0.8s; 119 | line-height: 30px; 120 | } 121 | 122 | .swal2-cancel:hover { 123 | background-color: #777; 124 | } 125 | 126 | .main-color { 127 | color: #eeeef3; 128 | text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.2); 129 | font-weight: bold; 130 | } 131 | 132 | #quote-box { 133 | background: rgba(0, 0, 0, 0.4); 134 | box-shadow: 0 8px 32px 0 rgba( 31, 38, 135, 0.37 ); 135 | backdrop-filter: blur( 3.5px ); 136 | -webkit-backdrop-filter: blur( 3.5px ); 137 | border-radius: 10px; 138 | border: 1px solid rgba( 255, 255, 255, 0.18 ); 139 | padding: 100px 40px; 140 | position: relative; 141 | margin-top: 20px; 142 | } 143 | 144 | #quote-left, #quote-right { 145 | color: #ffffffe9; 146 | font-size: 2em; 147 | position: absolute; 148 | } 149 | 150 | #quote-left { 151 | top: 30px; 152 | left: 30px; 153 | } 154 | 155 | #quote-right { 156 | bottom: 30px; 157 | right: 30px; 158 | } 159 | 160 | #facebook { 161 | color: #ffffffe9; 162 | font-size: 1.5em; 163 | position: absolute; 164 | } 165 | 166 | #tiktok { 167 | color: #ffffffe9; 168 | font-size: 1.5em; 169 | position: absolute; 170 | } 171 | 172 | #quote { 173 | font-size: 1.5em; 174 | text-align: center; 175 | } 176 | 177 | #author { 178 | position: absolute; 179 | font-size: 1.1em; 180 | left: 50px; 181 | bottom: 30px; 182 | } 183 | 184 | .btn { 185 | background: rgba( 0, 0, 0, 0.4 ); 186 | box-shadow: 0 8px 32px 0 rgba( 31, 38, 135, 0.37 ); 187 | backdrop-filter: blur( 3.5px ); 188 | -webkit-backdrop-filter: blur( 3.5px ); 189 | border-radius: 10px; 190 | color: #eeeef3; 191 | border: 1px solid rgba( 255, 255, 255, 0.18 ); 192 | transition: background 0.8s, color 0.8s; 193 | line-height: 30px; 194 | margin-top: 30px; 195 | } 196 | 197 | .btn:hover, .btn:active, .btn:focus { 198 | color: white !important; 199 | background-color: #181717 !important; 200 | box-shadow: none; 201 | } 202 | 203 | ul { 204 | list-style-type: none; 205 | padding: 0; 206 | margin: 10px 0 0 0; 207 | float: right; 208 | white-space: nowrap; 209 | overflow: hidden; 210 | } 211 | 212 | li { 213 | display: inline-block; 214 | margin: 0 0 0 1px; 215 | } 216 | 217 | #hidden { 218 | display: none; 219 | } 220 | .loading-icon { 221 | display: none; 222 | margin-left: 5px; 223 | } 224 | 225 | /* Add loading spinner animation */ 226 | @keyframes spin { 227 | 0% { transform: rotate(0deg); } 228 | 100% { transform: rotate(360deg); } 229 | } 230 | .loading-icon:before { 231 | content: ''; 232 | box-sizing: border-box; 233 | width: 14px; 234 | height: 14px; 235 | border-radius: 50%; 236 | border: 2px solid #fff; 237 | border-top-color: transparent; 238 | animation: spin 0.8s linear infinite; 239 | display: inline-block; 240 | vertical-align: middle; 241 | } 242 | #copy-button { 243 | font-size: large; 244 | background-color: #181717; 245 | color: aliceblue; 246 | position: absolute; 247 | bottom: 20px; 248 | right: 20px; 249 | transform: translateX(-50%); 250 | padding: 5px 10px; 251 | border: 1px solid rgb(68, 68, 68); /* Thin white border */ 252 | cursor: pointer; 253 | border-radius: 5px; 254 | } 255 | #copy-button:hover { 256 | color: rgb(164, 251, 173); 257 | } 258 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | Capstone Generator 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 30 |
31 |
32 |
33 |

Capstone Title Generator

34 |

This capstone title generator was created by Carl Andrew Castanas. This mini project was designed for students who are having difficulty coming up with a unique capstone title. This capstone title generator will help you create the greatest capstone title while reducing your stress.

35 | Do you need a tutor? 36 | Join our Community 37 |
38 |
39 |
40 | 47 | 48 | 49 |
50 | Share 51 |
52 |
53 | 54 |
55 |

This is the generated text.

56 | 57 |
58 | 59 | 60 | 61 | 62 | 63 |
64 |
65 |
    66 |
  • 67 |
  • 68 |
69 |
70 |
71 |
72 |
73 |
74 | 75 | 76 | 96 | 97 | 98 |
99 | 100 | 101 | 137 | 138 | 139 | 141 | 142 | 143 | 144 | 145 | -------------------------------------------------------------------------------- /script.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function() { 2 | $("#next-quote").on("click", function(e) { 3 | e.preventDefault(); 4 | 5 | var randomQuoteNumber = getRandomQuoteNumber(); 6 | updateQuote(randomQuoteNumber); 7 | }); 8 | 9 | var q = location.search.split("?q=")[1]; 10 | 11 | if (q >= 0 && q < quotes.length) { 12 | updateQuote(q); 13 | } else { 14 | $("#next-quote").click(); 15 | } 16 | }); 17 | 18 | $(document).ready(function() { 19 | $(".menu-toggle").click(function() { 20 | $(".nav-links").slideToggle(400); 21 | }); 22 | 23 | // Show/hide dropdown menu on mobile 24 | $(".dropdown > a").click(function(e) { 25 | e.preventDefault(); 26 | $(this).siblings(".dropdown-content").slideToggle(400); 27 | }); 28 | 29 | // Close dropdown menu when clicking outside 30 | $(document).on("click", function(event) { 31 | if (!$(event.target).closest(".dropdown").length) { 32 | $(".dropdown-content").slideUp(400); 33 | } 34 | }); 35 | }); 36 | 37 | // Function to copy the dynamically generated quote 38 | function copyQuoteToClipboard() { 39 | var quoteText = document.getElementById("quote").innerText; 40 | 41 | // Create a temporary textarea element 42 | var tempTextArea = document.createElement("textarea"); 43 | tempTextArea.value = quoteText; 44 | 45 | // Append the textarea element to the body 46 | document.body.appendChild(tempTextArea); 47 | 48 | // Select the text in the textarea 49 | tempTextArea.select(); 50 | 51 | // Execute the copy command 52 | document.execCommand("copy"); 53 | 54 | // Remove the textarea element 55 | document.body.removeChild(tempTextArea); 56 | } 57 | 58 | // Function to handle mouseenter event and copy the quote 59 | function handleMouseEnter() { 60 | // Call the function to copy the quote to clipboard 61 | copyQuoteToClipboard(); 62 | } 63 | 64 | // Attach the event listener after the quote is generated 65 | document.addEventListener("DOMContentLoaded", function() { 66 | document.getElementById("quote-box").addEventListener("mouseenter", handleMouseEnter); 67 | }); 68 | 69 | function updateQuote(quoteNumber) { 70 | var randomQuote = quotes[quoteNumber]; 71 | 72 | $("#quote").html(randomQuote.quote); 73 | $("#author").html(randomQuote.author); 74 | $("#quote-box").removeClass().addClass("animated bounceIn").one('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', function() { 75 | $(this).removeClass(); 76 | }); 77 | 78 | $("#share").attr("href", "https://twitter.com/intent/tweet?text=" + encodeURIComponent($("#hidden").html(randomQuote.quote).text()) + "\" carlcastanas" + quoteNumber); 79 | } 80 | 81 | function getRandomQuoteNumber() { 82 | return Math.floor(Math.random() * quotes.length); 83 | } 84 | 85 | document.getElementById('copy-button').addEventListener('click', function() { 86 | var quoteText = document.getElementById('quote').innerText; 87 | navigator.clipboard.writeText(quoteText).then(function() { 88 | console.log('Text copied to clipboard: ' + quoteText); 89 | // Display success message using SweetAlert 90 | Swal.fire({ 91 | icon: 'success', 92 | title: 'Text copied to clipboard!', 93 | text: quoteText 94 | }); 95 | }, function(err) { 96 | console.error('Unable to copy text to clipboard: ', err); 97 | // Display error message using SweetAlert 98 | Swal.fire({ 99 | icon: 'error', 100 | title: 'Unable to copy text to clipboard!', 101 | text: err 102 | }); 103 | }); 104 | }); 105 | document.getElementById('copy-button').addEventListener('click', function() { 106 | var quoteText = document.getElementById('quote').innerText; 107 | navigator.clipboard.writeText(quoteText).then(function() { 108 | console.log('Text copied to clipboard: ' + quoteText); 109 | // Display success message using SweetAlert 110 | Swal.fire({ 111 | icon: 'success', 112 | title: 'Text copied to clipboard!', 113 | text: quoteText, 114 | customClass: { 115 | popup: 'dark-mode' 116 | } 117 | }); 118 | }, function(err) { 119 | console.error('Unable to copy text to clipboard: ', err); 120 | // Display error message using SweetAlert 121 | Swal.fire({ 122 | icon: 'error', 123 | title: 'Unable to copy text to clipboard!', 124 | text: err, 125 | customClass: { 126 | popup: 'dark-mode' 127 | } 128 | }); 129 | }); 130 | }); 131 | 132 | 133 | 134 | 135 | var quotes = [{ 136 | "author": "Carl Andrew Castañas", 137 | "quote": "Online E-Learning System" 138 | }, 139 | { 140 | "author": "Carl Andrew Castañas", 141 | "quote": "Online Examination System" 142 | }, 143 | { 144 | "author": "Carl Andrew Castañas", 145 | "quote": "OJT Timesheet Monitoring System" 146 | }, 147 | { 148 | "author": "Carl Andrew Castañas", 149 | "quote": "Home Surveillance and Automation" 150 | }, 151 | { 152 | "author": "Carl Andrew Castañas", 153 | "quote": "iPhone SMS Notification Systems" 154 | }, 155 | { 156 | "author": "Carl Andrew Castañas", 157 | "quote": "Using GSM Technologies for Detecting Theft" 158 | }, 159 | { 160 | "author": "Carl Andrew Castañas", 161 | "quote": "POS Apps and Their Use" 162 | }, 163 | { 164 | "author": "Carl Andrew Castañas", 165 | "quote": "Business Use Cases for Accounting Apps" 166 | }, 167 | { 168 | "author": "Carl Andrew Castañas", 169 | "quote": "Time Tracking Solutions for Office Productivity" 170 | }, 171 | { 172 | "author": "Carl Andrew Castañas", 173 | "quote": "SMS Doorbell Notification Tools" 174 | }, 175 | { 176 | "author": "Carl Andrew Castañas", 177 | "quote": "Wireless Technologies for Surveillance" 178 | }, 179 | { 180 | "author": "Carl Andrew Castañas", 181 | "quote": "Online Learning Systems and Their Relevance" 182 | }, 183 | { 184 | "author": "Carl Andrew Castañas", 185 | "quote": "Online Apps For Business Management" 186 | }, 187 | { 188 | "author": "Carl Andrew Castañas", 189 | "quote": "Improving Nursing Education With a Healthcare System" 190 | }, 191 | { 192 | "author": "Carl Andrew Castañas", 193 | "quote": "Project Management Tracking Systems" 194 | }, 195 | { 196 | "author": "Carl Andrew Castañas", 197 | "quote": "Biometric Security Systems" 198 | }, 199 | { 200 | "author": "Carl Andrew Castañas", 201 | "quote": "Most Important Tools For Managing Data Security" 202 | }, 203 | { 204 | "author": "Carl Andrew Castañas", 205 | "quote": "Most Important Tools For Managing Data Security" 206 | }, 207 | { 208 | "author": "Carl Andrew Castañas", 209 | "quote": "How The Internet Works: The Basics" 210 | }, 211 | { 212 | "author": "Carl Andrew Castañas", 213 | "quote": "Introduction to Data Mining" 214 | }, 215 | { 216 | "author": "Carl Andrew Castañas", 217 | "quote": "Emergency Vehicle Notification Systems" 218 | }, 219 | { 220 | "author": "Carl Andrew Castañas", 221 | "quote": "Benefits of Data Mining" 222 | }, 223 | { 224 | "author": "Carl Andrew Castañas", 225 | "quote": "Student Tracking Performance" 226 | }, 227 | { 228 | "author": "Carl Andrew Castañas", 229 | "quote": "Library Information System" 230 | }, 231 | { 232 | "author": "Carl Andrew Castañas", 233 | "quote": "Student Information System" 234 | }, 235 | { 236 | "author": "Carl Andrew Castañas", 237 | "quote": "Student Handbook Application" 238 | }, 239 | { 240 | "author": "Carl Andrew Castañas", 241 | "quote": "Thesis and Capstone Archiving System" 242 | }, 243 | { 244 | "author": "Carl Andrew Castañas", 245 | "quote": "School Portal Application" 246 | }, 247 | { 248 | "author": "Carl Andrew Castañas", 249 | "quote": "School Events Attendance System" 250 | }, 251 | { 252 | "author": "Carl Andrew Castañas", 253 | "quote": "Grading System" 254 | }, 255 | { 256 | "author": "Carl Andrew Castañas", 257 | "quote": "Student Profile and Guidance Services with Decision Support" 258 | }, 259 | { 260 | "author": "Carl Andrew Castañas", 261 | "quote": "Faculty Evaluation System" 262 | }, 263 | { 264 | "author": "Carl Andrew Castañas", 265 | "quote": "Online School Documents Processing with Payment System" 266 | }, 267 | { 268 | "author": "Carl Andrew Castañas", 269 | "quote": "Class Scheduling System" 270 | }, 271 | { 272 | "author": "Carl Andrew Castañas", 273 | "quote": "Student Council Voting System" 274 | }, 275 | { 276 | "author": "Carl Andrew Castañas", 277 | "quote": "Android Based E-learning" 278 | }, 279 | { 280 | "author": "Carl Andrew Castañas", 281 | "quote": "OJT Records Monitoring System" 282 | }, 283 | { 284 | "author": "Carl Andrew Castañas", 285 | "quote": "Sales and Inventory System" 286 | }, 287 | { 288 | "author": "Carl Andrew Castañas", 289 | "quote": "Point of Sale Application" 290 | }, 291 | { 292 | "author": "Carl Andrew Castañas", 293 | "quote": "Boarding House Management System" 294 | }, 295 | { 296 | "author": "Carl Andrew Castañas", 297 | "quote": "COOP Management System" 298 | }, 299 | { 300 | "author": "Carl Andrew Castañas", 301 | "quote": "Insurance Management System" 302 | }, 303 | 304 | { 305 | "author": "Carl Andrew Castañas", 306 | "quote": "Beauty Parlor Management System" 307 | }, 308 | { 309 | "author": "Carl Andrew Castañas", 310 | "quote": "Daily Time Record and Payroll System with Barcode/Biometric" 311 | }, 312 | { 313 | "author": "Carl Andrew Castañas", 314 | "quote": "Budget Management System" 315 | }, 316 | { 317 | "author": "Carl Andrew Castañas", 318 | "quote": "Queuing System" 319 | }, 320 | { 321 | "author": "Carl Andrew Castañas", 322 | "quote": "Financial Management with SMS Notification" 323 | }, 324 | { 325 | "author": "Carl Andrew Castañas", 326 | "quote": "Procurement Management System" 327 | }, 328 | { 329 | "author": "Carl Andrew Castañas", 330 | "quote": "Financial Documents Archiving Management System" 331 | }, 332 | { 333 | "author": "Carl Andrew Castañas", 334 | "quote": "Teller’s Queuing System Using Barcode Technology" 335 | }, 336 | { 337 | "author": "Carl Andrew Castañas", 338 | "quote": "Service Marketplace System" 339 | }, 340 | { 341 | "author": "Carl Andrew Castañas", 342 | "quote": "Tailor Booking Management System" 343 | }, 344 | { 345 | "author": "Carl Andrew Castañas", 346 | "quote": "Expense Tracking and Monitoring System" 347 | }, 348 | { 349 | "author": "Carl Andrew Castañas", 350 | "quote": "Loan Transaction and Reservation with SMS" 351 | }, 352 | { 353 | "author": "Carl Andrew Castañas", 354 | "quote": "Accounting Information Management System" 355 | }, 356 | { 357 | "author": "Carl Andrew Castañas", 358 | "quote": "Food Order and Catering Services System" 359 | }, 360 | { 361 | "author": "Carl Andrew Castañas", 362 | "quote": "Online and SMS Based Salary Notification" 363 | }, 364 | { 365 | "author": "Carl Andrew Castañas", 366 | "quote": "Pharmacy Stocks Management" 367 | }, 368 | { 369 | "author": "Carl Andrew Castañas", 370 | "quote": "Laundry Booking System" 371 | }, 372 | { 373 | "author": "Carl Andrew Castañas", 374 | "quote": "Hotel Reservation Application" 375 | }, 376 | { 377 | "author": "Carl Andrew Castañas", 378 | "quote": "Tourism Management Database System" 379 | }, 380 | { 381 | "author": "Carl Andrew Castañas", 382 | "quote": "Management Information Systems for Tourism and Hospitality" 383 | }, 384 | { 385 | "author": "Carl Andrew Castañas", 386 | "quote": "Hotel And Restaurant Management And Monitoring System with SMS Support" 387 | }, 388 | { 389 | "author": "Carl Andrew Castañas", 390 | "quote": "Mobile Based Tourist Destination Information" 391 | }, 392 | { 393 | "author": "Carl Andrew Castañas", 394 | "quote": "Hotel Best Prices Mobile Application" 395 | }, 396 | { 397 | "author": "Carl Andrew Castañas", 398 | "quote": "Hospitality Information System" 399 | }, 400 | { 401 | "author": "Carl Andrew Castañas", 402 | "quote": "Cloud-Based Property and Hospitality Management" 403 | }, 404 | { 405 | "author": "Carl Andrew Castañas", 406 | "quote": "Hotel Booking App For Smart Travel" 407 | }, 408 | { 409 | "author": "Carl Andrew Castañas", 410 | "quote": "Point of Sale (PoS) System used in the Hotel Industry" 411 | }, 412 | { 413 | "author": "Carl Andrew Castañas", 414 | "quote": "BrowseHotel: Hotel Hopping using Mobile Devices" 415 | }, 416 | { 417 | "author": "Carl Andrew Castañas", 418 | "quote": "Transaction Processing System in Hotel and Restaurant" 419 | }, 420 | { 421 | "author": "Carl Andrew Castañas", 422 | "quote": "Travel Destination and Events Portal Capstone Project" 423 | }, 424 | { 425 | "author": "Carl Andrew Castañas", 426 | "quote": "Property Management Information System" 427 | }, 428 | { 429 | "author": "Carl Andrew Castañas", 430 | "quote": "Hotels and Vacation Rentals" 431 | }, 432 | { 433 | "author": "Carl Andrew Castañas", 434 | "quote": "Maternal Records Management" 435 | }, 436 | { 437 | "author": "Carl Andrew Castañas", 438 | "quote": "Smart Healthcare Support for Remote Patient Monitoring During COVID-19 Quarantine" 439 | }, 440 | { 441 | "author": "Carl Andrew Castañas", 442 | "quote": "X-Ray Results Image Archiving" 443 | }, 444 | { 445 | "author": "Carl Andrew Castañas", 446 | "quote": "First Aid Knowledge-Based Mobile Application" 447 | }, 448 | { 449 | "author": "Carl Andrew Castañas", 450 | "quote": "Hospital Management System" 451 | }, 452 | { 453 | "author": "Carl Andrew Castañas", 454 | "quote": "Hospital Resources and Room Utilization" 455 | }, 456 | { 457 | "author": "Carl Andrew Castañas", 458 | "quote": "Online Platform for COVID-19 Contact Tracing System" 459 | }, 460 | { 461 | "author": "Carl Andrew Castañas", 462 | "quote": "Nutrition Office Management Information System" 463 | }, 464 | { 465 | "author": "Carl Andrew Castañas", 466 | "quote": "Patient monitoring and tracking system of family planning in the community" 467 | }, 468 | { 469 | "author": "Carl Andrew Castañas", 470 | "quote": "Mask Wearing Monitoring Application" 471 | }, 472 | { 473 | "author": "Carl Andrew Castañas", 474 | "quote": "Mobile Based E-Prescribing App with Admin Panel" 475 | }, 476 | { 477 | "author": "Carl Andrew Castañas", 478 | "quote": "Clinic Management System" 479 | }, 480 | { 481 | "author": "Carl Andrew Castañas", 482 | "quote": "Online Platform for Patient Dental and Medical Records" 483 | }, 484 | { 485 | "author": "Carl Andrew Castañas", 486 | "quote": "Web-Based Psychopathology Diagnosis System" 487 | }, 488 | { 489 | "author": "Carl Andrew Castañas", 490 | "quote": "Health and Welfare Monitoring System" 491 | }, 492 | { 493 | "author": "Carl Andrew Castañas", 494 | "quote": "Mobile Based Common Ailment Guide with Admin Panel" 495 | }, 496 | { 497 | "author": "Carl Andrew Castañas", 498 | "quote": "Blood Bank Information System" 499 | }, 500 | { 501 | "author": "Carl Andrew Castañas", 502 | "quote": "Medicine Reminder Application" 503 | }, 504 | { 505 | "author": "Carl Andrew Castañas", 506 | "quote": "Web and Mobile Based Information of Herbal Plants and Medicinal Usages" 507 | }, 508 | { 509 | "author": "Carl Andrew Castañas", 510 | "quote": "Android Based Fitness and Exercise App" 511 | }, 512 | { 513 | "author": "Carl Andrew Castañas", 514 | "quote": "Gym Management System" 515 | }, 516 | { 517 | "author": "Carl Andrew Castañas", 518 | "quote": "Nutrition and Diet Mobile Application" 519 | }, 520 | { 521 | "author": "Carl Andrew Castañas", 522 | "quote": "Contact Tracing Application" 523 | }, 524 | { 525 | "author": "Carl Andrew Castañas", 526 | "quote": " COVID-19 Facilities Information System" 527 | }, 528 | { 529 | "author": "Carl Andrew Castañas", 530 | "quote": "Online Bus Ticket Reservation" 531 | }, 532 | { 533 | "author": "Carl Andrew Castañas", 534 | "quote": "Vehicle Rental System with Mobile App Support" 535 | }, 536 | { 537 | "author": "Carl Andrew Castañas", 538 | "quote": "Driving School Management System" 539 | }, 540 | { 541 | "author": "Carl Andrew Castañas", 542 | "quote": "Shipping Management System" 543 | }, 544 | { 545 | "author": "Carl Andrew Castañas", 546 | "quote": "Vehicle Insurance Information System" 547 | }, 548 | { 549 | "author": "Carl Andrew Castañas", 550 | "quote": "GPS based Vehicle Theft Detection System using GSM Technology" 551 | }, 552 | { 553 | "author": "Carl Andrew Castañas", 554 | "quote": "Bike Portal Information System" 555 | }, 556 | { 557 | "author": "Carl Andrew Castañas", 558 | "quote": "Vehicle Parking Management System" 559 | }, 560 | { 561 | "author": "Carl Andrew Castañas", 562 | "quote": "Vehicle Impoundment Information Management System" 563 | }, 564 | { 565 | "author": "Carl Andrew Castañas", 566 | "quote": "Vehicle Registration Portal" 567 | }, 568 | { 569 | "author": "Carl Andrew Castañas", 570 | "quote": "Vehicle Franchising and Drivers Offense Software" 571 | }, 572 | { 573 | "author": "Carl Andrew Castañas", 574 | "quote": "Traffic Management System" 575 | }, 576 | { 577 | "author": "Carl Andrew Castañas", 578 | "quote": "Mobile Based Airline Reservation System (Android and IOS)" 579 | }, 580 | { 581 | "author": "Carl Andrew Castañas", 582 | "quote": "Tricycle Driver Conduct Reporting Mobile Application" 583 | }, 584 | { 585 | "author": "Carl Andrew Castañas", 586 | "quote": "PUV Transportation Route and Mapping System" 587 | }, 588 | { 589 | "author": "Carl Andrew Castañas", 590 | "quote": "Driving School Management System" 591 | }, 592 | { 593 | "author": "Carl Andrew Castañas", 594 | "quote": "QR Code Fare Payment System" 595 | }, 596 | { 597 | "author": "Carl Andrew Castañas", 598 | "quote": "Courier Management System" 599 | }, 600 | { 601 | "author": "Carl Andrew Castañas", 602 | "quote": "Mobile Based Emergency Reporting with SMS Support" 603 | }, 604 | { 605 | "author": "Carl Andrew Castañas", 606 | "quote": "Interactive Flood Hazard Map" 607 | }, 608 | { 609 | "author": "Carl Andrew Castañas", 610 | "quote": "Web and Mobile Crime Reporting System" 611 | }, 612 | { 613 | "author": "Carl Andrew Castañas", 614 | "quote": "Weather Prediction App" 615 | }, 616 | { 617 | "author": "Carl Andrew Castañas", 618 | "quote": "Bantay Baha Alert System with SMS and Push Notification" 619 | }, 620 | { 621 | "author": "Carl Andrew Castañas", 622 | "quote": "Fire and Smoke Detection Application with SMS Notification" 623 | }, 624 | { 625 | "author": "Carl Andrew Castañas", 626 | "quote": "SMS-based Flood Monitoring System" 627 | }, 628 | { 629 | "author": "Carl Andrew Castañas", 630 | "quote": "Crisis Information Management Software" 631 | }, 632 | { 633 | "author": "Carl Andrew Castañas", 634 | "quote": "Data Platform for Emergency Response Management" 635 | }, 636 | { 637 | "author": "Carl Andrew Castañas", 638 | "quote": "Fire Extinguisher and Fire Fighting Drone" 639 | }, 640 | { 641 | "author": "Carl Andrew Castañas", 642 | "quote": "Disaster Management Information System" 643 | }, 644 | { 645 | "author": "Carl Andrew Castañas", 646 | "quote": "Crime Scene Management Mobile Application" 647 | }, 648 | { 649 | "author": "Carl Andrew Castañas", 650 | "quote": "Android Based Controlled Water Sprinkler" 651 | }, 652 | { 653 | "author": "Carl Andrew Castañas", 654 | "quote": "Online Platform for Plant Calendar Scheduling" 655 | }, 656 | { 657 | "author": "Carl Andrew Castañas", 658 | "quote": "MobileMangrove a Mobile-Based Mangrove Species Field Guide" 659 | }, 660 | { 661 | "author": "Carl Andrew Castañas", 662 | "quote": "Mobile Based Instructional Material for Agriculture" 663 | }, 664 | { 665 | "author": "Carl Andrew Castañas", 666 | "quote": "Soil Moisture Sensor using Micro Controller" 667 | }, 668 | { 669 | "author": "Carl Andrew Castañas", 670 | "quote": "E-commerce Platform for Farm Trading Activities" 671 | }, 672 | { 673 | "author": "Carl Andrew Castañas", 674 | "quote": "Web and Mobile Based Monitoring and Tracking of Fertilizer Delivery Products" 675 | }, 676 | { 677 | "author": "Carl Andrew Castañas", 678 | "quote": "Online Record Archiving of Soil Analysis Results" 679 | }, 680 | { 681 | "author": "Carl Andrew Castañas", 682 | "quote": "Drone Based Seeding Application Controlled by Mobile Devices" 683 | }, 684 | { 685 | "author": "Carl Andrew Castañas", 686 | "quote": "Dairy Farm Management System" 687 | }, 688 | { 689 | "author": "Carl Andrew Castañas", 690 | "quote": "Water Monitoring For Aquaculture with SMS Notification" 691 | }, 692 | { 693 | "author": "Carl Andrew Castañas", 694 | "quote": "Arduino Based Irrigation Device with Android Controlled Settings" 695 | }, 696 | { 697 | "author": "Carl Andrew Castañas", 698 | "quote": "Android Based Feeds Scheduler Dispensing Application" 699 | }, 700 | { 701 | "author": "Carl Andrew Castañas", 702 | "quote": "Mobile Based Farm Management Application" 703 | }, 704 | { 705 | "author": "Carl Andrew Castañas", 706 | "quote": "Electronic Watering System for Vegetable Nursery Garden" 707 | }, 708 | { 709 | "author": "Carl Andrew Castañas", 710 | "quote": "Solar-Powered Water Filtration System used in Farm Land" 711 | }, 712 | { 713 | "author": "Carl Andrew Castañas", 714 | "quote": "Curfew and Travel Pass Information System" 715 | }, 716 | { 717 | "author": "Carl Andrew Castañas", 718 | "quote": "Evacuation Center Management System" 719 | }, 720 | { 721 | "author": "Carl Andrew Castañas", 722 | "quote": "PWD Information System" 723 | }, 724 | { 725 | "author": "Carl Andrew Castañas", 726 | "quote": "Cloud-Based Business Permit Processing" 727 | }, 728 | { 729 | "author": "Carl Andrew Castañas", 730 | "quote": "Vaccine Distribution System" 731 | }, 732 | { 733 | "author": "Carl Andrew Castañas", 734 | "quote": "Senior Citizen Information System" 735 | }, 736 | { 737 | "author": "Carl Andrew Castañas", 738 | "quote": "DSWD Donation System" 739 | }, 740 | { 741 | "author": "Carl Andrew Castañas", 742 | "quote": "Information System for Bureau of Fire Protection" 743 | }, 744 | { 745 | "author": "Carl Andrew Castañas", 746 | "quote": "Poverty and Malnutrition Monitoring System" 747 | }, 748 | { 749 | "author": "Carl Andrew Castañas", 750 | "quote": "Project Monitoring and Evaluation System" 751 | }, 752 | { 753 | "author": "Carl Andrew Castañas", 754 | "quote": "BJMP’S Visitor’s Log Monitoring System" 755 | }, 756 | { 757 | "author": "Carl Andrew Castañas", 758 | "quote": "City Business Permit and Monitoring System with Decision Support" 759 | }, 760 | { 761 | "author": "Carl Andrew Castañas", 762 | "quote": "Barangay Records Management System" 763 | }, 764 | { 765 | "author": "Carl Andrew Castañas", 766 | "quote": "Housing Information Management with Mapping" 767 | }, 768 | { 769 | "author": "Carl Andrew Castañas", 770 | "quote": "Census Monitoring" 771 | }, 772 | { 773 | "author": "Carl Andrew Castañas", 774 | "quote": "Cedula Mobile: Cedula and Certification Request Mobile Application" 775 | }, 776 | { 777 | "author": "Carl Andrew Castañas", 778 | "quote": "Health Center Information Management System" 779 | }, 780 | { 781 | "author": "Carl Andrew Castañas", 782 | "quote": "" 783 | }, { 784 | "author": "Carl Andrew Castañas", 785 | "quote": "What are Data Breaches and How to Prevent Them" 786 | }, { 787 | "author": "Carl Andrew Castañas", 788 | "quote": "Improving Data Security" 789 | }, { 790 | "author": "Carl Andrew Castañas", 791 | "quote": "Benefits of Car Transportation Systems" 792 | }, { 793 | "author": "Carl Andrew Castañas", 794 | "quote": "Ecommerce Pricing Control Systems" 795 | }, { 796 | "author": "Carl Andrew Castañas", 797 | "quote": "Apps for Monitoring Temperature" 798 | }, { 799 | "author": "Carl Andrew Castañas", 800 | "quote": "Mobile Event Planners" 801 | }, { 802 | "author": "Carl Andrew Castañas", 803 | "quote": "Alarm SMS Notification Systems" 804 | }, { 805 | "author": "Carl Andrew Castañas", 806 | "quote": "Mobile Learning: How it Works" 807 | }, { 808 | "author": "Carl Andrew Castañas", 809 | "quote": "Project Management Systems" 810 | }, { 811 | "author": "Carl Andrew Castañas", 812 | "quote": "Machine Learning and Big Data" 813 | }, { 814 | "author": "Carl Andrew Castañas", 815 | "quote": "University Networks" 816 | }, { 817 | "author": "Carl Andrew Castañas", 818 | "quote": "ARPANET: How The Internet Started" 819 | }, { 820 | "author": "Carl Andrew Castañas", 821 | "quote": "Latest Ecommerce Technologies" 822 | }, { 823 | "author": "Carl Andrew Castañas", 824 | "quote": "Cre Principles of Cybersecurity" 825 | }, { 826 | "author": "Carl Andrew Castañas", 827 | "quote": "Information Technology in the 21st century" 828 | }, { 829 | "author": "Carl Andrew Castañas", 830 | "quote": "Java Programming: The Basics" 831 | }, { 832 | "author": "Carl Andrew Castañas", 833 | "quote": "Software Testing 101" 834 | }, { 835 | "author": "Carl Andrew Castañas", 836 | "quote": "Introduction to Software Quality Assurance" 837 | }, { 838 | "author": "Carl Andrew Castañas", 839 | "quote": "Employee Productivity Apps" 840 | }, { 841 | "author": "Carl Andrew Castañas", 842 | "quote": "Onboarding Systems and HR" 843 | }, { 844 | "author": "Carl Andrew Castañas", 845 | "quote": "Cloud-Based Software vs. On-Site Solutions" 846 | }, { 847 | "author": "Carl Andrew Castañas", 848 | "quote": "Benefits of Cloud Solutions" 849 | }, { 850 | "author": "Carl Andrew Castañas", 851 | "quote": "Hotel PMS Systems" 852 | }, { 853 | "author": "Carl Andrew Castañas", 854 | "quote": "Smart Technology in the Hotel Industry" 855 | }, { 856 | "author": "Carl Andrew Castañas", 857 | "quote": "IoT and Data" 858 | }, { 859 | "author": "Carl Andrew Castañas", 860 | "quote": "New IoT Gadgets" 861 | }, { 862 | "author": "Carl Andrew Castañas", 863 | "quote": "What is Artificial Intelligence" 864 | }, { 865 | "author": "Carl Andrew Castañas", 866 | "quote": "What is Machine Learning" 867 | }, { 868 | "author": "Carl Andrew Castañas", 869 | "quote": "Robotics Systems" 870 | }, { 871 | "author": "Carl Andrew Castañas", 872 | "quote": "Neural Networks" 873 | }, { 874 | "author": "Carl Andrew Castañas", 875 | "quote": "How Has Technology Changed Our Lives" 876 | }, { 877 | "author": "Carl Andrew Castañas", 878 | "quote": "Censorship on the Internet" 879 | }, { 880 | "author": "Carl Andrew Castañas", 881 | "quote": "Should the Internet be Free?" 882 | }, { 883 | "author": "Carl Andrew Castañas", 884 | "quote": "Email Marketing Tools" 885 | }, { 886 | "author": "Carl Andrew Castañas", 887 | "quote": "Web Scrapers" 888 | }, { 889 | "author": "Carl Andrew Castañas", 890 | "quote": "How Machine Learning Learns" 891 | }, { 892 | "author": "Carl Andrew Castañas", 893 | "quote": "How is AI Affecting us Today" 894 | }, { 895 | "author": "Carl Andrew Castañas", 896 | "quote": "New Tech Innovations for the Near Future" 897 | }, { 898 | "author": "Carl Andrew Castañas", 899 | "quote": "What is Virtual Reality" 900 | }, { 901 | "author": "Carl Andrew Castañas", 902 | "quote": "How are Clouds Technologies Used for Data Storage" 903 | }, { 904 | "author": "Carl Andrew Castañas", 905 | "quote": "Mobile Apps That Improve Education" 906 | }, { 907 | "author": "Carl Andrew Castañas", 908 | "quote": "How The Internet Will Develop" 909 | }, { 910 | "author": "Carl Andrew Castañas", 911 | "quote": "Software as a Service" 912 | }, { 913 | "author": "Carl Andrew Castañas", 914 | "quote": "Platform as a Service" 915 | }, { 916 | "author": "Carl Andrew Castañas", 917 | "quote": "Infrastructure as a Service" 918 | }, { 919 | "author": "Carl Andrew Castañas", 920 | "quote": "SaaS, PaaS, & IaaS: Main Differences" 921 | }, { 922 | "author": "Carl Andrew Castañas", 923 | "quote": "How Google Ranks Websites" 924 | }, { 925 | "author": "Carl Andrew Castañas", 926 | "quote": "3D Visualization in Architecture" 927 | }, { 928 | "author": "Carl Andrew Castañas", 929 | "quote": "Essential Skills 3D Artists Need" 930 | }, { 931 | "author": "Carl Andrew Castañas", 932 | "quote": "3D Rendering Tools" 933 | }, { 934 | "author": "Carl Andrew Castañas", 935 | "quote": "DMaaS - Data Mining as a Service" 936 | }, { 937 | "author": "Carl Andrew Castañas", 938 | "quote": "Augmented Reality" 939 | }, { 940 | "author": "Carl Andrew Castañas", 941 | "quote": "VR vs. AR: Differences Explained" 942 | }, { 943 | "author": "Carl Andrew Castañas", 944 | "quote": "Automation Systems in the 21st century" 945 | }, { 946 | "author": "Carl Andrew Castañas", 947 | "quote": "Data Management for Big Companies" 948 | }, { 949 | "author": "Carl Andrew Castañas", 950 | "quote": "Essential Data Analyst Skills" 951 | }, { 952 | "author": "Carl Andrew Castañas", 953 | "quote": "AI and Gamification" 954 | }, { 955 | "author": "Carl Andrew Castañas", 956 | "quote": "Data Mining for Employee Evaluation" 957 | }, { 958 | "author": "Carl Andrew Castañas", 959 | "quote": "Data Mining in Healthcare" 960 | }, { 961 | "author": "Carl Andrew Castañas", 962 | "quote": "Machine Learning for OTAs" 963 | }, { 964 | "author": "Carl Andrew Castañas", 965 | "quote": "Facebook and Data" 966 | }, { 967 | "author": "Carl Andrew Castañas", 968 | "quote": "Censorship on Social Media" 969 | }, { 970 | "author": "Carl Andrew Castañas", 971 | "quote": "How Social Media Filters out Content" 972 | }, { 973 | "author": "Carl Andrew Castañas", 974 | "quote": "Fingerprint Authentication" 975 | }, { 976 | "author": "Carl Andrew Castañas", 977 | "quote": "IoT Sensors" 978 | }, { 979 | "author": "Carl Andrew Castañas", 980 | "quote": "Web Ordering Systems" 981 | }, { 982 | "author": "Carl Andrew Castañas", 983 | "quote": "How to Prevent Phishing Attacks" 984 | }, { 985 | "author": "Carl Andrew Castañas", 986 | "quote": "Using Web Scraping for Research" 987 | }, { 988 | "author": "Carl Andrew Castañas", 989 | "quote": "Web Proxies" 990 | }, { 991 | "author": "Carl Andrew Castañas", 992 | "quote": "Virtual Private Networks" 993 | }, { 994 | "author": "Carl Andrew Castañas", 995 | "quote": "Differences Between VPNs and Proxies" 996 | }, { 997 | "author": "Carl Andrew Castañas", 998 | "quote": "How Proxies Enhances Web Scraping" 999 | }, { 1000 | "author": "Carl Andrew Castañas", 1001 | "quote": "Home Automation Systems" 1002 | }, { 1003 | "author": "Carl Andrew Castañas", 1004 | "quote": "Smart Homes" 1005 | }, { 1006 | "author": "Carl Andrew Castañas", 1007 | "quote": "Warehouse Management Systems" 1008 | }, { 1009 | "author": "Carl Andrew Castañas", 1010 | "quote": "How Voice Recognition Systems Work" 1011 | }, { 1012 | "author": "Carl Andrew Castañas", 1013 | "quote": "QR Code Check-ins" 1014 | }, { 1015 | "author": "Carl Andrew Castañas", 1016 | "quote": "Smart Systems in Cars" 1017 | }, { 1018 | "author": "Carl Andrew Castañas", 1019 | "quote": "Should Cars Have More Computers or Less?" 1020 | }, { 1021 | "author": "Carl Andrew Castañas", 1022 | "quote": "Solar Grass Cutters With Automation" 1023 | }, { 1024 | "author": "Carl Andrew Castañas", 1025 | "quote": "Voice Controlled Tools" 1026 | }, { 1027 | "author": "Carl Andrew Castañas", 1028 | "quote": "CRM Software" 1029 | }, { 1030 | "author": "Carl Andrew Castañas", 1031 | "quote": "Online Training Software Benefits" 1032 | }, { 1033 | "author": "Carl Andrew Castañas", 1034 | "quote": "ChatBots: Introduction" 1035 | }, { 1036 | "author": "Carl Andrew Castañas", 1037 | "quote": "Complex Chat Bots" 1038 | }, { 1039 | "author": "Carl Andrew Castañas", 1040 | "quote": "Using ML for Cybersecurity" 1041 | }, { 1042 | "author": "Carl Andrew Castañas", 1043 | "quote": "Machine LEarning in Ecommerce" 1044 | }, { 1045 | "author": "Carl Andrew Castañas", 1046 | "quote": "Elearning and Gamification" 1047 | }, { 1048 | "author": "Carl Andrew Castañas", 1049 | "quote": "How Games Have Improved Digital Technologies" 1050 | }, { 1051 | "author": "Carl Andrew Castañas", 1052 | "quote": "How Far Have Video Games Gone?" 1053 | }, { 1054 | "author": "Carl Andrew Castañas", 1055 | "quote": "Home Voice Assistants" 1056 | }, { 1057 | "author": "Carl Andrew Castañas", 1058 | "quote": "How Technology Helps Disabled People" 1059 | }, { 1060 | "author": "Carl Andrew Castañas", 1061 | "quote": "Apps for Child Monitoring" 1062 | }, { 1063 | "author": "Carl Andrew Castañas", 1064 | "quote": "Nutrition Tools" 1065 | }, { 1066 | "author": "Carl Andrew Castañas", 1067 | "quote": "Semantic Web & Big Data" 1068 | }, { 1069 | "author": "Carl Andrew Castañas", 1070 | "quote": "Autonomous Systems Today" 1071 | }, { 1072 | "author": "Carl Andrew Castañas", 1073 | "quote": "Is The Internet Helping us?" 1074 | }, { 1075 | "author": "Carl Andrew Castañas", 1076 | "quote": "Blockchain and Crypto" 1077 | }, { 1078 | "author": "Carl Andrew Castañas", 1079 | "quote": "How Bitcoin Works" 1080 | }, { 1081 | "author": "Carl Andrew Castañas", 1082 | "quote": "IoT and 5G" 1083 | }, { 1084 | "author": "Carl Andrew Castañas", 1085 | "quote": "Edge Computing Explained" 1086 | } 1087 | ] 1088 | -------------------------------------------------------------------------------- /assets/particle.js: -------------------------------------------------------------------------------- 1 | var pJS = function(tag_id, params){ 2 | 3 | var canvas_el = document.querySelector('#'+tag_id+' > .particles-js-canvas-el'); 4 | 5 | /* particles.js variables with default values */ 6 | this.pJS = { 7 | canvas: { 8 | el: canvas_el, 9 | w: canvas_el.offsetWidth, 10 | h: canvas_el.offsetHeight 11 | }, 12 | particles: { 13 | number: { 14 | value: 400, 15 | density: { 16 | enable: true, 17 | value_area: 800 18 | } 19 | }, 20 | color: { 21 | value: '#fff' 22 | }, 23 | shape: { 24 | type: 'circle', 25 | stroke: { 26 | width: 0, 27 | color: '#ff0000' 28 | }, 29 | polygon: { 30 | nb_sides: 5 31 | }, 32 | image: { 33 | src: '', 34 | width: 100, 35 | height: 100 36 | } 37 | }, 38 | opacity: { 39 | value: 1, 40 | random: false, 41 | anim: { 42 | enable: false, 43 | speed: 2, 44 | opacity_min: 0, 45 | sync: false 46 | } 47 | }, 48 | size: { 49 | value: 20, 50 | random: false, 51 | anim: { 52 | enable: false, 53 | speed: 20, 54 | size_min: 0, 55 | sync: false 56 | } 57 | }, 58 | line_linked: { 59 | enable: true, 60 | distance: 100, 61 | color: '#fff', 62 | opacity: 1, 63 | width: 1 64 | }, 65 | move: { 66 | enable: true, 67 | speed: 2, 68 | direction: 'none', 69 | random: false, 70 | straight: false, 71 | out_mode: 'out', 72 | bounce: false, 73 | attract: { 74 | enable: false, 75 | rotateX: 3000, 76 | rotateY: 3000 77 | } 78 | }, 79 | array: [] 80 | }, 81 | interactivity: { 82 | detect_on: 'canvas', 83 | events: { 84 | onhover: { 85 | enable: true, 86 | mode: 'grab' 87 | }, 88 | onclick: { 89 | enable: true, 90 | mode: 'push' 91 | }, 92 | resize: true 93 | }, 94 | modes: { 95 | grab:{ 96 | distance: 100, 97 | line_linked:{ 98 | opacity: 1 99 | } 100 | }, 101 | bubble:{ 102 | distance: 200, 103 | size: 80, 104 | duration: 0.4 105 | }, 106 | repulse:{ 107 | distance: 200, 108 | duration: 0.4 109 | }, 110 | push:{ 111 | particles_nb: 4 112 | }, 113 | remove:{ 114 | particles_nb: 2 115 | } 116 | }, 117 | mouse:{} 118 | }, 119 | retina_detect: false, 120 | fn: { 121 | interact: {}, 122 | modes: {}, 123 | vendors:{} 124 | }, 125 | tmp: {} 126 | }; 127 | 128 | var pJS = this.pJS; 129 | 130 | /* params settings */ 131 | if(params){ 132 | Object.deepExtend(pJS, params); 133 | } 134 | 135 | pJS.tmp.obj = { 136 | size_value: pJS.particles.size.value, 137 | size_anim_speed: pJS.particles.size.anim.speed, 138 | move_speed: pJS.particles.move.speed, 139 | line_linked_distance: pJS.particles.line_linked.distance, 140 | line_linked_width: pJS.particles.line_linked.width, 141 | mode_grab_distance: pJS.interactivity.modes.grab.distance, 142 | mode_bubble_distance: pJS.interactivity.modes.bubble.distance, 143 | mode_bubble_size: pJS.interactivity.modes.bubble.size, 144 | mode_repulse_distance: pJS.interactivity.modes.repulse.distance 145 | }; 146 | 147 | 148 | pJS.fn.retinaInit = function(){ 149 | 150 | if(pJS.retina_detect && window.devicePixelRatio > 1){ 151 | pJS.canvas.pxratio = window.devicePixelRatio; 152 | pJS.tmp.retina = true; 153 | } 154 | else{ 155 | pJS.canvas.pxratio = 1; 156 | pJS.tmp.retina = false; 157 | } 158 | 159 | pJS.canvas.w = pJS.canvas.el.offsetWidth * pJS.canvas.pxratio; 160 | pJS.canvas.h = pJS.canvas.el.offsetHeight * pJS.canvas.pxratio; 161 | 162 | pJS.particles.size.value = pJS.tmp.obj.size_value * pJS.canvas.pxratio; 163 | pJS.particles.size.anim.speed = pJS.tmp.obj.size_anim_speed * pJS.canvas.pxratio; 164 | pJS.particles.move.speed = pJS.tmp.obj.move_speed * pJS.canvas.pxratio; 165 | pJS.particles.line_linked.distance = pJS.tmp.obj.line_linked_distance * pJS.canvas.pxratio; 166 | pJS.interactivity.modes.grab.distance = pJS.tmp.obj.mode_grab_distance * pJS.canvas.pxratio; 167 | pJS.interactivity.modes.bubble.distance = pJS.tmp.obj.mode_bubble_distance * pJS.canvas.pxratio; 168 | pJS.particles.line_linked.width = pJS.tmp.obj.line_linked_width * pJS.canvas.pxratio; 169 | pJS.interactivity.modes.bubble.size = pJS.tmp.obj.mode_bubble_size * pJS.canvas.pxratio; 170 | pJS.interactivity.modes.repulse.distance = pJS.tmp.obj.mode_repulse_distance * pJS.canvas.pxratio; 171 | 172 | }; 173 | 174 | 175 | 176 | /* ---------- pJS functions - canvas ------------ */ 177 | 178 | pJS.fn.canvasInit = function(){ 179 | pJS.canvas.ctx = pJS.canvas.el.getContext('2d'); 180 | }; 181 | 182 | pJS.fn.canvasSize = function(){ 183 | 184 | pJS.canvas.el.width = pJS.canvas.w; 185 | pJS.canvas.el.height = pJS.canvas.h; 186 | 187 | if(pJS && pJS.interactivity.events.resize){ 188 | 189 | window.addEventListener('resize', function(){ 190 | 191 | pJS.canvas.w = pJS.canvas.el.offsetWidth; 192 | pJS.canvas.h = pJS.canvas.el.offsetHeight; 193 | 194 | /* resize canvas */ 195 | if(pJS.tmp.retina){ 196 | pJS.canvas.w *= pJS.canvas.pxratio; 197 | pJS.canvas.h *= pJS.canvas.pxratio; 198 | } 199 | 200 | pJS.canvas.el.width = pJS.canvas.w; 201 | pJS.canvas.el.height = pJS.canvas.h; 202 | 203 | /* repaint canvas on anim disabled */ 204 | if(!pJS.particles.move.enable){ 205 | pJS.fn.particlesEmpty(); 206 | pJS.fn.particlesCreate(); 207 | pJS.fn.particlesDraw(); 208 | pJS.fn.vendors.densityAutoParticles(); 209 | } 210 | 211 | /* density particles enabled */ 212 | pJS.fn.vendors.densityAutoParticles(); 213 | 214 | }); 215 | 216 | } 217 | 218 | }; 219 | 220 | 221 | pJS.fn.canvasPaint = function(){ 222 | pJS.canvas.ctx.fillRect(0, 0, pJS.canvas.w, pJS.canvas.h); 223 | }; 224 | 225 | pJS.fn.canvasClear = function(){ 226 | pJS.canvas.ctx.clearRect(0, 0, pJS.canvas.w, pJS.canvas.h); 227 | }; 228 | 229 | 230 | /* --------- pJS functions - particles ----------- */ 231 | 232 | pJS.fn.particle = function(color, opacity, position){ 233 | 234 | /* size */ 235 | this.radius = (pJS.particles.size.random ? Math.random() : 1) * pJS.particles.size.value; 236 | if(pJS.particles.size.anim.enable){ 237 | this.size_status = false; 238 | this.vs = pJS.particles.size.anim.speed / 100; 239 | if(!pJS.particles.size.anim.sync){ 240 | this.vs = this.vs * Math.random(); 241 | } 242 | } 243 | 244 | /* position */ 245 | this.x = position ? position.x : Math.random() * pJS.canvas.w; 246 | this.y = position ? position.y : Math.random() * pJS.canvas.h; 247 | 248 | /* check position - into the canvas */ 249 | if(this.x > pJS.canvas.w - this.radius*2) this.x = this.x - this.radius; 250 | else if(this.x < this.radius*2) this.x = this.x + this.radius; 251 | if(this.y > pJS.canvas.h - this.radius*2) this.y = this.y - this.radius; 252 | else if(this.y < this.radius*2) this.y = this.y + this.radius; 253 | 254 | /* check position - avoid overlap */ 255 | if(pJS.particles.move.bounce){ 256 | pJS.fn.vendors.checkOverlap(this, position); 257 | } 258 | 259 | /* color */ 260 | this.color = {}; 261 | if(typeof(color.value) == 'object'){ 262 | 263 | if(color.value instanceof Array){ 264 | var color_selected = color.value[Math.floor(Math.random() * pJS.particles.color.value.length)]; 265 | this.color.rgb = hexToRgb(color_selected); 266 | }else{ 267 | if(color.value.r != undefined && color.value.g != undefined && color.value.b != undefined){ 268 | this.color.rgb = { 269 | r: color.value.r, 270 | g: color.value.g, 271 | b: color.value.b 272 | } 273 | } 274 | if(color.value.h != undefined && color.value.s != undefined && color.value.l != undefined){ 275 | this.color.hsl = { 276 | h: color.value.h, 277 | s: color.value.s, 278 | l: color.value.l 279 | } 280 | } 281 | } 282 | 283 | } 284 | else if(color.value == 'random'){ 285 | this.color.rgb = { 286 | r: (Math.floor(Math.random() * (255 - 0 + 1)) + 0), 287 | g: (Math.floor(Math.random() * (255 - 0 + 1)) + 0), 288 | b: (Math.floor(Math.random() * (255 - 0 + 1)) + 0) 289 | } 290 | } 291 | else if(typeof(color.value) == 'string'){ 292 | this.color = color; 293 | this.color.rgb = hexToRgb(this.color.value); 294 | } 295 | 296 | /* opacity */ 297 | this.opacity = (pJS.particles.opacity.random ? Math.random() : 1) * pJS.particles.opacity.value; 298 | if(pJS.particles.opacity.anim.enable){ 299 | this.opacity_status = false; 300 | this.vo = pJS.particles.opacity.anim.speed / 100; 301 | if(!pJS.particles.opacity.anim.sync){ 302 | this.vo = this.vo * Math.random(); 303 | } 304 | } 305 | 306 | /* animation - velocity for speed */ 307 | var velbase = {} 308 | switch(pJS.particles.move.direction){ 309 | case 'top': 310 | velbase = { x:0, y:-1 }; 311 | break; 312 | case 'top-right': 313 | velbase = { x:0.5, y:-0.5 }; 314 | break; 315 | case 'right': 316 | velbase = { x:1, y:-0 }; 317 | break; 318 | case 'bottom-right': 319 | velbase = { x:0.5, y:0.5 }; 320 | break; 321 | case 'bottom': 322 | velbase = { x:0, y:1 }; 323 | break; 324 | case 'bottom-left': 325 | velbase = { x:-0.5, y:1 }; 326 | break; 327 | case 'left': 328 | velbase = { x:-1, y:0 }; 329 | break; 330 | case 'top-left': 331 | velbase = { x:-0.5, y:-0.5 }; 332 | break; 333 | default: 334 | velbase = { x:0, y:0 }; 335 | break; 336 | } 337 | 338 | if(pJS.particles.move.straight){ 339 | this.vx = velbase.x; 340 | this.vy = velbase.y; 341 | if(pJS.particles.move.random){ 342 | this.vx = this.vx * (Math.random()); 343 | this.vy = this.vy * (Math.random()); 344 | } 345 | }else{ 346 | this.vx = velbase.x + Math.random()-0.5; 347 | this.vy = velbase.y + Math.random()-0.5; 348 | } 349 | 350 | // var theta = 2.0 * Math.PI * Math.random(); 351 | // this.vx = Math.cos(theta); 352 | // this.vy = Math.sin(theta); 353 | 354 | this.vx_i = this.vx; 355 | this.vy_i = this.vy; 356 | 357 | 358 | 359 | /* if shape is image */ 360 | 361 | var shape_type = pJS.particles.shape.type; 362 | if(typeof(shape_type) == 'object'){ 363 | if(shape_type instanceof Array){ 364 | var shape_selected = shape_type[Math.floor(Math.random() * shape_type.length)]; 365 | this.shape = shape_selected; 366 | } 367 | }else{ 368 | this.shape = shape_type; 369 | } 370 | 371 | if(this.shape == 'image'){ 372 | var sh = pJS.particles.shape; 373 | this.img = { 374 | src: sh.image.src, 375 | ratio: sh.image.width / sh.image.height 376 | } 377 | if(!this.img.ratio) this.img.ratio = 1; 378 | if(pJS.tmp.img_type == 'svg' && pJS.tmp.source_svg != undefined){ 379 | pJS.fn.vendors.createSvgImg(this); 380 | if(pJS.tmp.pushing){ 381 | this.img.loaded = false; 382 | } 383 | } 384 | } 385 | 386 | 387 | 388 | }; 389 | 390 | 391 | pJS.fn.particle.prototype.draw = function() { 392 | 393 | var p = this; 394 | 395 | if(p.radius_bubble != undefined){ 396 | var radius = p.radius_bubble; 397 | }else{ 398 | var radius = p.radius; 399 | } 400 | 401 | if(p.opacity_bubble != undefined){ 402 | var opacity = p.opacity_bubble; 403 | }else{ 404 | var opacity = p.opacity; 405 | } 406 | 407 | if(p.color.rgb){ 408 | var color_value = 'rgba('+p.color.rgb.r+','+p.color.rgb.g+','+p.color.rgb.b+','+opacity+')'; 409 | }else{ 410 | var color_value = 'hsla('+p.color.hsl.h+','+p.color.hsl.s+'%,'+p.color.hsl.l+'%,'+opacity+')'; 411 | } 412 | 413 | pJS.canvas.ctx.fillStyle = color_value; 414 | pJS.canvas.ctx.beginPath(); 415 | 416 | switch(p.shape){ 417 | 418 | case 'circle': 419 | pJS.canvas.ctx.arc(p.x, p.y, radius, 0, Math.PI * 2, false); 420 | break; 421 | 422 | case 'edge': 423 | pJS.canvas.ctx.rect(p.x-radius, p.y-radius, radius*2, radius*2); 424 | break; 425 | 426 | case 'triangle': 427 | pJS.fn.vendors.drawShape(pJS.canvas.ctx, p.x-radius, p.y+radius / 1.66, radius*2, 3, 2); 428 | break; 429 | 430 | case 'polygon': 431 | pJS.fn.vendors.drawShape( 432 | pJS.canvas.ctx, 433 | p.x - radius / (pJS.particles.shape.polygon.nb_sides/3.5), // startX 434 | p.y - radius / (2.66/3.5), // startY 435 | radius*2.66 / (pJS.particles.shape.polygon.nb_sides/3), // sideLength 436 | pJS.particles.shape.polygon.nb_sides, // sideCountNumerator 437 | 1 // sideCountDenominator 438 | ); 439 | break; 440 | 441 | case 'star': 442 | pJS.fn.vendors.drawShape( 443 | pJS.canvas.ctx, 444 | p.x - radius*2 / (pJS.particles.shape.polygon.nb_sides/4), // startX 445 | p.y - radius / (2*2.66/3.5), // startY 446 | radius*2*2.66 / (pJS.particles.shape.polygon.nb_sides/3), // sideLength 447 | pJS.particles.shape.polygon.nb_sides, // sideCountNumerator 448 | 2 // sideCountDenominator 449 | ); 450 | break; 451 | 452 | case 'image': 453 | 454 | function draw(){ 455 | pJS.canvas.ctx.drawImage( 456 | img_obj, 457 | p.x-radius, 458 | p.y-radius, 459 | radius*2, 460 | radius*2 / p.img.ratio 461 | ); 462 | } 463 | 464 | if(pJS.tmp.img_type == 'svg'){ 465 | var img_obj = p.img.obj; 466 | }else{ 467 | var img_obj = pJS.tmp.img_obj; 468 | } 469 | 470 | if(img_obj){ 471 | draw(); 472 | } 473 | 474 | break; 475 | 476 | } 477 | 478 | pJS.canvas.ctx.closePath(); 479 | 480 | if(pJS.particles.shape.stroke.width > 0){ 481 | pJS.canvas.ctx.strokeStyle = pJS.particles.shape.stroke.color; 482 | pJS.canvas.ctx.lineWidth = pJS.particles.shape.stroke.width; 483 | pJS.canvas.ctx.stroke(); 484 | } 485 | 486 | pJS.canvas.ctx.fill(); 487 | 488 | }; 489 | 490 | 491 | pJS.fn.particlesCreate = function(){ 492 | for(var i = 0; i < pJS.particles.number.value; i++) { 493 | pJS.particles.array.push(new pJS.fn.particle(pJS.particles.color, pJS.particles.opacity.value)); 494 | } 495 | }; 496 | 497 | pJS.fn.particlesUpdate = function(){ 498 | 499 | for(var i = 0; i < pJS.particles.array.length; i++){ 500 | 501 | /* the particle */ 502 | var p = pJS.particles.array[i]; 503 | 504 | // var d = ( dx = pJS.interactivity.mouse.click_pos_x - p.x ) * dx + ( dy = pJS.interactivity.mouse.click_pos_y - p.y ) * dy; 505 | // var f = -BANG_SIZE / d; 506 | // if ( d < BANG_SIZE ) { 507 | // var t = Math.atan2( dy, dx ); 508 | // p.vx = f * Math.cos(t); 509 | // p.vy = f * Math.sin(t); 510 | // } 511 | 512 | /* move the particle */ 513 | if(pJS.particles.move.enable){ 514 | var ms = pJS.particles.move.speed/2; 515 | p.x += p.vx * ms; 516 | p.y += p.vy * ms; 517 | } 518 | 519 | /* change opacity status */ 520 | if(pJS.particles.opacity.anim.enable) { 521 | if(p.opacity_status == true) { 522 | if(p.opacity >= pJS.particles.opacity.value) p.opacity_status = false; 523 | p.opacity += p.vo; 524 | }else { 525 | if(p.opacity <= pJS.particles.opacity.anim.opacity_min) p.opacity_status = true; 526 | p.opacity -= p.vo; 527 | } 528 | if(p.opacity < 0) p.opacity = 0; 529 | } 530 | 531 | /* change size */ 532 | if(pJS.particles.size.anim.enable){ 533 | if(p.size_status == true){ 534 | if(p.radius >= pJS.particles.size.value) p.size_status = false; 535 | p.radius += p.vs; 536 | }else{ 537 | if(p.radius <= pJS.particles.size.anim.size_min) p.size_status = true; 538 | p.radius -= p.vs; 539 | } 540 | if(p.radius < 0) p.radius = 0; 541 | } 542 | 543 | /* change particle position if it is out of canvas */ 544 | if(pJS.particles.move.out_mode == 'bounce'){ 545 | var new_pos = { 546 | x_left: p.radius, 547 | x_right: pJS.canvas.w, 548 | y_top: p.radius, 549 | y_bottom: pJS.canvas.h 550 | } 551 | }else{ 552 | var new_pos = { 553 | x_left: -p.radius, 554 | x_right: pJS.canvas.w + p.radius, 555 | y_top: -p.radius, 556 | y_bottom: pJS.canvas.h + p.radius 557 | } 558 | } 559 | 560 | if(p.x - p.radius > pJS.canvas.w){ 561 | p.x = new_pos.x_left; 562 | p.y = Math.random() * pJS.canvas.h; 563 | } 564 | else if(p.x + p.radius < 0){ 565 | p.x = new_pos.x_right; 566 | p.y = Math.random() * pJS.canvas.h; 567 | } 568 | if(p.y - p.radius > pJS.canvas.h){ 569 | p.y = new_pos.y_top; 570 | p.x = Math.random() * pJS.canvas.w; 571 | } 572 | else if(p.y + p.radius < 0){ 573 | p.y = new_pos.y_bottom; 574 | p.x = Math.random() * pJS.canvas.w; 575 | } 576 | 577 | /* out of canvas modes */ 578 | switch(pJS.particles.move.out_mode){ 579 | case 'bounce': 580 | if (p.x + p.radius > pJS.canvas.w) p.vx = -p.vx; 581 | else if (p.x - p.radius < 0) p.vx = -p.vx; 582 | if (p.y + p.radius > pJS.canvas.h) p.vy = -p.vy; 583 | else if (p.y - p.radius < 0) p.vy = -p.vy; 584 | break; 585 | } 586 | 587 | /* events */ 588 | if(isInArray('grab', pJS.interactivity.events.onhover.mode)){ 589 | pJS.fn.modes.grabParticle(p); 590 | } 591 | 592 | if(isInArray('bubble', pJS.interactivity.events.onhover.mode) || isInArray('bubble', pJS.interactivity.events.onclick.mode)){ 593 | pJS.fn.modes.bubbleParticle(p); 594 | } 595 | 596 | if(isInArray('repulse', pJS.interactivity.events.onhover.mode) || isInArray('repulse', pJS.interactivity.events.onclick.mode)){ 597 | pJS.fn.modes.repulseParticle(p); 598 | } 599 | 600 | /* interaction auto between particles */ 601 | if(pJS.particles.line_linked.enable || pJS.particles.move.attract.enable){ 602 | for(var j = i + 1; j < pJS.particles.array.length; j++){ 603 | var p2 = pJS.particles.array[j]; 604 | 605 | /* link particles */ 606 | if(pJS.particles.line_linked.enable){ 607 | pJS.fn.interact.linkParticles(p,p2); 608 | } 609 | 610 | /* attract particles */ 611 | if(pJS.particles.move.attract.enable){ 612 | pJS.fn.interact.attractParticles(p,p2); 613 | } 614 | 615 | /* bounce particles */ 616 | if(pJS.particles.move.bounce){ 617 | pJS.fn.interact.bounceParticles(p,p2); 618 | } 619 | 620 | } 621 | } 622 | 623 | 624 | } 625 | 626 | }; 627 | 628 | pJS.fn.particlesDraw = function(){ 629 | 630 | /* clear canvas */ 631 | pJS.canvas.ctx.clearRect(0, 0, pJS.canvas.w, pJS.canvas.h); 632 | 633 | /* update each particles param */ 634 | pJS.fn.particlesUpdate(); 635 | 636 | /* draw each particle */ 637 | for(var i = 0; i < pJS.particles.array.length; i++){ 638 | var p = pJS.particles.array[i]; 639 | p.draw(); 640 | } 641 | 642 | }; 643 | 644 | pJS.fn.particlesEmpty = function(){ 645 | pJS.particles.array = []; 646 | }; 647 | 648 | pJS.fn.particlesRefresh = function(){ 649 | 650 | /* init all */ 651 | cancelRequestAnimFrame(pJS.fn.checkAnimFrame); 652 | cancelRequestAnimFrame(pJS.fn.drawAnimFrame); 653 | pJS.tmp.source_svg = undefined; 654 | pJS.tmp.img_obj = undefined; 655 | pJS.tmp.count_svg = 0; 656 | pJS.fn.particlesEmpty(); 657 | pJS.fn.canvasClear(); 658 | 659 | /* restart */ 660 | pJS.fn.vendors.start(); 661 | 662 | }; 663 | 664 | 665 | /* ---------- pJS functions - particles interaction ------------ */ 666 | 667 | pJS.fn.interact.linkParticles = function(p1, p2){ 668 | 669 | var dx = p1.x - p2.x, 670 | dy = p1.y - p2.y, 671 | dist = Math.sqrt(dx*dx + dy*dy); 672 | 673 | /* draw a line between p1 and p2 if the distance between them is under the config distance */ 674 | if(dist <= pJS.particles.line_linked.distance){ 675 | 676 | var opacity_line = pJS.particles.line_linked.opacity - (dist / (1/pJS.particles.line_linked.opacity)) / pJS.particles.line_linked.distance; 677 | 678 | if(opacity_line > 0){ 679 | 680 | /* style */ 681 | var color_line = pJS.particles.line_linked.color_rgb_line; 682 | pJS.canvas.ctx.strokeStyle = 'rgba('+color_line.r+','+color_line.g+','+color_line.b+','+opacity_line+')'; 683 | pJS.canvas.ctx.lineWidth = pJS.particles.line_linked.width; 684 | //pJS.canvas.ctx.lineCap = 'round'; /* performance issue */ 685 | 686 | /* path */ 687 | pJS.canvas.ctx.beginPath(); 688 | pJS.canvas.ctx.moveTo(p1.x, p1.y); 689 | pJS.canvas.ctx.lineTo(p2.x, p2.y); 690 | pJS.canvas.ctx.stroke(); 691 | pJS.canvas.ctx.closePath(); 692 | 693 | } 694 | 695 | } 696 | 697 | }; 698 | 699 | 700 | pJS.fn.interact.attractParticles = function(p1, p2){ 701 | 702 | /* condensed particles */ 703 | var dx = p1.x - p2.x, 704 | dy = p1.y - p2.y, 705 | dist = Math.sqrt(dx*dx + dy*dy); 706 | 707 | if(dist <= pJS.particles.line_linked.distance){ 708 | 709 | var ax = dx/(pJS.particles.move.attract.rotateX*1000), 710 | ay = dy/(pJS.particles.move.attract.rotateY*1000); 711 | 712 | p1.vx -= ax; 713 | p1.vy -= ay; 714 | 715 | p2.vx += ax; 716 | p2.vy += ay; 717 | 718 | } 719 | 720 | 721 | } 722 | 723 | 724 | pJS.fn.interact.bounceParticles = function(p1, p2){ 725 | 726 | var dx = p1.x - p2.x, 727 | dy = p1.y - p2.y, 728 | dist = Math.sqrt(dx*dx + dy*dy), 729 | dist_p = p1.radius+p2.radius; 730 | 731 | if(dist <= dist_p){ 732 | p1.vx = -p1.vx; 733 | p1.vy = -p1.vy; 734 | 735 | p2.vx = -p2.vx; 736 | p2.vy = -p2.vy; 737 | } 738 | 739 | } 740 | 741 | 742 | /* ---------- pJS functions - modes events ------------ */ 743 | 744 | pJS.fn.modes.pushParticles = function(nb, pos){ 745 | 746 | pJS.tmp.pushing = true; 747 | 748 | for(var i = 0; i < nb; i++){ 749 | pJS.particles.array.push( 750 | new pJS.fn.particle( 751 | pJS.particles.color, 752 | pJS.particles.opacity.value, 753 | { 754 | 'x': pos ? pos.pos_x : Math.random() * pJS.canvas.w, 755 | 'y': pos ? pos.pos_y : Math.random() * pJS.canvas.h 756 | } 757 | ) 758 | ) 759 | if(i == nb-1){ 760 | if(!pJS.particles.move.enable){ 761 | pJS.fn.particlesDraw(); 762 | } 763 | pJS.tmp.pushing = false; 764 | } 765 | } 766 | 767 | }; 768 | 769 | 770 | pJS.fn.modes.removeParticles = function(nb){ 771 | 772 | pJS.particles.array.splice(0, nb); 773 | if(!pJS.particles.move.enable){ 774 | pJS.fn.particlesDraw(); 775 | } 776 | 777 | }; 778 | 779 | 780 | pJS.fn.modes.bubbleParticle = function(p){ 781 | 782 | /* on hover event */ 783 | if(pJS.interactivity.events.onhover.enable && isInArray('bubble', pJS.interactivity.events.onhover.mode)){ 784 | 785 | var dx_mouse = p.x - pJS.interactivity.mouse.pos_x, 786 | dy_mouse = p.y - pJS.interactivity.mouse.pos_y, 787 | dist_mouse = Math.sqrt(dx_mouse*dx_mouse + dy_mouse*dy_mouse), 788 | ratio = 1 - dist_mouse / pJS.interactivity.modes.bubble.distance; 789 | 790 | function init(){ 791 | p.opacity_bubble = p.opacity; 792 | p.radius_bubble = p.radius; 793 | } 794 | 795 | /* mousemove - check ratio */ 796 | if(dist_mouse <= pJS.interactivity.modes.bubble.distance){ 797 | 798 | if(ratio >= 0 && pJS.interactivity.status == 'mousemove'){ 799 | 800 | /* size */ 801 | if(pJS.interactivity.modes.bubble.size != pJS.particles.size.value){ 802 | 803 | if(pJS.interactivity.modes.bubble.size > pJS.particles.size.value){ 804 | var size = p.radius + (pJS.interactivity.modes.bubble.size*ratio); 805 | if(size >= 0){ 806 | p.radius_bubble = size; 807 | } 808 | }else{ 809 | var dif = p.radius - pJS.interactivity.modes.bubble.size, 810 | size = p.radius - (dif*ratio); 811 | if(size > 0){ 812 | p.radius_bubble = size; 813 | }else{ 814 | p.radius_bubble = 0; 815 | } 816 | } 817 | 818 | } 819 | 820 | /* opacity */ 821 | if(pJS.interactivity.modes.bubble.opacity != pJS.particles.opacity.value){ 822 | 823 | if(pJS.interactivity.modes.bubble.opacity > pJS.particles.opacity.value){ 824 | var opacity = pJS.interactivity.modes.bubble.opacity*ratio; 825 | if(opacity > p.opacity && opacity <= pJS.interactivity.modes.bubble.opacity){ 826 | p.opacity_bubble = opacity; 827 | } 828 | }else{ 829 | var opacity = p.opacity - (pJS.particles.opacity.value-pJS.interactivity.modes.bubble.opacity)*ratio; 830 | if(opacity < p.opacity && opacity >= pJS.interactivity.modes.bubble.opacity){ 831 | p.opacity_bubble = opacity; 832 | } 833 | } 834 | 835 | } 836 | 837 | } 838 | 839 | }else{ 840 | init(); 841 | } 842 | 843 | 844 | /* mouseleave */ 845 | if(pJS.interactivity.status == 'mouseleave'){ 846 | init(); 847 | } 848 | 849 | } 850 | 851 | /* on click event */ 852 | else if(pJS.interactivity.events.onclick.enable && isInArray('bubble', pJS.interactivity.events.onclick.mode)){ 853 | 854 | 855 | if(pJS.tmp.bubble_clicking){ 856 | var dx_mouse = p.x - pJS.interactivity.mouse.click_pos_x, 857 | dy_mouse = p.y - pJS.interactivity.mouse.click_pos_y, 858 | dist_mouse = Math.sqrt(dx_mouse*dx_mouse + dy_mouse*dy_mouse), 859 | time_spent = (new Date().getTime() - pJS.interactivity.mouse.click_time)/1000; 860 | 861 | if(time_spent > pJS.interactivity.modes.bubble.duration){ 862 | pJS.tmp.bubble_duration_end = true; 863 | } 864 | 865 | if(time_spent > pJS.interactivity.modes.bubble.duration*2){ 866 | pJS.tmp.bubble_clicking = false; 867 | pJS.tmp.bubble_duration_end = false; 868 | } 869 | } 870 | 871 | 872 | function process(bubble_param, particles_param, p_obj_bubble, p_obj, id){ 873 | 874 | if(bubble_param != particles_param){ 875 | 876 | if(!pJS.tmp.bubble_duration_end){ 877 | if(dist_mouse <= pJS.interactivity.modes.bubble.distance){ 878 | if(p_obj_bubble != undefined) var obj = p_obj_bubble; 879 | else var obj = p_obj; 880 | if(obj != bubble_param){ 881 | var value = p_obj - (time_spent * (p_obj - bubble_param) / pJS.interactivity.modes.bubble.duration); 882 | if(id == 'size') p.radius_bubble = value; 883 | if(id == 'opacity') p.opacity_bubble = value; 884 | } 885 | }else{ 886 | if(id == 'size') p.radius_bubble = undefined; 887 | if(id == 'opacity') p.opacity_bubble = undefined; 888 | } 889 | }else{ 890 | if(p_obj_bubble != undefined){ 891 | var value_tmp = p_obj - (time_spent * (p_obj - bubble_param) / pJS.interactivity.modes.bubble.duration), 892 | dif = bubble_param - value_tmp; 893 | value = bubble_param + dif; 894 | if(id == 'size') p.radius_bubble = value; 895 | if(id == 'opacity') p.opacity_bubble = value; 896 | } 897 | } 898 | 899 | } 900 | 901 | } 902 | 903 | if(pJS.tmp.bubble_clicking){ 904 | /* size */ 905 | process(pJS.interactivity.modes.bubble.size, pJS.particles.size.value, p.radius_bubble, p.radius, 'size'); 906 | /* opacity */ 907 | process(pJS.interactivity.modes.bubble.opacity, pJS.particles.opacity.value, p.opacity_bubble, p.opacity, 'opacity'); 908 | } 909 | 910 | } 911 | 912 | }; 913 | 914 | 915 | pJS.fn.modes.repulseParticle = function(p){ 916 | 917 | if(pJS.interactivity.events.onhover.enable && isInArray('repulse', pJS.interactivity.events.onhover.mode) && pJS.interactivity.status == 'mousemove') { 918 | 919 | var dx_mouse = p.x - pJS.interactivity.mouse.pos_x, 920 | dy_mouse = p.y - pJS.interactivity.mouse.pos_y, 921 | dist_mouse = Math.sqrt(dx_mouse*dx_mouse + dy_mouse*dy_mouse); 922 | 923 | var normVec = {x: dx_mouse/dist_mouse, y: dy_mouse/dist_mouse}, 924 | repulseRadius = pJS.interactivity.modes.repulse.distance, 925 | velocity = 100, 926 | repulseFactor = clamp((1/repulseRadius)*(-1*Math.pow(dist_mouse/repulseRadius,2)+1)*repulseRadius*velocity, 0, 50); 927 | 928 | var pos = { 929 | x: p.x + normVec.x * repulseFactor, 930 | y: p.y + normVec.y * repulseFactor 931 | } 932 | 933 | if(pJS.particles.move.out_mode == 'bounce'){ 934 | if(pos.x - p.radius > 0 && pos.x + p.radius < pJS.canvas.w) p.x = pos.x; 935 | if(pos.y - p.radius > 0 && pos.y + p.radius < pJS.canvas.h) p.y = pos.y; 936 | }else{ 937 | p.x = pos.x; 938 | p.y = pos.y; 939 | } 940 | 941 | } 942 | 943 | 944 | else if(pJS.interactivity.events.onclick.enable && isInArray('repulse', pJS.interactivity.events.onclick.mode)) { 945 | 946 | if(!pJS.tmp.repulse_finish){ 947 | pJS.tmp.repulse_count++; 948 | if(pJS.tmp.repulse_count == pJS.particles.array.length){ 949 | pJS.tmp.repulse_finish = true; 950 | } 951 | } 952 | 953 | if(pJS.tmp.repulse_clicking){ 954 | 955 | var repulseRadius = Math.pow(pJS.interactivity.modes.repulse.distance/6, 3); 956 | 957 | var dx = pJS.interactivity.mouse.click_pos_x - p.x, 958 | dy = pJS.interactivity.mouse.click_pos_y - p.y, 959 | d = dx*dx + dy*dy; 960 | 961 | var force = -repulseRadius / d * 1; 962 | 963 | function process(){ 964 | 965 | var f = Math.atan2(dy,dx); 966 | p.vx = force * Math.cos(f); 967 | p.vy = force * Math.sin(f); 968 | 969 | if(pJS.particles.move.out_mode == 'bounce'){ 970 | var pos = { 971 | x: p.x + p.vx, 972 | y: p.y + p.vy 973 | } 974 | if (pos.x + p.radius > pJS.canvas.w) p.vx = -p.vx; 975 | else if (pos.x - p.radius < 0) p.vx = -p.vx; 976 | if (pos.y + p.radius > pJS.canvas.h) p.vy = -p.vy; 977 | else if (pos.y - p.radius < 0) p.vy = -p.vy; 978 | } 979 | 980 | } 981 | 982 | // default 983 | if(d <= repulseRadius){ 984 | process(); 985 | } 986 | 987 | // bang - slow motion mode 988 | // if(!pJS.tmp.repulse_finish){ 989 | // if(d <= repulseRadius){ 990 | // process(); 991 | // } 992 | // }else{ 993 | // process(); 994 | // } 995 | 996 | 997 | }else{ 998 | 999 | if(pJS.tmp.repulse_clicking == false){ 1000 | 1001 | p.vx = p.vx_i; 1002 | p.vy = p.vy_i; 1003 | 1004 | } 1005 | 1006 | } 1007 | 1008 | } 1009 | 1010 | } 1011 | 1012 | 1013 | pJS.fn.modes.grabParticle = function(p){ 1014 | 1015 | if(pJS.interactivity.events.onhover.enable && pJS.interactivity.status == 'mousemove'){ 1016 | 1017 | var dx_mouse = p.x - pJS.interactivity.mouse.pos_x, 1018 | dy_mouse = p.y - pJS.interactivity.mouse.pos_y, 1019 | dist_mouse = Math.sqrt(dx_mouse*dx_mouse + dy_mouse*dy_mouse); 1020 | 1021 | /* draw a line between the cursor and the particle if the distance between them is under the config distance */ 1022 | if(dist_mouse <= pJS.interactivity.modes.grab.distance){ 1023 | 1024 | var opacity_line = pJS.interactivity.modes.grab.line_linked.opacity - (dist_mouse / (1/pJS.interactivity.modes.grab.line_linked.opacity)) / pJS.interactivity.modes.grab.distance; 1025 | 1026 | if(opacity_line > 0){ 1027 | 1028 | /* style */ 1029 | var color_line = pJS.particles.line_linked.color_rgb_line; 1030 | pJS.canvas.ctx.strokeStyle = 'rgba('+color_line.r+','+color_line.g+','+color_line.b+','+opacity_line+')'; 1031 | pJS.canvas.ctx.lineWidth = pJS.particles.line_linked.width; 1032 | //pJS.canvas.ctx.lineCap = 'round'; /* performance issue */ 1033 | 1034 | /* path */ 1035 | pJS.canvas.ctx.beginPath(); 1036 | pJS.canvas.ctx.moveTo(p.x, p.y); 1037 | pJS.canvas.ctx.lineTo(pJS.interactivity.mouse.pos_x, pJS.interactivity.mouse.pos_y); 1038 | pJS.canvas.ctx.stroke(); 1039 | pJS.canvas.ctx.closePath(); 1040 | 1041 | } 1042 | 1043 | } 1044 | 1045 | } 1046 | 1047 | }; 1048 | 1049 | 1050 | 1051 | /* ---------- pJS functions - vendors ------------ */ 1052 | 1053 | pJS.fn.vendors.eventsListeners = function(){ 1054 | 1055 | /* events target element */ 1056 | if(pJS.interactivity.detect_on == 'window'){ 1057 | pJS.interactivity.el = window; 1058 | }else{ 1059 | pJS.interactivity.el = pJS.canvas.el; 1060 | } 1061 | 1062 | 1063 | /* detect mouse pos - on hover / click event */ 1064 | if(pJS.interactivity.events.onhover.enable || pJS.interactivity.events.onclick.enable){ 1065 | 1066 | /* el on mousemove */ 1067 | pJS.interactivity.el.addEventListener('mousemove', function(e){ 1068 | 1069 | if(pJS.interactivity.el == window){ 1070 | var pos_x = e.clientX, 1071 | pos_y = e.clientY; 1072 | } 1073 | else{ 1074 | var pos_x = e.offsetX || e.clientX, 1075 | pos_y = e.offsetY || e.clientY; 1076 | } 1077 | 1078 | pJS.interactivity.mouse.pos_x = pos_x; 1079 | pJS.interactivity.mouse.pos_y = pos_y; 1080 | 1081 | if(pJS.tmp.retina){ 1082 | pJS.interactivity.mouse.pos_x *= pJS.canvas.pxratio; 1083 | pJS.interactivity.mouse.pos_y *= pJS.canvas.pxratio; 1084 | } 1085 | 1086 | pJS.interactivity.status = 'mousemove'; 1087 | 1088 | }); 1089 | 1090 | /* el on onmouseleave */ 1091 | pJS.interactivity.el.addEventListener('mouseleave', function(e){ 1092 | 1093 | pJS.interactivity.mouse.pos_x = null; 1094 | pJS.interactivity.mouse.pos_y = null; 1095 | pJS.interactivity.status = 'mouseleave'; 1096 | 1097 | }); 1098 | 1099 | } 1100 | 1101 | /* on click event */ 1102 | if(pJS.interactivity.events.onclick.enable){ 1103 | 1104 | pJS.interactivity.el.addEventListener('click', function(){ 1105 | 1106 | pJS.interactivity.mouse.click_pos_x = pJS.interactivity.mouse.pos_x; 1107 | pJS.interactivity.mouse.click_pos_y = pJS.interactivity.mouse.pos_y; 1108 | pJS.interactivity.mouse.click_time = new Date().getTime(); 1109 | 1110 | if(pJS.interactivity.events.onclick.enable){ 1111 | 1112 | switch(pJS.interactivity.events.onclick.mode){ 1113 | 1114 | case 'push': 1115 | if(pJS.particles.move.enable){ 1116 | pJS.fn.modes.pushParticles(pJS.interactivity.modes.push.particles_nb, pJS.interactivity.mouse); 1117 | }else{ 1118 | if(pJS.interactivity.modes.push.particles_nb == 1){ 1119 | pJS.fn.modes.pushParticles(pJS.interactivity.modes.push.particles_nb, pJS.interactivity.mouse); 1120 | } 1121 | else if(pJS.interactivity.modes.push.particles_nb > 1){ 1122 | pJS.fn.modes.pushParticles(pJS.interactivity.modes.push.particles_nb); 1123 | } 1124 | } 1125 | break; 1126 | 1127 | case 'remove': 1128 | pJS.fn.modes.removeParticles(pJS.interactivity.modes.remove.particles_nb); 1129 | break; 1130 | 1131 | case 'bubble': 1132 | pJS.tmp.bubble_clicking = true; 1133 | break; 1134 | 1135 | case 'repulse': 1136 | pJS.tmp.repulse_clicking = true; 1137 | pJS.tmp.repulse_count = 0; 1138 | pJS.tmp.repulse_finish = false; 1139 | setTimeout(function(){ 1140 | pJS.tmp.repulse_clicking = false; 1141 | }, pJS.interactivity.modes.repulse.duration*1000) 1142 | break; 1143 | 1144 | } 1145 | 1146 | } 1147 | 1148 | }); 1149 | 1150 | } 1151 | 1152 | 1153 | }; 1154 | 1155 | pJS.fn.vendors.densityAutoParticles = function(){ 1156 | 1157 | if(pJS.particles.number.density.enable){ 1158 | 1159 | /* calc area */ 1160 | var area = pJS.canvas.el.width * pJS.canvas.el.height / 1000; 1161 | if(pJS.tmp.retina){ 1162 | area = area/(pJS.canvas.pxratio*2); 1163 | } 1164 | 1165 | /* calc number of particles based on density area */ 1166 | var nb_particles = area * pJS.particles.number.value / pJS.particles.number.density.value_area; 1167 | 1168 | /* add or remove X particles */ 1169 | var missing_particles = pJS.particles.array.length - nb_particles; 1170 | if(missing_particles < 0) pJS.fn.modes.pushParticles(Math.abs(missing_particles)); 1171 | else pJS.fn.modes.removeParticles(missing_particles); 1172 | 1173 | } 1174 | 1175 | }; 1176 | 1177 | 1178 | pJS.fn.vendors.checkOverlap = function(p1, position){ 1179 | for(var i = 0; i < pJS.particles.array.length; i++){ 1180 | var p2 = pJS.particles.array[i]; 1181 | 1182 | var dx = p1.x - p2.x, 1183 | dy = p1.y - p2.y, 1184 | dist = Math.sqrt(dx*dx + dy*dy); 1185 | 1186 | if(dist <= p1.radius + p2.radius){ 1187 | p1.x = position ? position.x : Math.random() * pJS.canvas.w; 1188 | p1.y = position ? position.y : Math.random() * pJS.canvas.h; 1189 | pJS.fn.vendors.checkOverlap(p1); 1190 | } 1191 | } 1192 | }; 1193 | 1194 | 1195 | pJS.fn.vendors.createSvgImg = function(p){ 1196 | 1197 | /* set color to svg element */ 1198 | var svgXml = pJS.tmp.source_svg, 1199 | rgbHex = /#([0-9A-F]{3,6})/gi, 1200 | coloredSvgXml = svgXml.replace(rgbHex, function (m, r, g, b) { 1201 | if(p.color.rgb){ 1202 | var color_value = 'rgba('+p.color.rgb.r+','+p.color.rgb.g+','+p.color.rgb.b+','+p.opacity+')'; 1203 | }else{ 1204 | var color_value = 'hsla('+p.color.hsl.h+','+p.color.hsl.s+'%,'+p.color.hsl.l+'%,'+p.opacity+')'; 1205 | } 1206 | return color_value; 1207 | }); 1208 | 1209 | /* prepare to create img with colored svg */ 1210 | var svg = new Blob([coloredSvgXml], {type: 'image/svg+xml;charset=utf-8'}), 1211 | DOMURL = window.URL || window.webkitURL || window, 1212 | url = DOMURL.createObjectURL(svg); 1213 | 1214 | /* create particle img obj */ 1215 | var img = new Image(); 1216 | img.addEventListener('load', function(){ 1217 | p.img.obj = img; 1218 | p.img.loaded = true; 1219 | DOMURL.revokeObjectURL(url); 1220 | pJS.tmp.count_svg++; 1221 | }); 1222 | img.src = url; 1223 | 1224 | }; 1225 | 1226 | 1227 | pJS.fn.vendors.destroypJS = function(){ 1228 | cancelAnimationFrame(pJS.fn.drawAnimFrame); 1229 | canvas_el.remove(); 1230 | pJSDom = null; 1231 | }; 1232 | 1233 | 1234 | pJS.fn.vendors.drawShape = function(c, startX, startY, sideLength, sideCountNumerator, sideCountDenominator){ 1235 | 1236 | // By Programming Thomas - https://programmingthomas.wordpress.com/2013/04/03/n-sided-shapes/ 1237 | var sideCount = sideCountNumerator * sideCountDenominator; 1238 | var decimalSides = sideCountNumerator / sideCountDenominator; 1239 | var interiorAngleDegrees = (180 * (decimalSides - 2)) / decimalSides; 1240 | var interiorAngle = Math.PI - Math.PI * interiorAngleDegrees / 180; // convert to radians 1241 | c.save(); 1242 | c.beginPath(); 1243 | c.translate(startX, startY); 1244 | c.moveTo(0,0); 1245 | for (var i = 0; i < sideCount; i++) { 1246 | c.lineTo(sideLength,0); 1247 | c.translate(sideLength,0); 1248 | c.rotate(interiorAngle); 1249 | } 1250 | //c.stroke(); 1251 | c.fill(); 1252 | c.restore(); 1253 | 1254 | }; 1255 | 1256 | pJS.fn.vendors.exportImg = function(){ 1257 | window.open(pJS.canvas.el.toDataURL('image/png'), '_blank'); 1258 | }; 1259 | 1260 | 1261 | pJS.fn.vendors.loadImg = function(type){ 1262 | 1263 | pJS.tmp.img_error = undefined; 1264 | 1265 | if(pJS.particles.shape.image.src != ''){ 1266 | 1267 | if(type == 'svg'){ 1268 | 1269 | var xhr = new XMLHttpRequest(); 1270 | xhr.open('GET', pJS.particles.shape.image.src); 1271 | xhr.onreadystatechange = function (data) { 1272 | if(xhr.readyState == 4){ 1273 | if(xhr.status == 200){ 1274 | pJS.tmp.source_svg = data.currentTarget.response; 1275 | pJS.fn.vendors.checkBeforeDraw(); 1276 | }else{ 1277 | console.log('Error pJS - Image not found'); 1278 | pJS.tmp.img_error = true; 1279 | } 1280 | } 1281 | } 1282 | xhr.send(); 1283 | 1284 | }else{ 1285 | 1286 | var img = new Image(); 1287 | img.addEventListener('load', function(){ 1288 | pJS.tmp.img_obj = img; 1289 | pJS.fn.vendors.checkBeforeDraw(); 1290 | }); 1291 | img.src = pJS.particles.shape.image.src; 1292 | 1293 | } 1294 | 1295 | }else{ 1296 | console.log('Error pJS - No image.src'); 1297 | pJS.tmp.img_error = true; 1298 | } 1299 | 1300 | }; 1301 | 1302 | 1303 | pJS.fn.vendors.draw = function(){ 1304 | 1305 | if(pJS.particles.shape.type == 'image'){ 1306 | 1307 | if(pJS.tmp.img_type == 'svg'){ 1308 | 1309 | if(pJS.tmp.count_svg >= pJS.particles.number.value){ 1310 | pJS.fn.particlesDraw(); 1311 | if(!pJS.particles.move.enable) cancelRequestAnimFrame(pJS.fn.drawAnimFrame); 1312 | else pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw); 1313 | }else{ 1314 | //console.log('still loading...'); 1315 | if(!pJS.tmp.img_error) pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw); 1316 | } 1317 | 1318 | }else{ 1319 | 1320 | if(pJS.tmp.img_obj != undefined){ 1321 | pJS.fn.particlesDraw(); 1322 | if(!pJS.particles.move.enable) cancelRequestAnimFrame(pJS.fn.drawAnimFrame); 1323 | else pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw); 1324 | }else{ 1325 | if(!pJS.tmp.img_error) pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw); 1326 | } 1327 | 1328 | } 1329 | 1330 | }else{ 1331 | pJS.fn.particlesDraw(); 1332 | if(!pJS.particles.move.enable) cancelRequestAnimFrame(pJS.fn.drawAnimFrame); 1333 | else pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw); 1334 | } 1335 | 1336 | }; 1337 | 1338 | 1339 | pJS.fn.vendors.checkBeforeDraw = function(){ 1340 | 1341 | // if shape is image 1342 | if(pJS.particles.shape.type == 'image'){ 1343 | 1344 | if(pJS.tmp.img_type == 'svg' && pJS.tmp.source_svg == undefined){ 1345 | pJS.tmp.checkAnimFrame = requestAnimFrame(check); 1346 | }else{ 1347 | //console.log('images loaded! cancel check'); 1348 | cancelRequestAnimFrame(pJS.tmp.checkAnimFrame); 1349 | if(!pJS.tmp.img_error){ 1350 | pJS.fn.vendors.init(); 1351 | pJS.fn.vendors.draw(); 1352 | } 1353 | 1354 | } 1355 | 1356 | }else{ 1357 | pJS.fn.vendors.init(); 1358 | pJS.fn.vendors.draw(); 1359 | } 1360 | 1361 | }; 1362 | 1363 | 1364 | pJS.fn.vendors.init = function(){ 1365 | 1366 | /* init canvas + particles */ 1367 | pJS.fn.retinaInit(); 1368 | pJS.fn.canvasInit(); 1369 | pJS.fn.canvasSize(); 1370 | pJS.fn.canvasPaint(); 1371 | pJS.fn.particlesCreate(); 1372 | pJS.fn.vendors.densityAutoParticles(); 1373 | 1374 | /* particles.line_linked - convert hex colors to rgb */ 1375 | pJS.particles.line_linked.color_rgb_line = hexToRgb(pJS.particles.line_linked.color); 1376 | 1377 | }; 1378 | 1379 | 1380 | pJS.fn.vendors.start = function(){ 1381 | 1382 | if(isInArray('image', pJS.particles.shape.type)){ 1383 | pJS.tmp.img_type = pJS.particles.shape.image.src.substr(pJS.particles.shape.image.src.length - 3); 1384 | pJS.fn.vendors.loadImg(pJS.tmp.img_type); 1385 | }else{ 1386 | pJS.fn.vendors.checkBeforeDraw(); 1387 | } 1388 | 1389 | }; 1390 | 1391 | 1392 | 1393 | 1394 | /* ---------- pJS - start ------------ */ 1395 | 1396 | 1397 | pJS.fn.vendors.eventsListeners(); 1398 | 1399 | pJS.fn.vendors.start(); 1400 | 1401 | 1402 | 1403 | }; 1404 | 1405 | /* ---------- global functions - vendors ------------ */ 1406 | 1407 | Object.deepExtend = function(destination, source) { 1408 | for (var property in source) { 1409 | if (source[property] && source[property].constructor && 1410 | source[property].constructor === Object) { 1411 | destination[property] = destination[property] || {}; 1412 | arguments.callee(destination[property], source[property]); 1413 | } else { 1414 | destination[property] = source[property]; 1415 | } 1416 | } 1417 | return destination; 1418 | }; 1419 | 1420 | window.requestAnimFrame = (function(){ 1421 | return window.requestAnimationFrame || 1422 | window.webkitRequestAnimationFrame || 1423 | window.mozRequestAnimationFrame || 1424 | window.oRequestAnimationFrame || 1425 | window.msRequestAnimationFrame || 1426 | function(callback){ 1427 | window.setTimeout(callback, 1000 / 60); 1428 | }; 1429 | })(); 1430 | 1431 | window.cancelRequestAnimFrame = ( function() { 1432 | return window.cancelAnimationFrame || 1433 | window.webkitCancelRequestAnimationFrame || 1434 | window.mozCancelRequestAnimationFrame || 1435 | window.oCancelRequestAnimationFrame || 1436 | window.msCancelRequestAnimationFrame || 1437 | clearTimeout 1438 | } )(); 1439 | 1440 | function hexToRgb(hex){ 1441 | // By Tim Down - http://stackoverflow.com/a/5624139/3493650 1442 | // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF") 1443 | var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i; 1444 | hex = hex.replace(shorthandRegex, function(m, r, g, b) { 1445 | return r + r + g + g + b + b; 1446 | }); 1447 | var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); 1448 | return result ? { 1449 | r: parseInt(result[1], 16), 1450 | g: parseInt(result[2], 16), 1451 | b: parseInt(result[3], 16) 1452 | } : null; 1453 | }; 1454 | 1455 | function clamp(number, min, max) { 1456 | return Math.min(Math.max(number, min), max); 1457 | }; 1458 | 1459 | function isInArray(value, array) { 1460 | return array.indexOf(value) > -1; 1461 | } 1462 | 1463 | 1464 | /* ---------- particles.js functions - start ------------ */ 1465 | 1466 | window.pJSDom = []; 1467 | 1468 | window.particlesJS = function(tag_id, params){ 1469 | 1470 | //console.log(params); 1471 | 1472 | /* no string id? so it's object params, and set the id with default id */ 1473 | if(typeof(tag_id) != 'string'){ 1474 | params = tag_id; 1475 | tag_id = 'particles-js'; 1476 | } 1477 | 1478 | /* no id? set the id to default id */ 1479 | if(!tag_id){ 1480 | tag_id = 'particles-js'; 1481 | } 1482 | 1483 | /* pJS elements */ 1484 | var pJS_tag = document.getElementById(tag_id), 1485 | pJS_canvas_class = 'particles-js-canvas-el', 1486 | exist_canvas = pJS_tag.getElementsByClassName(pJS_canvas_class); 1487 | 1488 | /* remove canvas if exists into the pJS target tag */ 1489 | if(exist_canvas.length){ 1490 | while(exist_canvas.length > 0){ 1491 | pJS_tag.removeChild(exist_canvas[0]); 1492 | } 1493 | } 1494 | 1495 | /* create canvas element */ 1496 | var canvas_el = document.createElement('canvas'); 1497 | canvas_el.className = pJS_canvas_class; 1498 | 1499 | /* set size canvas */ 1500 | canvas_el.style.width = "100%"; 1501 | canvas_el.style.height = "100%"; 1502 | 1503 | /* append canvas */ 1504 | var canvas = document.getElementById(tag_id).appendChild(canvas_el); 1505 | 1506 | /* launch particle.js */ 1507 | if(canvas != null){ 1508 | pJSDom.push(new pJS(tag_id, params)); 1509 | } 1510 | 1511 | }; 1512 | 1513 | window.particlesJS.load = function(tag_id, path_config_json, callback){ 1514 | 1515 | /* load json config */ 1516 | var xhr = new XMLHttpRequest(); 1517 | xhr.open('GET', path_config_json); 1518 | xhr.onreadystatechange = function (data) { 1519 | if(xhr.readyState == 4){ 1520 | if(xhr.status == 200){ 1521 | var params = JSON.parse(data.currentTarget.response); 1522 | window.particlesJS(tag_id, params); 1523 | if(callback) callback(); 1524 | }else{ 1525 | console.log('Error pJS - XMLHttpRequest status: '+xhr.status); 1526 | console.log('Error pJS - File config not found'); 1527 | } 1528 | } 1529 | }; 1530 | xhr.send(); 1531 | 1532 | }; --------------------------------------------------------------------------------