Created
February 20, 2014 14:53
-
-
Save zzz6519003/9115426 to your computer and use it in GitHub Desktop.
A Pen by Volodymyr.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<canvas id="olympic"></canvas> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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