|
<!DOCTYPE html> |
|
<html> |
|
<head> |
|
<meta charset="utf-8"> |
|
|
|
<!-- D3.js --> |
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js" charset="utf-8"></script> |
|
|
|
</head> |
|
<body> |
|
|
|
<div id="chart" style="text-align: center;"></div> |
|
|
|
<script language="javascript" type="text/javascript"> |
|
|
|
/////////////////////////////////////////////////////////////////////////// |
|
//////////////////// Set up and initiate svg containers /////////////////// |
|
/////////////////////////////////////////////////////////////////////////// |
|
|
|
var margin = { |
|
top: 10, |
|
right: 10, |
|
bottom: 10, |
|
left: 10 |
|
}; |
|
var width = 400, |
|
height = 400; |
|
|
|
//SVG container |
|
var svg = d3.select('#chart') |
|
.append("svg") |
|
.attr("width", width + margin.left + margin.right) |
|
.attr("height", height + margin.top + margin.bottom) |
|
.append("g") |
|
.attr("transform", "translate(" + (margin.left + width/2) + "," + (margin.top + height/2) + ")"); |
|
|
|
/////////////////////////////////////////////////////////////////////////// |
|
///////////////////////////// Create filter /////////////////////////////// |
|
/////////////////////////////////////////////////////////////////////////// |
|
|
|
//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"); |
|
//If you want the end shapes to be exactly the same size as without the filter |
|
//add the feComposite below. However this will result in a less beautiful gooey effect |
|
filter.append("feBlend") |
|
.attr("in","SourceGraphic") |
|
.attr("in2","gooey"); |
|
//Instead of the feBlend, you can do feComposite. This will also place a sharp image on top |
|
//But it will result in smaller circles |
|
// filter.append("feComposite") //feBlend |
|
// .attr("in","SourceGraphic") |
|
// .attr("in2","gooey") |
|
// .attr("operator","atop"); |
|
|
|
/////////////////////////////////////////////////////////////////////////// |
|
/////////////////////////// Create circles //////////////////////////////// |
|
/////////////////////////////////////////////////////////////////////////// |
|
|
|
//Create scale |
|
var xScale = d3.scale.linear() |
|
.domain([-1.25, 1.25]) |
|
.range([-width/2, width/2]); |
|
|
|
//Create a wrapper for the circles that has the Gooey effect applied to it |
|
var circleWrapper = svg.append("g") |
|
.style("filter", "url(#gooeyCodeFilter)"); |
|
|
|
//Create the circles that will move out and in the center circle |
|
var steps = 14; |
|
var colors = ["#F95B34", "#EE3E64", "#F36283", "#FF9C34", "#EBDE52", "#B7D84B", "#44ACCF"]; |
|
var flyCircleData = []; |
|
for (var i = 0; i < steps; i++) { |
|
flyCircleData.push({ |
|
fixedAngle: (i/steps)*(2*Math.PI), |
|
randomAngle: (i/steps)*(2*Math.PI), |
|
speed: Math.random() * 7000 + 3000, |
|
r: Math.floor(Math.random() * 20 + 15), |
|
color: colors[i%colors.length] |
|
}) |
|
}//for i |
|
|
|
//Set up the circles |
|
var flyCircles = circleWrapper.selectAll(".flyCircle") |
|
.data(flyCircleData) |
|
.enter().append("circle") |
|
.attr("class", "flyCircle") |
|
.style("fill", function(d) { return d.color; }) |
|
.attr("cy", 0) |
|
.attr("cx", 0) |
|
.attr("r", 0) |
|
.transition().duration(500)//.delay(function(d,i) { return i*50; }) |
|
.attr("cy", function(d) { return xScale(Math.sin(d.fixedAngle)); }) |
|
.attr("cx", function(d) { return xScale(Math.cos(d.fixedAngle)); }) |
|
.attr("r", function(d) { return d.r; }) |
|
.each("end", goRound); |
|
|
|
//Continuously moves the circles with different speeds |
|
function goRound(d) { |
|
d3.select(this) |
|
.transition().duration(function(d) { return d.speed; }) |
|
.ease("linear") |
|
.attrTween("transform", function() { return d3.interpolateString("rotate(0)", "rotate(360)"); }) |
|
.each("end", goRound); |
|
}//function goRound |
|
|
|
</script> |
|
|
|
</body> |
|
</html> |