HTML5 and JavaScript animation that shows the molecular structure of Caffeine. The double bonds in Caffeine are displayed by darkening the lines.
A Pen by Tomasz Foster on CodePen.
HTML5 and JavaScript animation that shows the molecular structure of Caffeine. The double bonds in Caffeine are displayed by darkening the lines.
A Pen by Tomasz Foster on CodePen.
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script> | |
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.9.2/jquery-ui.js"></script> | |
<div class="caffeine"> | |
<div class="startText"> | |
<p>move your mouse here</p> | |
<img src="https://raw.github.com/TomaszFoster/tomaszfoster.github.io/master/img/arrow.png" class="arrow"> | |
</div> | |
<div id="container" style="height:200px;width:200px"></div> | |
<h2>caffeine</h2> | |
</div> | |
<script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v4.5.5.min.js"></script> |
/*This JavaScript is an animation that, upon mouseover, will reveal | |
a caffeine molecule, complete with darker bonds that signify the | |
double bonds. | |
One improvement I'd like to make later would be to assign the ending locations | |
geometrically, versus using key-value pairs for the ending locations. | |
This would also allow me to dynamically name and create tweens based | |
upon the number of keys. Another day... */ | |
//first, let's set the stage | |
var stage = new Kinetic.Stage({ | |
container: 'container', | |
width: 200, | |
height: 200 | |
}); | |
//create a layer in this stage | |
var layer = new Kinetic.Layer({ | |
y: -30, | |
x: 10 | |
}); | |
//hexagon numbers | |
var h1 = 34.4; | |
var h2 = 20; | |
//pentagon numbers | |
var p1 = 12.3; | |
var p2 = 38; | |
var p3 = 23.5; | |
var p4 = 32.4; | |
/* here are the key-value pairs for the ending coordinates.*/ | |
var points = {1:[50, 260, 50, 220], | |
2:[50, 220, 50+h1, 220-h2], | |
3:[50+h1, 220-h2, 50+(2*h1), 220], | |
4:[50+(2*h1), 220, 50+(2*h1), 260], | |
5:[50+(2*h1), 260, 50+h1, 260+h2], | |
6:[50+h1, 260+h2, 50, 260], | |
7:[50, 220, 50-h1, 220-h2], | |
8:[50+h1, 220-h2, 50+h1, 180-h2], | |
9:[50, 260, 50-h1, 260+h2], | |
10:[50+h1, 260+h2, 50+h1, 300+h2], | |
11:[50+(2*h1), 260, 50+(2*h1)+p2, 260+p1], | |
12:[50+(2*h1), 220, 50+(2*h1)+p2, 220-p1], | |
13:[50+(2*h1)+p2, 220-p1, 50+(2*h1)+p2+p3, 240], | |
14:[50+(2*h1)+p2+p3, 240, 50+(2*h1)+p2, 260+p1], | |
15:[50+(2*h1)+p2, 220-p1, 50+(2*h1)+p2+p1, 220-p2-p1] | |
}; | |
//create key-value pairs for the tweens | |
var tweens = {}; | |
/*now, let's make each 'stick' and assign it (almost) the same | |
properties, only variation is in the starting points, where I shift | |
them each by 5 pixels, since they each have a strokeWidth of 5 */ | |
var list = {}; | |
for(i=0;i<15;i++){ | |
var temp = 'stick'+(i+1); | |
list[temp] = new Kinetic.Spline({ | |
points: [60+(i*5), 130, 60+(i*5), 90], //here's the only difference | |
tension: 0.5, | |
opacity: 0.6, | |
stroke: '#FFF', | |
strokeWidth: 5, | |
lineCap: 'round' | |
}); | |
//add each new layer | |
layer.add(list[temp]); | |
var temp = 'stick'+i+'Tween'; | |
//the tweens with single bonds depicted with opacity = 0.6 | |
if (i!=3 && i!=7 && i!=8 && i!=13){ | |
tweens[temp] = new Kinetic.Tween({ | |
node: list['stick'+(i+1)], | |
duration: 1, | |
easing: Kinetic.Easings.EaseOut, | |
y: -100, | |
opacity: 0.5, | |
points: points[i+1] | |
}); | |
}else{ | |
//the tweens with double bonds depicted with opacity = 1.0 | |
tweens[temp] = new Kinetic.Tween({ | |
node: list['stick'+(i+1)], | |
duration: 1, | |
easing: Kinetic.Easings.EaseOut, | |
y: -100, | |
opacity: 1, | |
points: points[i+1] | |
}); | |
} | |
} | |
//now add all the layers to the stage | |
stage.add(layer); | |
var keys = Object.keys(tweens); | |
//on mouseover, play all the tweens | |
stage.getContainer().addEventListener('mouseover', function() { | |
for(i=0;i<15;i++){ | |
tweens[keys[i]].play(); | |
} | |
}); | |
//on mouseout, reverse the tweens | |
stage.getContainer().addEventListener('mouseout', function() { | |
for(i=0;i<16;i++){ | |
tweens[keys[i]].reverse(); | |
} | |
}); | |
// here's the transform for the alternative text | |
$("#container").hover( | |
function(){ | |
$(".altText").animate({ color: "#CCC" }, 2000); | |
$(".startText").animate({ color: "#301E12" }, 1000); | |
$(".arrow").animate({opacity: 0}, 1000); | |
}, | |
function(){ | |
$(".altText").animate({ color: "#301E12" }, 1000); | |
} | |
); | |
body { | |
background: #301E12; | |
} | |
.caffeine { position: absolute; top:50%; left:50%; margin:-200px 0 0 -100px; } | |
.caffeine h2 { | |
font-family: helvetica; | |
font-size: 50px; | |
color:#DDD; | |
text-align: center; | |
text-shadow: 2px 2px #666; | |
margin-top:0px; | |
} | |
.caffeine .altText { | |
font-family: helvetica; | |
font-size: 20px; | |
color:#301E12; | |
text-align: center; | |
} | |
.startText { | |
font-family: helvetica; | |
font-size: 15px; | |
color:#CCC; | |
text-align: center; | |
margin-right: 50px; | |
} | |
.startText img { | |
position: absolute; | |
margin-left: 100px; | |
margin-top: -40px; | |
} | |
.altText { | |
margin-top:-20px; | |
} |