jekyll-theme-satellite 1.1.2 → 1.2.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,700 +1 @@
1
- /**
2
- * Stars
3
- * Inspired by Steve Courtney's poster art for Celsius GS's Drifter - http://celsiusgs.com/drifter/posters.php
4
- * by Cory Hughart - http://coryhughart.com
5
- */
6
-
7
- // Settings
8
- var particleCount = 40,
9
- flareCount = 16,
10
- motion = 0.05,
11
- tilt = 0.05,
12
- color = '#44b5fd',
13
- colorPalette = ["#c13c3c", "#c13cc1", "#3c3cc1", "#3cc1c1", "#3cc13c", "#c1c13c"],
14
- particleSizeBase = 2,
15
- particleSizeMultiplier = 0.5,
16
- flareSizeBase = 100,
17
- flareSizeMultiplier = 100,
18
- lineWidth = 1,
19
- linkChance = 75, // chance per frame of link, higher = smaller chance
20
- linkLengthMin = 5, // min linked vertices
21
- linkLengthMax = 7, // max linked vertices
22
- linkOpacity = 0.375; // number between 0 & 1
23
- linkFade = 90, // link fade-out frames
24
- linkSpeed = 1, // distance a link travels in 1 frame
25
- glareAngle = -60,
26
- glareOpacityMultiplier = 0.05,
27
- renderParticles = true,
28
- renderParticleGlare = true,
29
- renderFlares = true,
30
- renderLinks = true,
31
- renderMesh = false,
32
- flicker = true,
33
- flickerSmoothing = 15, // higher = smoother flicker
34
- blurSize = 0,
35
- orbitTilt = true,
36
- randomMotion = true,
37
- noiseLength = 1000,
38
- noiseStrength = 1;
39
-
40
- var canvas = document.getElementById('stars'),
41
- context = canvas.getContext('2d'),
42
- mouse = { x: 0, y: 0 },
43
- m = {},
44
- r = 0,
45
- c = 1000, // multiplier for delaunay points, since floats too small can mess up the algorithm
46
- n = 0,
47
- nAngle = (Math.PI * 2) / noiseLength,
48
- nRad = 100,
49
- nScale = 0.5,
50
- nPos = {x: 0, y: 0},
51
- points = [],
52
- vertices = [],
53
- triangles = [],
54
- links = [],
55
- particles = [],
56
- flares = [];
57
-
58
- // Delaunay Triangulation
59
- var EPSILON = 1.0 / 1048576.0;
60
-
61
- function randomColor(colors){
62
- return colors[Math.floor(Math.random() * colors.length)];
63
- }
64
-
65
- function supertriangle(vertices) {
66
- var xmin = Number.POSITIVE_INFINITY,
67
- ymin = Number.POSITIVE_INFINITY,
68
- xmax = Number.NEGATIVE_INFINITY,
69
- ymax = Number.NEGATIVE_INFINITY,
70
- i, dx, dy, dmax, xmid, ymid;
71
-
72
- for(i = vertices.length; i--; ) {
73
- if(vertices[i][0] < xmin) xmin = vertices[i][0];
74
- if(vertices[i][0] > xmax) xmax = vertices[i][0];
75
- if(vertices[i][1] < ymin) ymin = vertices[i][1];
76
- if(vertices[i][1] > ymax) ymax = vertices[i][1];
77
- }
78
-
79
- dx = xmax - xmin;
80
- dy = ymax - ymin;
81
- dmax = Math.max(dx, dy);
82
- xmid = xmin + dx * 0.5;
83
- ymid = ymin + dy * 0.5;
84
-
85
- return [
86
- [xmid - 20 * dmax, ymid - dmax],
87
- [xmid , ymid + 20 * dmax],
88
- [xmid + 20 * dmax, ymid - dmax]
89
- ];
90
- }
91
-
92
- function circumcircle(vertices, i, j, k) {
93
- var x1 = vertices[i][0],
94
- y1 = vertices[i][1],
95
- x2 = vertices[j][0],
96
- y2 = vertices[j][1],
97
- x3 = vertices[k][0],
98
- y3 = vertices[k][1],
99
- fabsy1y2 = Math.abs(y1 - y2),
100
- fabsy2y3 = Math.abs(y2 - y3),
101
- xc, yc, m1, m2, mx1, mx2, my1, my2, dx, dy;
102
-
103
- /* Check for coincident points */
104
- if(fabsy1y2 < EPSILON && fabsy2y3 < EPSILON)
105
- throw new Error("Eek! Coincident points!");
106
-
107
- if(fabsy1y2 < EPSILON) {
108
- m2 = -((x3 - x2) / (y3 - y2));
109
- mx2 = (x2 + x3) / 2.0;
110
- my2 = (y2 + y3) / 2.0;
111
- xc = (x2 + x1) / 2.0;
112
- yc = m2 * (xc - mx2) + my2;
113
- }
114
- else if(fabsy2y3 < EPSILON) {
115
- m1 = -((x2 - x1) / (y2 - y1));
116
- mx1 = (x1 + x2) / 2.0;
117
- my1 = (y1 + y2) / 2.0;
118
- xc = (x3 + x2) / 2.0;
119
- yc = m1 * (xc - mx1) + my1;
120
- }
121
- else {
122
- m1 = -((x2 - x1) / (y2 - y1));
123
- m2 = -((x3 - x2) / (y3 - y2));
124
- mx1 = (x1 + x2) / 2.0;
125
- mx2 = (x2 + x3) / 2.0;
126
- my1 = (y1 + y2) / 2.0;
127
- my2 = (y2 + y3) / 2.0;
128
- xc = (m1 * mx1 - m2 * mx2 + my2 - my1) / (m1 - m2);
129
- yc = (fabsy1y2 > fabsy2y3) ?
130
- m1 * (xc - mx1) + my1 :
131
- m2 * (xc - mx2) + my2;
132
- }
133
-
134
- dx = x2 - xc;
135
- dy = y2 - yc;
136
- return {i: i, j: j, k: k, x: xc, y: yc, r: dx * dx + dy * dy};
137
- }
138
-
139
- function dedup(edges) {
140
- var i, j, a, b, m, n;
141
-
142
- for(j = edges.length; j; ) {
143
- b = edges[--j];
144
- a = edges[--j];
145
-
146
- for(i = j; i; ) {
147
- n = edges[--i];
148
- m = edges[--i];
149
-
150
- if((a === m && b === n) || (a === n && b === m)) {
151
- edges.splice(j, 2);
152
- edges.splice(i, 2);
153
- break;
154
- }
155
- }
156
- }
157
- }
158
-
159
- function Delaunay(vertices, key) {
160
- var n = vertices.length,
161
- i, j, indices, st, open, closed, edges, dx, dy, a, b, c;
162
-
163
- /* Bail if there aren't enough vertices to form any triangles. */
164
- if(n < 3)
165
- return [];
166
-
167
- /* Slice out the actual vertices from the passed objects. (Duplicate the
168
- * array even if we don't, though, since we need to make a supertriangle
169
- * later on!) */
170
- vertices = vertices.slice(0);
171
-
172
- if(key)
173
- for(i = n; i--; )
174
- vertices[i] = vertices[i][key];
175
-
176
- /* Make an array of indices into the vertex array, sorted by the
177
- * vertices' x-position. */
178
- indices = new Array(n);
179
-
180
- for(i = n; i--; )
181
- indices[i] = i;
182
-
183
- indices.sort(function(i, j) {
184
- return vertices[j][0] - vertices[i][0];
185
- });
186
-
187
- /* Next, find the vertices of the supertriangle (which contains all other
188
- * triangles), and append them onto the end of a (copy of) the vertex
189
- * array. */
190
- st = supertriangle(vertices);
191
- vertices.push(st[0], st[1], st[2]);
192
-
193
- /* Initialize the open list (containing the supertriangle and nothing
194
- * else) and the closed list (which is empty since we havn't processed
195
- * any triangles yet). */
196
- open = [circumcircle(vertices, n + 0, n + 1, n + 2)];
197
- closed = [];
198
- edges = [];
199
-
200
- /* Incrementally add each vertex to the mesh. */
201
- for(i = indices.length; i--; edges.length = 0) {
202
- c = indices[i];
203
-
204
- /* For each open triangle, check to see if the current point is
205
- * inside it's circumcircle. If it is, remove the triangle and add
206
- * it's edges to an edge list. */
207
- for(j = open.length; j--; ) {
208
- /* If this point is to the right of this triangle's circumcircle,
209
- * then this triangle should never get checked again. Remove it
210
- * from the open list, add it to the closed list, and skip. */
211
- dx = vertices[c][0] - open[j].x;
212
-
213
- if(dx > 0.0 && dx * dx > open[j].r) {
214
- closed.push(open[j]);
215
- open.splice(j, 1);
216
- continue;
217
- }
218
-
219
- /* If we're outside the circumcircle, skip this triangle. */
220
- dy = vertices[c][1] - open[j].y;
221
-
222
- if(dx * dx + dy * dy - open[j].r > EPSILON)
223
- continue;
224
-
225
- /* Remove the triangle and add it's edges to the edge list. */
226
- edges.push(
227
- open[j].i, open[j].j,
228
- open[j].j, open[j].k,
229
- open[j].k, open[j].i
230
- );
231
-
232
- open.splice(j, 1);
233
- }
234
-
235
- /* Remove any doubled edges. */
236
- dedup(edges);
237
-
238
- /* Add a new triangle for each edge. */
239
- for(j = edges.length; j; ) {
240
- b = edges[--j];
241
- a = edges[--j];
242
- open.push(circumcircle(vertices, a, b, c));
243
- }
244
- }
245
-
246
- /* Copy any remaining open triangles to the closed list, and then
247
- * remove any triangles that share a vertex with the supertriangle,
248
- * building a list of triplets that represent triangles. */
249
- for(i = open.length; i--; )
250
- closed.push(open[i]);
251
-
252
- open.length = 0;
253
-
254
- for(i = closed.length; i--; )
255
- if(closed[i].i < n && closed[i].j < n && closed[i].k < n)
256
- open.push(closed[i].i, closed[i].j, closed[i].k);
257
-
258
- /* Yay, we're done! */
259
- return open;
260
- }
261
-
262
- function init() {
263
- var i, j, k;
264
-
265
- // requestAnimFrame polyfill
266
- window.requestAnimFrame = (function(){
267
- return window.requestAnimationFrame ||
268
- window.webkitRequestAnimationFrame ||
269
- window.mozRequestAnimationFrame ||
270
- function( callback ){
271
- window.setTimeout(callback, 1000 / 60);
272
- };
273
- })();
274
-
275
- // Size canvas
276
- resize();
277
-
278
- mouse.x = canvas.clientWidth / 2;
279
- mouse.y = canvas.clientHeight / 2;
280
-
281
- // Create particle positions
282
- for (i = 0; i < particleCount; i++) {
283
- var p = new Particle();
284
- particles.push(p);
285
- points.push([p.x*c, p.y*c]);
286
- }
287
-
288
- vertices = Delaunay(points);
289
- // Create an array of "triangles" (groups of 3 indices)
290
- var tri = [];
291
-
292
- for (i = 0; i < vertices.length; i++) {
293
- if (tri.length == 3) {
294
- triangles.push(tri);
295
- tri = [];
296
- }
297
-
298
- tri.push(vertices[i]);
299
- }
300
-
301
- // Tell all the particles who their neighbors are
302
- for (i = 0; i < particles.length; i++) {
303
- // Loop through all tirangles
304
- for (j = 0; j < triangles.length; j++) {
305
- // Check if this particle's index is in this triangle
306
- k = triangles[j].indexOf(i);
307
- // If it is, add its neighbors to the particles contacts list
308
- if (k !== -1) {
309
- triangles[j].forEach(function(value, index, array) {
310
- if (value !== i && particles[i].neighbors.indexOf(value) == -1) {
311
- particles[i].neighbors.push(value);
312
- }
313
- });
314
- }
315
- }
316
- }
317
-
318
- if (renderFlares) {
319
- // Create flare positions
320
- for (i = 0; i < flareCount; i++) {
321
- flares.push(new Flare());
322
- }
323
- }
324
-
325
- // Motion mode
326
- if ('ontouchstart' in document.documentElement && window.DeviceOrientationEvent) {
327
- // console.log('Using device orientation');
328
- window.addEventListener('deviceorientation', function(e) {
329
- mouse.x = (canvas.clientWidth / 2) - ((e.gamma / 90) * (canvas.clientWidth / 2) * 2);
330
- mouse.y = (canvas.clientHeight / 2) - ((e.beta / 90) * (canvas.clientHeight / 2) * 2);
331
- }, true);
332
- }
333
- else {
334
- // Mouse move listener
335
- // console.log('Using mouse movement');
336
- document.body.addEventListener('mousemove', function(e) {
337
- mouse.x = e.clientX;
338
- mouse.y = e.clientY;
339
- });
340
- }
341
-
342
- // Animation loop
343
- (function animloop(){
344
- requestAnimFrame(animloop);
345
- resize();
346
- render();
347
- })();
348
- }
349
-
350
- function render() {
351
- if (randomMotion) {
352
- n++;
353
-
354
- if (n >= noiseLength) {
355
- n = 0;
356
- }
357
-
358
- nPos = noisePoint(n);
359
- }
360
-
361
- // Clear
362
- context.clearRect(0, 0, canvas.width, canvas.height);
363
-
364
- if (blurSize > 0) {
365
- context.shadowBlur = blurSize;
366
- context.shadowColor = randomColor(colorPalette);
367
- }
368
-
369
- if (renderParticles) {
370
- // Render particles
371
- for (var i = 0; i < particleCount; i++) {
372
- particles[i].render();
373
- }
374
- }
375
-
376
- if (renderMesh) {
377
- // Render all lines
378
- context.beginPath();
379
-
380
- for (var v = 0; v < vertices.length-1; v++) {
381
- // Splits the array into triplets
382
- if ((v + 1) % 3 === 0) { continue; }
383
-
384
- var p1 = particles[vertices[v]],
385
- p2 = particles[vertices[v+1]];
386
-
387
- var pos1 = position(p1.x, p1.y, p1.z),
388
- pos2 = position(p2.x, p2.y, p2.z);
389
-
390
- context.moveTo(pos1.x, pos1.y);
391
- context.lineTo(pos2.x, pos2.y);
392
- }
393
-
394
- context.strokeStyle = randomColor(colorPalette);
395
- context.lineWidth = lineWidth;
396
- context.stroke();
397
- context.closePath();
398
- }
399
-
400
- if (renderLinks) {
401
- // Possibly start a new link
402
- if (random(0, linkChance) == linkChance) {
403
- var length = random(linkLengthMin, linkLengthMax);
404
- var start = random(0, particles.length-1);
405
- startLink(start, length);
406
- }
407
-
408
- // Render existing links
409
- // Iterate in reverse so that removing items doesn't affect the loop
410
- for (var l = links.length-1; l >= 0; l--) {
411
- if (links[l] && !links[l].finished) {
412
- links[l].render();
413
- }
414
- else {
415
- delete links[l];
416
- }
417
- }
418
- }
419
-
420
- if (renderFlares) {
421
- // Render flares
422
- for (var j = 0; j < flareCount; j++) {
423
- flares[j].render();
424
- }
425
- }
426
- }
427
-
428
- function resize() {
429
- canvas.width = window.innerWidth * (window.devicePixelRatio || 1);
430
- canvas.height = canvas.width * (canvas.clientHeight / canvas.clientWidth);
431
- }
432
-
433
- function startLink(vertex, length) {
434
- links.push(new Link(vertex, length));
435
- }
436
-
437
- // Particle class
438
- var Particle = function() {
439
- this.x = random(-0.1, 1.1, true);
440
- this.y = random(-0.1, 1.1, true);
441
- this.z = random(0,4);
442
- this.color = randomColor(colorPalette);
443
- this.opacity = random(0.1,1,true);
444
- this.flicker = 0;
445
- this.neighbors = []; // placeholder for neighbors
446
- };
447
-
448
- Particle.prototype.render = function() {
449
- var pos = position(this.x, this.y, this.z),
450
- r = ((this.z * particleSizeMultiplier) + particleSizeBase) * (sizeRatio() / 1000),
451
- o = this.opacity;
452
-
453
- if (flicker) {
454
- var newVal = random(-0.5, 0.5, true);
455
- this.flicker += (newVal - this.flicker) / flickerSmoothing;
456
-
457
- if (this.flicker > 0.5) this.flicker = 0.5;
458
- if (this.flicker < -0.5) this.flicker = -0.5;
459
-
460
- o += this.flicker;
461
-
462
- if (o > 1) o = 1;
463
- if (o < 0) o = 0;
464
- }
465
-
466
- context.fillStyle = this.color;
467
- context.globalAlpha = o;
468
- context.beginPath();
469
- context.arc(pos.x, pos.y, r, 0, 2 * Math.PI, false);
470
- context.fill();
471
- context.closePath();
472
-
473
- if (renderParticleGlare) {
474
- context.globalAlpha = o * glareOpacityMultiplier;
475
- context.ellipse(pos.x, pos.y, r * 100, r, (glareAngle - ((nPos.x - 0.5) * noiseStrength * motion)) * (Math.PI / 180), 0, 2 * Math.PI, false);
476
- context.fill();
477
- context.closePath();
478
- }
479
-
480
- context.globalAlpha = 1;
481
- };
482
-
483
- // Flare class
484
- var Flare = function() {
485
- this.x = random(-0.25, 1.25, true);
486
- this.y = random(-0.25, 1.25, true);
487
- this.z = random(0,2);
488
- this.color = randomColor(colorPalette);
489
- this.opacity = random(0.001, 0.01, true);
490
- };
491
-
492
- Flare.prototype.render = function() {
493
- var pos = position(this.x, this.y, this.z),
494
- r = ((this.z * flareSizeMultiplier) + flareSizeBase) * (sizeRatio() / 1000);
495
-
496
- // Feathered circles
497
- context.beginPath();
498
- context.globalAlpha = this.opacity;
499
- context.arc(pos.x, pos.y, r, 0, 2 * Math.PI, false);
500
- context.fillStyle = this.color;
501
- context.fill();
502
- context.closePath();
503
- context.globalAlpha = 1;
504
- };
505
-
506
- // Link class
507
- var Link = function(startVertex, numPoints) {
508
- this.length = numPoints;
509
- this.verts = [startVertex];
510
- this.stage = 0;
511
- this.linked = [startVertex];
512
- this.distances = [];
513
- this.traveled = 0;
514
- this.fade = 0;
515
- this.finished = false;
516
- };
517
-
518
- Link.prototype.render = function() {
519
- // Stages:
520
- // 0. Vertex collection
521
- // 1. Render line reaching from vertex to vertex
522
- // 2. Fade out
523
- // 3. Finished (delete me)
524
-
525
- var i, p, pos, points;
526
-
527
- switch (this.stage) {
528
- // VERTEX COLLECTION STAGE
529
- case 0:
530
- // Grab the last member of the link
531
- var last = particles[this.verts[this.verts.length-1]];
532
- if (last && last.neighbors && last.neighbors.length > 0) {
533
- // Grab a random neighbor
534
- var neighbor = last.neighbors[random(0, last.neighbors.length-1)];
535
- // If we haven't seen that particle before, add it to the link
536
- if (this.verts.indexOf(neighbor) == -1) {
537
- this.verts.push(neighbor);
538
- }
539
- // If we have seen that particle before, we'll just wait for the next frame
540
- }
541
- else {
542
- this.stage = 3;
543
- this.finished = true;
544
- }
545
-
546
- if (this.verts.length >= this.length) {
547
- // Calculate all distances at once
548
- for (i = 0; i < this.verts.length-1; i++) {
549
- var p1 = particles[this.verts[i]],
550
- p2 = particles[this.verts[i+1]],
551
- dx = p1.x - p2.x,
552
- dy = p1.y - p2.y,
553
- dist = Math.sqrt(dx*dx + dy*dy);
554
-
555
- this.distances.push(dist);
556
- }
557
- this.stage = 1;
558
- }
559
- break;
560
-
561
- // RENDER LINE ANIMATION STAGE
562
- case 1:
563
- if (this.distances.length > 0) {
564
-
565
- points = [];
566
-
567
- // Gather all points already linked
568
- for (i = 0; i < this.linked.length; i++) {
569
- p = particles[this.linked[i]];
570
- pos = position(p.x, p.y, p.z);
571
- points.push([pos.x, pos.y]);
572
- }
573
-
574
- var linkSpeedRel = linkSpeed * 0.00001 * canvas.width;
575
- this.traveled += linkSpeedRel;
576
- var d = this.distances[this.linked.length-1];
577
- // Calculate last point based on linkSpeed and distance travelled to next point
578
- if (this.traveled >= d) {
579
- this.traveled = 0;
580
- // We've reached the next point, add coordinates to array
581
- this.linked.push(this.verts[this.linked.length]);
582
- p = particles[this.linked[this.linked.length-1]];
583
- pos = position(p.x, p.y, p.z);
584
- points.push([pos.x, pos.y]);
585
-
586
- if (this.linked.length >= this.verts.length) {
587
- this.stage = 2;
588
- }
589
- }
590
- else {
591
- // We're still travelling to the next point, get coordinates at travel distance
592
- // http://math.stackexchange.com/a/85582
593
- var a = particles[this.linked[this.linked.length-1]],
594
- b = particles[this.verts[this.linked.length]],
595
- t = d - this.traveled,
596
- x = ((this.traveled * b.x) + (t * a.x)) / d,
597
- y = ((this.traveled * b.y) + (t * a.y)) / d,
598
- z = ((this.traveled * b.z) + (t * a.z)) / d;
599
-
600
- pos = position(x, y, z);
601
- points.push([pos.x, pos.y]);
602
- }
603
-
604
- this.drawLine(points);
605
- }
606
- else {
607
- this.stage = 3;
608
- this.finished = true;
609
- }
610
- break;
611
-
612
- // FADE OUT STAGE
613
- case 2:
614
- if (this.verts.length > 1) {
615
- if (this.fade < linkFade) {
616
- this.fade++;
617
-
618
- // Render full link between all vertices and fade over time
619
- points = [];
620
- var alpha = (1 - (this.fade / linkFade)) * linkOpacity;
621
-
622
- for (i = 0; i < this.verts.length; i++) {
623
- p = particles[this.verts[i]];
624
- pos = position(p.x, p.y, p.z);
625
- points.push([pos.x, pos.y]);
626
- }
627
-
628
- this.drawLine(points, alpha);
629
- }
630
- else {
631
- this.stage = 3;
632
- this.finished = true;
633
- }
634
- }
635
- else {
636
- this.stage = 3;
637
- this.finished = true;
638
- }
639
-
640
- break;
641
- // FINISHED STAGE
642
- case 3:
643
- default:
644
- this.finished = true;
645
- break;
646
- }
647
- };
648
-
649
- Link.prototype.drawLine = function(points, alpha) {
650
- if (typeof alpha !== 'number') alpha = linkOpacity;
651
-
652
- if (points.length > 1 && alpha > 0) {
653
- context.globalAlpha = alpha;
654
- context.beginPath();
655
-
656
- for (var i = 0; i < points.length-1; i++) {
657
- context.moveTo(points[i][0], points[i][1]);
658
- context.lineTo(points[i+1][0], points[i+1][1]);
659
- }
660
-
661
- context.strokeStyle = '#888';
662
- context.lineWidth = lineWidth;
663
- context.stroke();
664
- context.closePath();
665
- context.globalAlpha = 1;
666
- }
667
- };
668
-
669
- // Utils
670
- function noisePoint(i) {
671
- var a = nAngle * i,
672
- cosA = Math.cos(a),
673
- sinA = Math.sin(a),
674
- rad = nRad;
675
-
676
- return {
677
- x: rad * cosA,
678
- y: rad * sinA
679
- };
680
- }
681
-
682
- function position(x, y, z) {
683
- return {
684
- x: (x * canvas.width) + ((((canvas.width / 2) - mouse.x + ((nPos.x - 0.5) * noiseStrength)) * z) * motion),
685
- y: (y * canvas.height) + ((((canvas.height / 2) - mouse.y + ((nPos.y - 0.5) * noiseStrength)) * z) * motion)
686
- };
687
- }
688
-
689
- function sizeRatio() {
690
- return canvas.width >= canvas.height ? canvas.width : canvas.height;
691
- }
692
-
693
- function random(min, max, float) {
694
- return float ?
695
- Math.random() * (max - min) + min :
696
- Math.floor(Math.random() * (max - min + 1)) + min;
697
- }
698
-
699
- // init
700
- if (canvas) init();
1
+ var particleCount=40,flareCount=16,motion=.05,tilt=.05,color="#44b5fd",colorPalette=["#c13c3c","#c13cc1","#3c3cc1","#3cc1c1","#3cc13c","#c1c13c"],particleSizeBase=2,particleSizeMultiplier=.5,flareSizeBase=100,flareSizeMultiplier=100,lineWidth=1,linkChance=75,linkLengthMin=5,linkLengthMax=7,linkOpacity=.375;linkFade=90,linkSpeed=1,glareAngle=-60,glareOpacityMultiplier=.05,renderParticles=!0,renderParticleGlare=!0,renderFlares=!0,renderLinks=!0,renderMesh=!1,flicker=!0,flickerSmoothing=15,blurSize=0,orbitTilt=!0,randomMotion=!0,noiseLength=1e3,noiseStrength=1;var canvas=document.getElementById("stars"),context=canvas.getContext("2d"),mouse={x:0,y:0},m={},r=0,c=1e3,n=0,nAngle=2*Math.PI/noiseLength,nRad=100,nScale=.5,nPos={x:0,y:0},points=[],vertices=[],triangles=[],links=[],particles=[],flares=[],EPSILON=1/1048576;function randomColor(t){return t[Math.floor(Math.random()*t.length)]}function supertriangle(t){var e,i,s,o,a,l,h=Number.POSITIVE_INFINITY,$=Number.POSITIVE_INFINITY,f=Number.NEGATIVE_INFINITY,d=Number.NEGATIVE_INFINITY;for(e=t.length;e--;)t[e][0]<h&&(h=t[e][0]),t[e][0]>f&&(f=t[e][0]),t[e][1]<$&&($=t[e][1]),t[e][1]>d&&(d=t[e][1]);return o=Math.max(i=f-h,s=d-$),[[(a=h+.5*i)-20*o,(l=$+.5*s)-o],[a,l+20*o],[a+20*o,l-o]]}function circumcircle(t,e,i,s){var o,a,l,h,$,f,d,u,v,p,g=t[e][0],_=t[e][1],x=t[i][0],k=t[i][1],y=t[s][0],P=t[s][1],I=Math.abs(_-k),b=Math.abs(k-P);if(I<EPSILON&&b<EPSILON)throw Error("Eek! Coincident points!");return I<EPSILON?(h=-((y-x)/(P-k)),f=(x+y)/2,u=(k+P)/2,a=h*((o=(x+g)/2)-f)+u):b<EPSILON?(l=-((x-g)/(k-_)),$=(g+x)/2,d=(_+k)/2,a=l*((o=(y+x)/2)-$)+d):(l=-((x-g)/(k-_)),h=-((y-x)/(P-k)),$=(g+x)/2,f=(x+y)/2,d=(_+k)/2,o=(l*$-h*f+(u=(k+P)/2)-d)/(l-h),a=I>b?l*(o-$)+d:h*(o-f)+u),v=x-o,p=k-a,{i:e,j:i,k:s,x:o,y:a,r:v*v+p*p}}function dedup(t){var e,i,s,o,a,l;for(i=t.length;i;)for(o=t[--i],s=t[--i],e=i;e;)if(l=t[--e],s===(a=t[--e])&&o===l||s===l&&o===a){t.splice(i,2),t.splice(e,2);break}}function Delaunay(t,e){var i,s,o,a,l,h,$,f,d,u,v,p,g=t.length;if(g<3)return[];if(t=t.slice(0),e)for(i=g;i--;)t[i]=t[i][e];for(o=Array(g),i=g;i--;)o[i]=i;for(o.sort(function(e,i){return t[i][0]-t[e][0]}),a=supertriangle(t),t.push(a[0],a[1],a[2]),l=[circumcircle(t,g+0,g+1,g+2)],h=[],$=[],i=o.length;i--;$.length=0){for(p=o[i],s=l.length;s--;){if((f=t[p][0]-l[s].x)>0&&f*f>l[s].r){h.push(l[s]),l.splice(s,1);continue}f*f+(d=t[p][1]-l[s].y)*d-l[s].r>EPSILON||($.push(l[s].i,l[s].j,l[s].j,l[s].k,l[s].k,l[s].i),l.splice(s,1))}for(dedup($),s=$.length;s;)v=$[--s],u=$[--s],l.push(circumcircle(t,u,v,p))}for(i=l.length;i--;)h.push(l[i]);for(l.length=0,i=h.length;i--;)h[i].i<g&&h[i].j<g&&h[i].k<g&&l.push(h[i].i,h[i].j,h[i].k);return l}function init(){for(window.requestAnimFrame=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||function(t){window.setTimeout(t,1e3/60)},resize(),mouse.x=canvas.clientWidth/2,mouse.y=canvas.clientHeight/2,t=0;t<particleCount;t++){var t,e,i,s=new Particle;particles.push(s),points.push([s.x*c,s.y*c])}vertices=Delaunay(points);var o=[];for(t=0;t<vertices.length;t++)3==o.length&&(triangles.push(o),o=[]),o.push(vertices[t]);for(t=0;t<particles.length;t++)for(e=0;e<triangles.length;e++)-1!==(i=triangles[e].indexOf(t))&&triangles[e].forEach(function(e,i,s){e!==t&&-1==particles[t].neighbors.indexOf(e)&&particles[t].neighbors.push(e)});if(renderFlares)for(t=0;t<flareCount;t++)flares.push(new Flare);"ontouchstart"in document.documentElement&&window.DeviceOrientationEvent?window.addEventListener("deviceorientation",function(t){mouse.x=canvas.clientWidth/2-t.gamma/90*(canvas.clientWidth/2)*2,mouse.y=canvas.clientHeight/2-t.beta/90*(canvas.clientHeight/2)*2},!0):document.body.addEventListener("mousemove",function(t){mouse.x=t.clientX,mouse.y=t.clientY}),function t(){requestAnimFrame(t),resize(),render()}()}function render(){if(randomMotion&&(++n>=noiseLength&&(n=0),nPos=noisePoint(n)),context.clearRect(0,0,canvas.width,canvas.height),blurSize>0&&(context.shadowBlur=blurSize,context.shadowColor=randomColor(colorPalette)),renderParticles)for(var t=0;t<particleCount;t++)particles[t].render();if(renderMesh){context.beginPath();for(var e=0;e<vertices.length-1;e++)if((e+1)%3!=0){var i=particles[vertices[e]],s=particles[vertices[e+1]],o=position(i.x,i.y,i.z),a=position(s.x,s.y,s.z);context.moveTo(o.x,o.y),context.lineTo(a.x,a.y)}context.strokeStyle=randomColor(colorPalette),context.lineWidth=lineWidth,context.stroke(),context.closePath()}if(renderLinks){if(random(0,linkChance)==linkChance){var l=random(linkLengthMin,linkLengthMax);startLink(random(0,particles.length-1),l)}for(var h=links.length-1;h>=0;h--)links[h]&&!links[h].finished?links[h].render():delete links[h]}if(renderFlares)for(var $=0;$<flareCount;$++)flares[$].render()}function resize(){canvas.width=window.innerWidth*(window.devicePixelRatio||1),canvas.height=canvas.width*(canvas.clientHeight/canvas.clientWidth)}function startLink(t,e){links.push(new Link(t,e))}var Particle=function(){this.x=random(-.1,1.1,!0),this.y=random(-.1,1.1,!0),this.z=random(0,4),this.color=randomColor(colorPalette),this.opacity=random(.1,1,!0),this.flicker=0,this.neighbors=[]};Particle.prototype.render=function(){var t=position(this.x,this.y,this.z),e=(this.z*particleSizeMultiplier+particleSizeBase)*(sizeRatio()/1e3),i=this.opacity;if(flicker){var s=random(-.5,.5,!0);this.flicker+=(s-this.flicker)/flickerSmoothing,this.flicker>.5&&(this.flicker=.5),this.flicker<-.5&&(this.flicker=-.5),(i+=this.flicker)>1&&(i=1),i<0&&(i=0)}context.fillStyle=this.color,context.globalAlpha=i,context.beginPath(),context.arc(t.x,t.y,e,0,2*Math.PI,!1),context.fill(),context.closePath(),renderParticleGlare&&(context.globalAlpha=i*glareOpacityMultiplier,context.ellipse(t.x,t.y,100*e,e,(glareAngle-(nPos.x-.5)*noiseStrength*motion)*(Math.PI/180),0,2*Math.PI,!1),context.fill(),context.closePath()),context.globalAlpha=1};var Flare=function(){this.x=random(-.25,1.25,!0),this.y=random(-.25,1.25,!0),this.z=random(0,2),this.color=randomColor(colorPalette),this.opacity=random(.001,.01,!0)};Flare.prototype.render=function(){var t=position(this.x,this.y,this.z),e=(this.z*flareSizeMultiplier+flareSizeBase)*(sizeRatio()/1e3);context.beginPath(),context.globalAlpha=this.opacity,context.arc(t.x,t.y,e,0,2*Math.PI,!1),context.fillStyle=this.color,context.fill(),context.closePath(),context.globalAlpha=1};var Link=function(t,e){this.length=e,this.verts=[t],this.stage=0,this.linked=[t],this.distances=[],this.traveled=0,this.fade=0,this.finished=!1};function noisePoint(t){var e=nAngle*t,i=nRad;return{x:i*Math.cos(e),y:i*Math.sin(e)}}function position(t,e,i){return{x:t*canvas.width+(canvas.width/2-mouse.x+(nPos.x-.5)*noiseStrength)*i*motion,y:e*canvas.height+(canvas.height/2-mouse.y+(nPos.y-.5)*noiseStrength)*i*motion}}function sizeRatio(){return canvas.width>=canvas.height?canvas.width:canvas.height}function random(t,e,i){return i?Math.random()*(e-t)+t:Math.floor(Math.random()*(e-t+1))+t}Link.prototype.render=function(){var t,e,i,s;switch(this.stage){case 0:var o=particles[this.verts[this.verts.length-1]];if(o&&o.neighbors&&o.neighbors.length>0){var a=o.neighbors[random(0,o.neighbors.length-1)];-1==this.verts.indexOf(a)&&this.verts.push(a)}else this.stage=3,this.finished=!0;if(this.verts.length>=this.length){for(t=0;t<this.verts.length-1;t++){var l=particles[this.verts[t]],h=particles[this.verts[t+1]],$=l.x-h.x,f=l.y-h.y,d=Math.sqrt($*$+f*f);this.distances.push(d)}this.stage=1}break;case 1:if(this.distances.length>0){for(t=0,s=[];t<this.linked.length;t++)i=position((e=particles[this.linked[t]]).x,e.y,e.z),s.push([i.x,i.y]);var u=1e-5*linkSpeed*canvas.width;this.traveled+=u;var v=this.distances[this.linked.length-1];if(this.traveled>=v)this.traveled=0,this.linked.push(this.verts[this.linked.length]),i=position((e=particles[this.linked[this.linked.length-1]]).x,e.y,e.z),s.push([i.x,i.y]),this.linked.length>=this.verts.length&&(this.stage=2);else{var p,g=particles[this.linked[this.linked.length-1]],_=particles[this.verts[this.linked.length]],x=v-this.traveled,k=(this.traveled*_.x+x*g.x)/v;i=position(k,(this.traveled*_.y+x*g.y)/v,(this.traveled*_.z+x*g.z)/v),s.push([i.x,i.y])}this.drawLine(s)}else this.stage=3,this.finished=!0;break;case 2:if(this.verts.length>1){if(this.fade<linkFade){this.fade++,s=[];var y=(1-this.fade/linkFade)*linkOpacity;for(t=0;t<this.verts.length;t++)i=position((e=particles[this.verts[t]]).x,e.y,e.z),s.push([i.x,i.y]);this.drawLine(s,y)}else this.stage=3,this.finished=!0}else this.stage=3,this.finished=!0;break;default:this.finished=!0}},Link.prototype.drawLine=function(t,e){if("number"!=typeof e&&(e=linkOpacity),t.length>1&&e>0){context.globalAlpha=e,context.beginPath();for(var i=0;i<t.length-1;i++)context.moveTo(t[i][0],t[i][1]),context.lineTo(t[i+1][0],t[i+1][1]);context.strokeStyle="#888",context.lineWidth=lineWidth,context.stroke(),context.closePath(),context.globalAlpha=1}},canvas&&init();