|
@@ -1,19 +1,19 @@
|
|
1
|
+/* Sorry, this code is pretty damn ugly. I spend 8 hours 5 days a week refactoring code, I just don't feel like making
|
|
2
|
+ * it better right now. Maybe I'll have enough caffiene in my veins and nothing better to do sometime to put this all
|
|
3
|
+ * into ES2015 modules or something.
|
|
4
|
+ */
|
|
5
|
+// global vars
|
1
|
6
|
var renderer;
|
2
|
7
|
var stage;
|
3
|
8
|
var screenWidth;
|
4
|
9
|
var screenHeight;
|
5
|
10
|
var counter;
|
6
|
11
|
var totalScreenPixels;
|
7
|
|
-var cycleDuration;
|
8
|
12
|
var connectionDistance;
|
9
|
|
-var connectionLimit;
|
10
|
13
|
var pointShiftDistance;
|
11
|
|
-// var colorShiftAmt;
|
12
|
|
-var disconnectedColorShiftAmt;
|
13
|
14
|
var polygon;
|
14
|
15
|
var startPoints;
|
15
|
16
|
var polygonPoints;
|
16
|
|
-var tweeningFns;
|
17
|
17
|
var lastLoop;
|
18
|
18
|
var thisLoop;
|
19
|
19
|
var fps;
|
|
@@ -21,10 +21,22 @@ var fpsGraphic;
|
21
|
21
|
var scrollDelta;
|
22
|
22
|
var pointShiftBiasX;
|
23
|
23
|
var pointShiftBiasY;
|
24
|
|
-var resolution = 1;
|
25
|
|
-var debug = false;
|
26
|
|
-var fpsEnabled = debug;
|
27
|
|
-var allTweeningFns = [
|
|
24
|
+
|
|
25
|
+// global non-configurable vars (modifying these might break stuff)
|
|
26
|
+var click = null;
|
|
27
|
+var hover = null;
|
|
28
|
+var lastHover = null;
|
|
29
|
+var clickEnd = false;
|
|
30
|
+
|
|
31
|
+// global configurable vars
|
|
32
|
+var resolution = 1; // scaling for PIXI renderer
|
|
33
|
+var debug = false; // toggles drawing extra indicators for debugging
|
|
34
|
+var fpsEnabled = debug; // toggles the FPS counter
|
|
35
|
+var cycleDuration = 60; // length of a point's "cycle": number of frames it takes for it to travel to its chosen destination
|
|
36
|
+var connectionLimit = 10; // maximum number of lines drawn from one point to others within connection distance
|
|
37
|
+// colorShiftAmt = 80; // disabled for now
|
|
38
|
+var disconnectedColorShiftAmt = 10; // when a point is alone (not connected), shift RGB values by this amount every tick
|
|
39
|
+var allTweeningFns = [ // array of all possible tweening functions, these are defined below
|
28
|
40
|
linearTweening,
|
29
|
41
|
easeInSine,
|
30
|
42
|
easeOutSine,
|
|
@@ -51,7 +63,8 @@ var allTweeningFns = [
|
51
|
63
|
easeOutBack,
|
52
|
64
|
easeInOutBack
|
53
|
65
|
];
|
54
|
|
-var tweeningSets = {
|
|
66
|
+// sets of tweening functions that I think look good with points randomly choose from them
|
|
67
|
+var tweeningSets = { // numbers refer to indicies into the allTweeningsFns array above
|
55
|
68
|
linear: [0],
|
56
|
69
|
meandering: [1, 2, 3, 4, 5, 6, 7, 8, 9],
|
57
|
70
|
snappy: [10, 11, 12, 13, 14, 15],
|
|
@@ -59,36 +72,37 @@ var tweeningSets = {
|
59
|
72
|
elastic: [19, 20, 21],
|
60
|
73
|
back: [22, 23, 24]
|
61
|
74
|
};
|
62
|
|
-var click = null;
|
63
|
|
-var hover = null;
|
64
|
|
-var lastHover = null;
|
65
|
|
-var clickEnd = false;
|
66
|
|
-var clickPullRateStart = 0.01;
|
67
|
|
-var clickMaxDistStart = 50;
|
68
|
|
-var clickPullRateInc = 0.005;
|
69
|
|
-var clickPullRateMax = 0.3;
|
70
|
|
-var clickMaxDistInc = 2;
|
71
|
|
-var clickMaxDistMax = 5000;
|
|
75
|
+var tweeningFns = tweeningSets.meandering; // the actual set of tweening functions points will randomly choose from
|
|
76
|
+// click effect related config vars
|
|
77
|
+var clickPullRateStart = 0.01; // initial value for the ratio of a point's distance from the click position to travel in one cycle
|
|
78
|
+var clickPullRateInc = 0.005; // amount to increase clickPullRate every tick that a click is held
|
|
79
|
+var clickPullRateMax = 0.5; // maximum value of clickPullRate
|
72
|
80
|
var clickPullRate = clickPullRateStart;
|
|
81
|
+var clickMaxDistStart = 50; // initial value for the effect radius of a click: points this distance from click position will be pulled
|
|
82
|
+var clickMaxDistInc = 2; // amount to increase clickMaxDist every tick that a click is held
|
|
83
|
+var clickMaxDistMax = 5000; // maximum value of clickMaxDist
|
73
|
84
|
var clickMaxDist = clickMaxDistStart;
|
74
|
|
-var clickPullRateEnd = -0.6;
|
75
|
|
-var clickInertiaStart = -0.7;
|
|
85
|
+var clickInertiaStart = -0.7; // initial value of the ratio of point's origin distance from the click position to be added to point's new target
|
76
|
86
|
var clickInertia = clickInertiaStart;
|
77
|
|
-var clickInertiaEnd = 0.3;
|
78
|
|
-var clickTweeningFnStart = null;
|
|
87
|
+var clickTweeningFnStart = null; // initial value of the specific tweening function to assign to points in effect radius (null will not change functions)
|
79
|
88
|
var clickTweeningFn = clickTweeningFnStart;
|
80
|
|
-var clickTweeningFnEnd = 12;
|
81
|
|
-var hoverPushRate = -0.05;
|
82
|
|
-var hoverInertia = 0.8;
|
83
|
|
-var hoverMaxDistStart = 75;
|
84
|
|
-var hoverMaxDistMax = 1000;
|
|
89
|
+var clickColorShiftAmt = disconnectedColorShiftAmt * 3; // amount of RGB color value to shift for each point in effect radius
|
|
90
|
+var clickPullRateEnd = -0.6; // value of clickPullRate during tick after end of click (for "rebound" effect)
|
|
91
|
+var clickInertiaEnd = 0.3; // value of clickInertia during tick after end of click
|
|
92
|
+var clickTweeningFnEnd = 12; // value of clickTweeningFn during tick after end of click (number refers to index into allTweeningsFns)
|
|
93
|
+// hover effect related config vars
|
|
94
|
+var hoverPushRate = -0.05; // ratio of a point's distance from the hover position to travel in one cycle
|
|
95
|
+var hoverInertia = 0.8; // ratio of a point's origin distance from the click position to be added to point's new target
|
|
96
|
+var hoverMaxDistStart = 75; // initial value for the effect radius of a hover: points this distance from hover position will be pushed
|
|
97
|
+var hoverMaxDistMax = 1000; // maximum value of hoverMaxDist
|
85
|
98
|
var hoverMaxDist = hoverMaxDistStart;
|
86
|
|
-var hoverTweeningFn = 5;
|
|
99
|
+var hoverTweeningFn = 5; // specific tweening function to assign to points in effect radius
|
87
|
100
|
|
88
|
|
-function randomInt (min, max) {
|
89
|
|
- // inclusive of min and max
|
90
|
|
- return Math.floor(Math.random() * (max - min + 1)) + min;
|
91
|
|
-}
|
|
101
|
+/* TWEENING FUNCTIONS */
|
|
102
|
+
|
|
103
|
+// These are modified versions of the jquery easing functions:
|
|
104
|
+// https://github.com/danro/jquery-easing/blob/master/jquery.easing.js
|
|
105
|
+// See license in LICENSE-3RD-PARTY.txt
|
92
|
106
|
|
93
|
107
|
/* eslint-disable no-unused-vars */
|
94
|
108
|
function linearTweening (t, b, c, d) {
|
|
@@ -225,6 +239,13 @@ function easeInOutCirc (t, b, c, d) {
|
225
|
239
|
}
|
226
|
240
|
/* eslint-enable no-unused-vars */
|
227
|
241
|
|
|
242
|
+/* UTILITY FUNCTIONS */
|
|
243
|
+
|
|
244
|
+function randomInt (min, max) {
|
|
245
|
+ // inclusive of min and max
|
|
246
|
+ return Math.floor(Math.random() * (max - min + 1)) + min;
|
|
247
|
+}
|
|
248
|
+
|
228
|
249
|
// from: http://stackoverflow.com/a/5624139
|
229
|
250
|
// modified to return integer literal
|
230
|
251
|
function rgbToHex (color) {
|
|
@@ -301,18 +322,40 @@ function getMousePos (evt, res) {
|
301
|
322
|
}
|
302
|
323
|
}
|
303
|
324
|
|
|
325
|
+function distance (point1, point2) {
|
|
326
|
+ var a = point1[0] - point2[0];
|
|
327
|
+ var b = point1[1] - point2[1];
|
|
328
|
+ return Math.sqrt(a * a + b * b);
|
|
329
|
+}
|
|
330
|
+
|
304
|
331
|
function distancePos (point1, point2) {
|
|
332
|
+ // TODO: refactor distance and distancePos to the same function
|
305
|
333
|
var a = point1.x - point2.x;
|
306
|
334
|
var b = point1.y - point2.y;
|
307
|
335
|
return Math.sqrt(a * a + b * b);
|
308
|
336
|
}
|
309
|
337
|
|
310
|
|
-function distance (point1, point2) {
|
311
|
|
- var a = point1[0] - point2[0];
|
312
|
|
- var b = point1[1] - point2[1];
|
313
|
|
- return Math.sqrt(a * a + b * b);
|
|
338
|
+// eslint-disable-next-line no-unused-vars
|
|
339
|
+function shiftPointCounter (original, maxShiftAmt) {
|
|
340
|
+ var shiftAmt = randomInt(maxShiftAmt * -1, 0);
|
|
341
|
+ var newCounter = original + shiftAmt;
|
|
342
|
+ if (newCounter < 0) {
|
|
343
|
+ newCounter = cycleDuration + shiftAmt;
|
|
344
|
+ }
|
|
345
|
+ return newCounter;
|
314
|
346
|
}
|
315
|
347
|
|
|
348
|
+function relativeCounter (counter, targetStart) {
|
|
349
|
+ /* Return current progress of point in its cycle. AKA. what count would be if cycleDuration == targetStart */
|
|
350
|
+ var relCounter = counter - targetStart;
|
|
351
|
+ if (relCounter < 0) {
|
|
352
|
+ return cycleDuration + relCounter;
|
|
353
|
+ }
|
|
354
|
+ return relCounter;
|
|
355
|
+}
|
|
356
|
+
|
|
357
|
+/* POINT OPERATION FUNCTIONS */
|
|
358
|
+
|
316
|
359
|
function getRandomPoints (numPoints, maxX, maxY, tweeningFns) {
|
317
|
360
|
var i, x, y, color, cycleStart, easingFn;
|
318
|
361
|
var points = [];
|
|
@@ -327,16 +370,6 @@ function getRandomPoints (numPoints, maxX, maxY, tweeningFns) {
|
327
|
370
|
return points;
|
328
|
371
|
}
|
329
|
372
|
|
330
|
|
-// eslint-disable-next-line no-unused-vars
|
331
|
|
-function shiftPointCounter (original, maxShiftAmt) {
|
332
|
|
- var shiftAmt = randomInt(maxShiftAmt * -1, 0);
|
333
|
|
- var newCounter = original + shiftAmt;
|
334
|
|
- if (newCounter < 0) {
|
335
|
|
- newCounter = cycleDuration + shiftAmt;
|
336
|
|
- }
|
337
|
|
- return newCounter;
|
338
|
|
-}
|
339
|
|
-
|
340
|
373
|
function shiftPoints (points, maxShiftAmt, counter, tweeningFns) {
|
341
|
374
|
var i, shiftX, shiftY, candidateX, candidateY;
|
342
|
375
|
for (i = 0; i < points.original.length; i++) {
|
|
@@ -377,35 +410,42 @@ function shiftPoints (points, maxShiftAmt, counter, tweeningFns) {
|
377
|
410
|
}
|
378
|
411
|
|
379
|
412
|
function pullPoints (points, clickPos, pullRate, inertia, maxDist, counter, resetPoints, tweeningFn) {
|
380
|
|
- var xDist, yDist, xTraveled, yTraveled;
|
|
413
|
+ var targetXDiff, targetYDiff, originXDiff, originYDiff;
|
381
|
414
|
for (var i = 0; i < points.target.length; i++) {
|
382
|
|
- xDist = clickPos.x - points.target[i][0];
|
383
|
|
- yDist = clickPos.y - points.target[i][1];
|
384
|
|
- xTraveled = clickPos.x - points.original[i][0];
|
385
|
|
- yTraveled = clickPos.y - points.original[i][1];
|
386
|
|
- if (Math.abs(xDist) <= maxDist && Math.abs(yDist) <= maxDist) {
|
|
415
|
+ targetXDiff = clickPos.x - points.target[i][0];
|
|
416
|
+ targetYDiff = clickPos.y - points.target[i][1];
|
|
417
|
+ originXDiff = clickPos.x - points.original[i][0];
|
|
418
|
+ originYDiff = clickPos.y - points.original[i][1];
|
|
419
|
+ if (Math.abs(targetXDiff) <= maxDist && Math.abs(targetYDiff) <= maxDist) { // point is within effect radius
|
387
|
420
|
if (resetPoints) {
|
388
|
421
|
// Good for changing directions, reset the points original positions to their current positions
|
389
|
422
|
points.original[i][0] = points.tweened[i][0];
|
390
|
423
|
points.original[i][1] = points.tweened[i][1];
|
391
|
424
|
}
|
392
|
|
- points.target[i][0] += Math.round((xDist + (inertia * xTraveled)) * pullRate);
|
393
|
|
- points.target[i][1] += Math.round((yDist + (inertia * yTraveled)) * pullRate);
|
394
|
|
- points.target[i][3] = shiftColor(points.original[i][3], disconnectedColorShiftAmt * 3);
|
|
425
|
+ points.target[i][0] += Math.round((targetXDiff + (inertia * originXDiff)) * pullRate); // pull X
|
|
426
|
+ points.target[i][1] += Math.round((targetYDiff + (inertia * originYDiff)) * pullRate); // pull Y
|
|
427
|
+ // shift the color of each point in effect radius by some configurable amount
|
|
428
|
+ points.target[i][3] = shiftColor(points.original[i][3], clickColorShiftAmt);
|
395
|
429
|
if (tweeningFn !== null) {
|
396
|
|
- // Also twitch the tweening function for all affected points for additional effect
|
|
430
|
+ // Also switch the tweening function for all affected points for additional effect
|
|
431
|
+ // The tweening function will be re-assigned at the start of the point's next cycle
|
397
|
432
|
points.target[i][4] = tweeningFn;
|
398
|
433
|
}
|
399
|
434
|
}
|
400
|
|
- // TODO: define these magic numbers somewhere
|
401
|
435
|
// If this point's cycle is near it's end, bump it up some ticks to make the animation smoother
|
402
|
|
- if (relativeCounter(points.target[i][2]) > cycleDuration - 10) {
|
|
436
|
+ if (relativeCounter(points.target[i][2]) > Math.roundcycleDuration - 10) {
|
403
|
437
|
points.target[i][2] = (points.target[i][2] + Math.round(cycleDuration / 2)) % cycleDuration;
|
404
|
438
|
}
|
405
|
439
|
}
|
406
|
440
|
}
|
407
|
441
|
|
408
|
442
|
function redistributeCycles (points, oldCycleDuration, cycleDuration) {
|
|
443
|
+ /* Given old and new cycleDuration, re-assign points' cycle starts that expand/compress to fit the new range in a
|
|
444
|
+ * way that ensures the current progress of the point in its cycle is around the same percentage (so that the point
|
|
445
|
+ * does not jump erratically back or forward in it's current trajectory).
|
|
446
|
+ */
|
|
447
|
+ // FIXME: if cycleDuration goes to 1 all points' cycles will be compressed to about the same value, and when
|
|
448
|
+ // cycleDuration goes back up, the values will remain the same, making the points appear to dance in sync.
|
409
|
449
|
var progress;
|
410
|
450
|
for (var i = 0; i < points.original.length; i++) {
|
411
|
451
|
progress = points.target[i][2] / oldCycleDuration;
|
|
@@ -414,13 +454,7 @@ function redistributeCycles (points, oldCycleDuration, cycleDuration) {
|
414
|
454
|
return points;
|
415
|
455
|
}
|
416
|
456
|
|
417
|
|
-function relativeCounter (counter, targetStart) {
|
418
|
|
- var relCounter = counter - targetStart;
|
419
|
|
- if (relCounter < 0) {
|
420
|
|
- return cycleDuration + relCounter;
|
421
|
|
- }
|
422
|
|
- return relCounter;
|
423
|
|
-}
|
|
457
|
+/* DRAW FUNCTIONS */
|
424
|
458
|
|
425
|
459
|
function drawPolygon (polygon, points, counter, tweeningFns) {
|
426
|
460
|
var i, j, easingFn, relativeCount, avgColor, shadedColor, connectionCount, dist, connectivity;
|
|
@@ -478,6 +512,8 @@ function drawPolygon (polygon, points, counter, tweeningFns) {
|
478
|
512
|
}
|
479
|
513
|
}
|
480
|
514
|
|
|
515
|
+/* MAIN LOOP */
|
|
516
|
+
|
481
|
517
|
function loop () {
|
482
|
518
|
screenWidth = document.documentElement.clientWidth;
|
483
|
519
|
screenHeight = document.documentElement.clientHeight;
|
|
@@ -487,21 +523,24 @@ function loop () {
|
487
|
523
|
|
488
|
524
|
if (click !== null) {
|
489
|
525
|
if (clickEnd) {
|
|
526
|
+ // apply "rebound" effects
|
490
|
527
|
clickPullRate = clickPullRateEnd;
|
491
|
528
|
clickInertia = clickInertiaEnd;
|
492
|
529
|
clickTweeningFn = clickTweeningFnEnd;
|
493
|
530
|
if (debug) {
|
|
531
|
+ // draw debug click effect radius red color when clickEnd == true
|
494
|
532
|
polygon.lineStyle(1, 0xDC143C, 1);
|
495
|
533
|
polygon.drawCircle(click.x, click.y, clickMaxDist);
|
496
|
534
|
}
|
497
|
535
|
} else {
|
498
|
536
|
if (debug) {
|
|
537
|
+ // draw click effect radius blue when debug is on
|
499
|
538
|
polygon.lineStyle(1, 0x483D8B, 1);
|
500
|
539
|
polygon.drawCircle(click.x, click.y, clickMaxDist);
|
501
|
540
|
}
|
502
|
541
|
}
|
503
|
542
|
|
504
|
|
- // a pointer event is occuring and needs to affect the points
|
|
543
|
+ // a pointer event is occuring and needs to affect the points in effect radius
|
505
|
544
|
pullPoints(polygonPoints, click, clickPullRate, clickInertia, clickMaxDist, counter, clickEnd, clickTweeningFn);
|
506
|
545
|
|
507
|
546
|
// slightly increase effect amount for next loop if click is still occuring
|
|
@@ -513,6 +552,7 @@ function loop () {
|
513
|
552
|
}
|
514
|
553
|
|
515
|
554
|
if (clickEnd) {
|
|
555
|
+ // done with rebound effect, re-initialize everything to prepare for next click
|
516
|
556
|
click = null;
|
517
|
557
|
clickEnd = false;
|
518
|
558
|
clickMaxDist = clickMaxDistStart;
|
|
@@ -522,19 +562,23 @@ function loop () {
|
522
|
562
|
}
|
523
|
563
|
} else if (hover !== null) {
|
524
|
564
|
if (lastHover !== null) {
|
|
565
|
+ // hover effect radius grows bigger the faster the mouse moves
|
525
|
566
|
hoverMaxDist += Math.min(Math.round(distancePos(hover, lastHover)), hoverMaxDistMax);
|
526
|
567
|
}
|
527
|
568
|
if (debug) {
|
|
569
|
+ // draw hover effect radius yellow when debug is on
|
528
|
570
|
polygon.lineStyle(1, 0xBDB76B, 1);
|
529
|
571
|
polygon.drawCircle(hover.x, hover.y, hoverMaxDist);
|
530
|
572
|
}
|
531
|
573
|
|
|
574
|
+ // a hover event is occuring and needs to affect the points in effect radius
|
532
|
575
|
pullPoints(polygonPoints, hover, hoverPushRate, hoverInertia, hoverMaxDist, counter, false, hoverTweeningFn);
|
533
|
576
|
|
534
|
577
|
hoverMaxDist = hoverMaxDistStart;
|
535
|
578
|
lastHover = hover;
|
536
|
579
|
}
|
537
|
580
|
|
|
581
|
+ // TODO: it would be cool to fill in triangles
|
538
|
582
|
// polygon.beginFill(0x00FF00);
|
539
|
583
|
drawPolygon(polygon, polygonPoints, counter, tweeningFns);
|
540
|
584
|
// polygon.endFill();
|
|
@@ -549,12 +593,9 @@ function loop () {
|
549
|
593
|
lastLoop = thisLoop;
|
550
|
594
|
}
|
551
|
595
|
|
|
596
|
+ // points that have reached the end of their cycles need new targets
|
552
|
597
|
polygonPoints = shiftPoints(polygonPoints, pointShiftDistance, counter, tweeningFns);
|
553
|
598
|
|
554
|
|
- // var mousePosition = renderer.plugins.interaction.mouse.global;
|
555
|
|
- // triangle.x = mousePosition.x;
|
556
|
|
- // triangle.y = mousePosition.y;
|
557
|
|
-
|
558
|
599
|
// If user scrolled, modify cycleDuration by amount scrolled
|
559
|
600
|
if (scrollDelta !== 0) {
|
560
|
601
|
var oldCycleDuration = cycleDuration;
|
|
@@ -589,14 +630,9 @@ function loopStart () {
|
589
|
630
|
|
590
|
631
|
counter = 0;
|
591
|
632
|
totalScreenPixels = screenWidth + screenHeight;
|
592
|
|
- cycleDuration = 60;
|
593
|
633
|
connectionDistance = Math.min(Math.round(totalScreenPixels / 16), 75);
|
594
|
|
- connectionLimit = 10;
|
595
|
634
|
pointShiftDistance = Math.round(totalScreenPixels / 45);
|
596
|
|
- // colorShiftAmt = 80;
|
597
|
|
- disconnectedColorShiftAmt = 10;
|
598
|
635
|
polygon = new window.PIXI.Graphics();
|
599
|
|
- tweeningFns = tweeningSets.meandering;
|
600
|
636
|
startPoints = getRandomPoints(Math.round(totalScreenPixels / 6), screenWidth, screenHeight, tweeningFns);
|
601
|
637
|
polygonPoints = {
|
602
|
638
|
original: startPoints,
|
|
@@ -712,7 +748,7 @@ window.addEventListener('keydown', function (e) {
|
712
|
748
|
fpsEnabled = true;
|
713
|
749
|
lastLoop = new Date();
|
714
|
750
|
}
|
715
|
|
- } else if (e.keyCode === 68) {
|
|
751
|
+ } else if (e.keyCode === 68) { // d
|
716
|
752
|
// toggle debug
|
717
|
753
|
if (debug) {
|
718
|
754
|
if (fpsEnabled) {
|