Created
August 16, 2012 12:44
-
-
Save addyosmani/3369869 to your computer and use it in GitHub Desktop.
This was inspired by the Dribbble shot to the left of the canvas by Ramiro Galan, which can be found here: http://dribbble.com/shots/674715-Sparkle-Light-Trail. Some browsers still won't fully clear a canvas all the way with the destination-out globalCom
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
<!-- source image and inspiration from Ramiro Galan on Dribbble: http://dribbble.com/shots/674715-Sparkle-Light-Trail --> | |
<img src="http://dribbble.s3.amazonaws.com/users/36991/screenshots/674715/game.png" /> |
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
/* super inefficient right now, could be improved */ | |
var c = document.createElement('canvas'), | |
ctx = c.getContext('2d'), | |
cw = c.width = 400, | |
ch = c.height = 300, | |
rand = function(a,b){return ~~((Math.random()*(b-a+1))+a);}, | |
dToR = function(degrees){ | |
return degrees * (Math.PI / 180); | |
}, | |
circle = { | |
x: (cw / 2) + 5, | |
y: (ch / 2) + 22, | |
radius: 90, | |
speed: 2, | |
rotation: 0, | |
angleStart: 270, | |
angleEnd: 90, | |
hue: 220, | |
thickness: 18, | |
blur: 25 | |
}, | |
particles = [], | |
particleMax = 100, | |
updateCircle = function(){ | |
if(circle.rotation < 360){ | |
circle.rotation += circle.speed; | |
} else { | |
circle.rotation = 0; | |
} | |
}, | |
renderCircle = function(){ | |
ctx.save(); | |
ctx.translate(circle.x, circle.y); | |
ctx.rotate(dToR(circle.rotation)); | |
ctx.beginPath(); | |
ctx.arc(0, 0, circle.radius, dToR(circle.angleStart), dToR(circle.angleEnd), true); | |
ctx.lineWidth = circle.thickness; | |
ctx.strokeStyle = gradient1; | |
ctx.stroke(); | |
ctx.restore(); | |
}, | |
renderCircleBorder = function(){ | |
ctx.save(); | |
ctx.translate(circle.x, circle.y); | |
ctx.rotate(dToR(circle.rotation)); | |
ctx.beginPath(); | |
ctx.arc(0, 0, circle.radius + (circle.thickness/2), dToR(circle.angleStart), dToR(circle.angleEnd), true); | |
ctx.lineWidth = 2; | |
ctx.strokeStyle = gradient2; | |
ctx.stroke(); | |
ctx.restore(); | |
}, | |
renderCircleFlare = function(){ | |
ctx.save(); | |
ctx.translate(circle.x, circle.y); | |
ctx.rotate(dToR(circle.rotation+185)); | |
ctx.scale(1,1); | |
ctx.beginPath(); | |
ctx.arc(0, circle.radius, 30, 0, Math.PI *2, false); | |
ctx.closePath(); | |
var gradient3 = ctx.createRadialGradient(0, circle.radius, 0, 0, circle.radius, 30); | |
gradient3.addColorStop(0, 'hsla(330, 50%, 50%, .35)'); | |
gradient3.addColorStop(1, 'hsla(330, 50%, 50%, 0)'); | |
ctx.fillStyle = gradient3; | |
ctx.fill(); | |
ctx.restore(); | |
}, | |
renderCircleFlare2 = function(){ | |
ctx.save(); | |
ctx.translate(circle.x, circle.y); | |
ctx.rotate(dToR(circle.rotation+165)); | |
ctx.scale(1.5,1); | |
ctx.beginPath(); | |
ctx.arc(0, circle.radius, 25, 0, Math.PI *2, false); | |
ctx.closePath(); | |
var gradient4 = ctx.createRadialGradient(0, circle.radius, 0, 0, circle.radius, 25); | |
gradient4.addColorStop(0, 'hsla(30, 100%, 50%, .2)'); | |
gradient4.addColorStop(1, 'hsla(30, 100%, 50%, 0)'); | |
ctx.fillStyle = gradient4; | |
ctx.fill(); | |
ctx.restore(); | |
}, | |
createParticles = function(){ | |
if(particles.length < particleMax){ | |
particles.push({ | |
x: (circle.x + circle.radius * Math.cos(dToR(circle.rotation-85))) + (rand(0, circle.thickness*2) - circle.thickness), | |
y: (circle.y + circle.radius * Math.sin(dToR(circle.rotation-85))) + (rand(0, circle.thickness*2) - circle.thickness), | |
vx: (rand(0, 100)-50)/1000, | |
vy: (rand(0, 100)-50)/1000, | |
radius: rand(1, 6)/2, | |
alpha: rand(10, 20)/100 | |
}); | |
} | |
}, | |
updateParticles = function(){ | |
var i = particles.length; | |
while(i--){ | |
var p = particles[i]; | |
p.vx += (rand(0, 100)-50)/750; | |
p.vy += (rand(0, 100)-50)/750; | |
p.x += p.vx; | |
p.y += p.vy; | |
p.alpha -= .01; | |
if(p.alpha < .02){ | |
particles.splice(i, 1) | |
} | |
} | |
}, | |
renderParticles = function(){ | |
var i = particles.length; | |
while(i--){ | |
var p = particles[i]; | |
ctx.beginPath(); | |
ctx.fillRect(p.x, p.y, p.radius, p.radius); | |
ctx.closePath(); | |
ctx.fillStyle = 'hsla(0, 0%, 100%, '+p.alpha+')'; | |
} | |
}, | |
clear = function(){ | |
ctx.globalCompositeOperation = 'destination-out'; | |
ctx.fillStyle = 'rgba(0, 0, 0, .1)'; | |
ctx.fillRect(0, 0, cw, ch); | |
ctx.globalCompositeOperation = 'lighter'; | |
} | |
loop = function(){ | |
clear(); | |
updateCircle(); | |
renderCircle(); | |
renderCircleBorder(); | |
renderCircleFlare(); | |
renderCircleFlare2(); | |
createParticles(); | |
updateParticles(); | |
renderParticles(); | |
} | |
/* Append Canvas */ | |
document.body.appendChild(c); | |
/* Set Constant Properties */ | |
ctx.shadowBlur = circle.blur; | |
ctx.shadowColor = 'hsla('+circle.hue+', 80%, 60%, 1)'; | |
ctx.lineCap = 'round' | |
var gradient1 = ctx.createLinearGradient(0, -circle.radius, 0, circle.radius); | |
gradient1.addColorStop(0, 'hsla('+circle.hue+', 60%, 50%, .25)'); | |
gradient1.addColorStop(1, 'hsla('+circle.hue+', 60%, 50%, 0)'); | |
var gradient2 = ctx.createLinearGradient(0, -circle.radius, 0, circle.radius); | |
gradient2.addColorStop(0, 'hsla('+circle.hue+', 100%, 50%, 0)'); | |
gradient2.addColorStop(.1, 'hsla('+circle.hue+', 100%, 100%, .7)'); | |
gradient2.addColorStop(1, 'hsla('+circle.hue+', 100%, 50%, 0)'); | |
/* Loop It, Loop It Good */ | |
setInterval(loop, 16); |
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
body { | |
background: #000; | |
} | |
img { | |
display: block; | |
float: left; | |
margin: 0 1px 0 0; | |
} | |
canvas { | |
background: #131c35 linear-gradient(#192853, #131c35); | |
display: block; | |
float: left; | |
/* uncomment to test overlay */ | |
/* | |
position: absolute; | |
left: 0; | |
opacity: .5; | |
top: 0; | |
*/ | |
} |
I would love to take the credit for this, but it's just a save from http://codepen.io/jackrugile/pen/Gving (using their save to gist feature). Jack Rugile (guessing the name) was the author and the work looks pretty amazing.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
For those of you who want a quick preview: http://jsfiddle.net/tpdxX/