Skip to content

Instantly share code, notes, and snippets.

@zzz6519003
Created February 20, 2014 14:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zzz6519003/9115426 to your computer and use it in GitHub Desktop.
Save zzz6519003/9115426 to your computer and use it in GitHub Desktop.
A Pen by Volodymyr.
<canvas id="olympic"></canvas>
window.requestAnimationFrame =
window.__requestAnimationFrame ||
window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
(function () {
return function (callback, element) {
var lastTime = element.__lastTime;
if (lastTime === undefined) {
lastTime = 0;
}
var currTime = Date.now();
var timeToCall = Math.max(1, 33 - (currTime - lastTime));
window.setTimeout(callback, timeToCall);
element.__lastTime = currTime + timeToCall;
};
})();
window.isDevice = (/android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(((navigator.userAgent || navigator.vendor || window.opera)).toLowerCase()));
var loaded = false;
var scaleAndTranslate = function (pos, sx, sy, dx, dy) {
return [dx + pos[0] * sx, dy + pos[1] * sy];
};
var randInt = function (mean, wide) {
var t = ~~(wide * Math.random() + mean - wide * .5);
return t < 0 ? 0 : (t > 100 ? 100 : t);
};
var olympicConfig = {
c: [
[222, 100, 27],
[0, 0, 30],
[0, 80, 48],
[56, 100, 52],
[146, 88, 26]
],
customizeParticle: function (particleClusters, pointClusters, clusterIndex, particle, width, height) {
var points = pointClusters[clusterIndex].points;
particle.speed = Math.random()*.7 + 0.5;
particle.q = points[~~(Math.random() * points.length)];
particle.force = 0.2 * Math.random() + 0.7;
var c = this.c[clusterIndex];
particle.f = "hsla(" + c[0] + "," + randInt(c[1], 10) + "%," + randInt(c[2], 10) + "%,.9)";
var x = Math.random() * width;
var y = Math.random() * height;
var traceCount = window.isDevice ? 20 : 80;
for (var j = 0; j < traceCount; j++) particle.trace[j] = {x: x, y: y};
},
_circlePosition: function (rad) {
var k = Math.sin(rad * 10) / 40 + 1;
return [k * Math.cos(rad), k * Math.sin(rad)];
},
buildOriginPoints: function () {
var i;
var classes = [
{id: 0, points: [], origin: [0,0]},
{id: 1, points: [], origin: [0,0]},
{id: 2, points: [], origin: [0,0]},
{id: 3, points: [], origin: [0,0]},
{id: 4, points: [], origin: [0,0]}
];
var dr = window.isDevice ? 0.3 : 0.6;
var dx = -30, r = 100;
var dh = (2 * r - (dx + 70)) * Math.sqrt(3) / 4;
var dw = 2 * r - dx;
for (i = 0; i < Math.PI * 2; i += dr) {
classes[0].points.push({
class: classes[0],
point: scaleAndTranslate(this._circlePosition(i), r, r, -dw, -dh)
})
}
for (i = 0; i < Math.PI * 2; i += dr) {
classes[1].points.push({
class: classes[1],
point: scaleAndTranslate(this._circlePosition(i), r, r, 0, -dh)
});
}
for (i = 0; i < Math.PI * 2; i += dr) {
classes[2].points.push({
class: classes[2],
point: scaleAndTranslate(this._circlePosition(i), r, r, dw, -dh)
});
}
for (i = 0; i < Math.PI * 2; i += dr) {
classes[3].points.push({
class: classes[3],
point: scaleAndTranslate(this._circlePosition(i), r, r, -r + dx / 2, dh)
});
}
for (i = 0; i < Math.PI * 2; i += dr) {
classes[4].points.push({
class: classes[4],
point: scaleAndTranslate(this._circlePosition(i), r, r, r - dx / 2, dh)
});
}
return classes;
},
traceK: 0.7,
timeDelta: 0.005,
canvasScale: (window.isDevice ? 0.5 : 1),
probabilityOtherToRandOwnerCluster: 0.05,
probabilityOtherToRandRandCluster: 0.001,
probabilityOwnerToRandOwnerCluster: 0.0,
probabilityOwnerToRandRandCluster: 0.001
};
var init = function () {
if (loaded) return;
loaded = true;
var config = olympicConfig;
var canvas = document.getElementById('olympic');
var ctx = canvas.getContext('2d');
var width = canvas.width = config.canvasScale * innerWidth;
var height = canvas.height = config.canvasScale * innerHeight;
var scale = Math.min(width / 1000, height / 1000);
ctx.fillStyle = "rgba(250,250,250,1)";
ctx.fillRect(0, 0, width, height);
var initCopy = function (targetClusters) {
var clusters = [];
for (var k = 0; k < targetClusters.length; k++) {
clusters[k] = {
id: targetClusters[k].id,
points: []
};
var points = targetClusters[k].points;
for (var i = 0; i < points.length; i++) {
clusters[k].points[i] = {
class: clusters[k],
point: [points[i].point[0], points[i].point[1]]
};
}
}
return clusters;
};
var pulse = function (targetClusters, originClusters, kx, ky) {
for (var k = 0; k < targetClusters.length; k++) {
var points = targetClusters[k].points;
var originPoints = originClusters[k].points;
for (var i = 0; i < points.length; i++) {
points[i].point[0] = kx * (originPoints[i].point[0]) + width / 2;
points[i].point[1] = ky * (originPoints[i].point[1]) + height / 2;
}
}
};
var buildParticlesClusters = function (targetClusters) {
var clusters = [];
for (var k = 0; k < targetClusters.length; k++) {
clusters[k] = {
id: targetClusters[k].id,
points: []
};
var points = targetClusters[k].points;
for (var i = 0; i < points.length; i++) {
var e = {
class: clusters[k],
vx: 0,
vy: 0,
speed: 1,
q: points[i],
D: 2 * (i % 2) - 1,
force: 0.8,
f: "hsla(0,0%,50%,.3)",
trace: [
{x: points[i].point[0], y: points[i].point[1]}
]
};
config.customizeParticle(clusters, targetClusters, k, e, width, height);
clusters[k].points[i] = e;
}
}
return clusters;
};
var pointsOrigin = config.buildOriginPoints();
var targetPoints = initCopy(pointsOrigin);
pulse(targetPoints, pointsOrigin, scale, scale);
var e = buildParticlesClusters(targetPoints);
window.addEventListener('resize', function () {
width = canvas.width = config.canvasScale * innerWidth;
height = canvas.height = config.canvasScale * innerHeight;
ctx.fillStyle = "rgba(250,250,250,1)";
ctx.fillRect(0, 0, width, height);
scale = Math.min(width / 1000, height / 1000);
pulse(targetPoints, pointsOrigin, scale, scale);
});
var setRandOwnerCluster = function (particle) {
var clusterPoints = targetPoints[particle.class.id].points;
particle.q = clusterPoints[~~(Math.random() * clusterPoints.length)];
};
var setRandRandCluster = function (particle) {
var clusterPoints = targetPoints[~~(Math.random() * targetPoints.length)].points;
particle.q = clusterPoints[~~(Math.random() * clusterPoints.length)];
};
var setMoveOnCluster = function (particle) {
var points = particle.q.class.points;
var localIndex = points.indexOf(particle.q);
localIndex += (particle.D + points.length);
localIndex %= points.length;
particle.q = points[localIndex];
};
var draw = function () {
for (var j = 0; j < e.length; j++) {
var particles = e[j].points;
for (var i = particles.length; i--;) {
var u = particles[i], k;
var dx = u.trace[0].x - u.q.point[0];
var dy = u.trace[0].y - u.q.point[1];
var length = Math.sqrt(dx * dx + dy * dy);
u.vx += -dx / length * u.speed;
u.vy += -dy / length * u.speed;
u.trace[0].x += u.vx;
u.trace[0].y += u.vy;
u.vx *= u.force;
u.vy *= u.force;
for (k = 0; k < u.trace.length - 1;) {
var T = u.trace[k];
var N = u.trace[++k];
N.x -= config.traceK * (N.x - T.x);
N.y -= config.traceK * (N.y - T.y);
}
var circleIndex = u.class.id;
var targetCircleIndex = u.q.class.id;
if (10 > length) {
var h = Math.random();
if (targetCircleIndex != circleIndex) {
if (h < config.probabilityOtherToRandOwnerCluster) {
setRandOwnerCluster(u);
}
else if (h < (config.probabilityOtherToRandOwnerCluster + config.probabilityOtherToRandRandCluster)) {
setRandRandCluster(u);
}
else{
if (0.99 < Math.random()) u.D *= -1;
setMoveOnCluster(u);
}
}
else {
if (h < config.probabilityOwnerToRandOwnerCluster) {
setRandOwnerCluster(u);
}
else if (h < (config.probabilityOwnerToRandOwnerCluster + config.probabilityOwnerToRandRandCluster)) {
setRandRandCluster(u);
}
else {
if (0.99 < Math.random()) u.D *= -1;
setMoveOnCluster(u);
}
}
}
ctx.fillStyle = u.f;
for (k = 0; k < u.trace.length; k++) {
ctx.fillRect(u.trace[k].x, u.trace[k].y, 1, 1);
}
}
}
};
var timeStart = Date.now();
var title = "Faster, Higher, Stronger.";
var loop = function () {
ctx.fillStyle = "rgba(250,250,250,.3)";//"rgba(0,0,0,.1)";
ctx.fillRect(0, 0, width, height);
draw();
if (Date.now() - timeStart > 2000) {
var t = Date.now() - timeStart - 2000;
var a = .5 * Math.min(t, 1000) / 1000;
ctx.fillStyle = "rgba(10,10,10," + a + ")";
ctx.font = (~~(50 * scale)) + "px Georgia";
ctx.textAlign = 'center';
ctx.fillText(title, width / 2, height / 2 + 300 * scale);
ctx.fill();
}
window.requestAnimationFrame(loop, canvas);
};
loop();
};
var s = document.readyState;
if (s === 'complete' || s === 'loaded' || s === 'interactive') init();
else document.addEventListener('DOMContentLoaded', init, false);
canvas {
position: absolute;
left:0;
top: 0;
width: 100%;
height: 100%;
background-color: rgba(250,250,250,.2);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment