Skip to content

Instantly share code, notes, and snippets.

@mph006
Created June 26, 2016 00:02
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 mph006/dede2101d5394dcc63615f22a70f5d9b to your computer and use it in GitHub Desktop.
Save mph006/dede2101d5394dcc63615f22a70f5d9b to your computer and use it in GitHub Desktop.
D3 Lava Lamp
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js"charset="utf-8"></script>
<link rel="stylesheet" type="text/css" href="//fonts.googleapis.com/css?family=Open+Sans" />
<link rel="stylesheet" type="text/css" href="./lavaLamp.css">
</head>
<body>
<div id="gooContainer">
<div class='podium'></div>
<div class='block'>
<div class='instructions'>Select a Color</div>
<select id="color-select" onchange="changeColor()">
<option value="green" selected="selected">Green</option>
<option value="purple">Purple</option>
<option value="red">Red</option>
<option value="gray">Gray</option>
</select>
</div>
</div>
</body>
<script language="javascript" type="text/javascript" src='./lavaLamp.js'></script>
</html>
body {
text-align: center;
background-color: #fbfbfb;
font-family:"Open Sans";
font-size: 14px;
}
.podium{
position: absolute;
width: 35%;
height: 5%;
left:32%;
bottom:7%;
background-color:black;
border-radius: 5px;
}
.block{
position: absolute;
width: 110px;
height:80px;
left:44.3%;
bottom:10%;
background-color:black;
border-radius: 5px;
}
.instructions{
color:white;
margin-top: 15px;
margin-bottom: 5px;
}
var margin = {top: 10,right: 0,bottom: 50,left: 0};
var width = 700 - margin.left - margin.right - 10,
height = 500 - margin.top - margin.bottom - 20;
//SVG container
var svg = d3.select('#gooContainer')
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
//SVG filter for the gooey effect
//Code taken from http://tympanus.net/codrops/2015/03/10/creative-gooey-effects/
var defs = svg.append("defs");
var filter = defs.append("filter").attr("id","gooeyCodeFilter");
filter.append("feGaussianBlur")
.attr("in","SourceGraphic")
.attr("stdDeviation","10")
//to fix safari: http://stackoverflow.com/questions/24295043/svg-gaussian-blur-in-safari-unexpectedly-lightens-image
.attr("color-interpolation-filters","sRGB")
.attr("result","blur");
filter.append("feColorMatrix")
.attr("in","blur")
.attr("mode","matrix")
.attr("values","1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 19 -9")
.attr("result","gooey");
//Create gradients
var gradients ={
green:["#0AAF00","#00ff0e","#aaff5b","#f7ffa7"],
purple:["#520076","#c53ffe","#e297fe","#f4d6ff"],
red:["#950c14","#fb3930","#fb673c","#fcaa44"],
gray:["#2a2a2a","#545454","#7e7e7e","#d3d3d3"]
}
defs.append("linearGradient")
.attr("id", "lavaGradient")
.attr("gradientUnits", "userSpaceOnUse")
.attr("y1", -height/2*0.85).attr("x1", 0)
.attr("y2", height/2*0.85).attr("x2", 0)
.selectAll("stop")
.data(d3.range(gradients.green.length))
.enter().append("stop")
.attr("offset", function(d,i) { return (i/(gradients.green.length-1)*100) + "%"; })
.attr("stop-color", function(d) { return gradients.green[d]; });
defs.append("clipPath")
.attr("id", "clip")
.append("ellipse")
.attr("cx",width/2)
.attr("cy",height/2)
.attr("rx",width/12)
.attr("ry",height/2);
defs.append("clipPath")
.attr("id", "clip_cap")
.append("ellipse")
.attr("cx",width/2)
.attr("cy",(height/2))
.attr("rx",(width/12)+2)
.attr("ry",(height/2)+2);
svg.append("ellipse")
.attr("class","water")
.attr("cx",width/2)
.attr("cy",height/2)
.attr("rx",width/12)
.attr("ry",height/2)
.style("fill", "#AAD4E0");
//First append a group for the clip path, then a new group that can be transformed
var circleWrapper = svg.append("g")
.attr("clip-path", "url(#clip")
.style("clip-path", "url(#clip)") //make it work in safari
.append("g")
.attr("transform", "translate(" + (width/2) + "," + (height/2) + ")")
.style("filter", "url(#gooeyCodeFilter)");
//Create dataset with random radius
randStart = [];
for(var i = 0; i < 20; i++) {
randStart.push({
r: 15 + Math.random()*10
});
}
var circle = circleWrapper.selectAll(".dots")
.data(randStart)
.enter().append("circle")
.attr("class", "dots")
.attr("cx", 0)
.attr("cy", function(d){return (height/2)-d.r;})
.attr("r", function(d){return d.r})
.style("fill", "url(#lavaGradient)")
.style("opacity", 1)
.each(move);
var footer = circleWrapper.selectAll(".footer")
.data([{r:50}])
.enter().append("circle")
.attr("class", "footer")
.attr("cx", 0)
.attr("cy", function(d){return (height/2)-(d.r)})
.attr("r", function(d){return d.r})
.style("fill", "url(#lavaGradient)")
.style("opacity", 1);
var header = circleWrapper.selectAll(".header")
.data([{r:50}])
.enter().append("circle")
.attr("class", "header")
.attr("cx", 0)
.attr("cy", function(d){return (-height/2)+d.r})
.attr("r", function(d){return d.r})
.style("fill", "url(#lavaGradient)")
.style("opacity", 1);
svg.append("ellipse")
.attr("class","ellipse")
.attr("cx",width/2)
.attr("cy",height/2)
.attr("rx",width/12)
.attr("ry",height/2)
.style("stroke", "#6C6C6C")
.style("stroke-width", "4px")
.style("fill", "none");
svg.append("rect")
.attr("class","cap")
.attr("clip-path", "url(#clip_cap")
.style("clip-path", "url(#clip_cap)") //make it work in safari
.attr("x",width/4)
.attr("y",-10)
.attr("height",75)
.attr("width",width)
.style("fill", "black");
function changeColor(){
var selectedColor = document.getElementById("color-select")
.options[document.getElementById("color-select").selectedIndex].value;
d3.select("#lavaGradient")
.selectAll("stop")
.transition("change-color").duration(3000)
.attr("stop-color", function(d) { return gradients[selectedColor][d]; });
}
function move(d) {
var currenty = parseFloat(d3.select(this).attr("cy"));
var newx = (Math.random() <0.5)?-Math.random()*50:Math.random()*50;
var newy = currenty*-1;
//Transition the circle to its new location
d3.select(this)
.transition("move")
.duration(8000+8000*Math.random())
.ease("easeInQuart")
.attr("cy", newy)
.attr("cx", newx)
.attr("r",function(){return 15 + Math.random()*10})
.each("end", move)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment