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.
- checksums.yaml +4 -4
- data/README.md +16 -3
- data/_includes/footer.html +2 -3
- data/_includes/head.html +37 -8
- data/_includes/pagination.html +1 -1
- data/_includes/post.html +2 -2
- data/_includes/search_event.html +1 -2
- data/_includes/sidebar.html +6 -3
- data/_layouts/page.html +5 -6
- data/_sass/darkmode.scss +115 -122
- data/_sass/layout.scss +40 -40
- data/_sass/navigation.scss +133 -138
- data/_sass/pagination.scss +198 -211
- data/_sass/post.scss +550 -558
- data/_sass/search.scss +185 -204
- data/_sass/sidebar.scss +253 -254
- data/_sass/toc.scss +41 -41
- data/assets/css/404.scss +35 -35
- data/assets/css/highlight.min.css +2 -0
- data/assets/css/style.scss +22 -44
- data/assets/fonts/Lato-Regular.woff2 +0 -0
- data/assets/fonts/NunitoSans-Regular.woff2 +0 -0
- data/assets/fonts/Righteous-Regular.woff2 +0 -0
- data/assets/img/icon/house.webp +0 -0
- data/assets/img/loading.webp +0 -0
- data/assets/img/profile.webp +0 -0
- data/assets/js/background.js +1 -700
- data/assets/js/common.js +194 -21
- data/assets/js/post.js +172 -121
- data/assets/js/subject.js +1 -1
- metadata +22 -12
- data/assets/css/fonts.scss +0 -29
- data/assets/css/highlight-dark.min.css +0 -1
- data/assets/css/highlight-default.min.css +0 -1
- data/assets/fonts/Lato-Regular.ttf +0 -0
- data/assets/fonts/NunitoSans-Regular.ttf +0 -0
- data/assets/fonts/Righteous-Regular.ttf +0 -0
- data/assets/img/profile.jpg +0 -0
- data/assets/js/search.js +0 -168
- data/assets/js/sweet-scroll.min.js +0 -2
- data/assets/js/tocbot.min.js +0 -1
data/assets/js/background.js
CHANGED
@@ -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();
|