[ Launch: blobular droplets ] 2e3ccdfa5d8d285b833d by enjalot
[ Launch: blobular droplets ] f33a0503ea923d090019 by IPWright83
[ Launch: blobular droplets ] 202706c4d6f00e9397fa by IPWright83
[ Launch: blobular BADGE ] e0fdfe9987041c857e11 by enjalot
[ Launch: blobular BADGE ] 9680733 by enjalot
-
-
Save enjalot/2e3ccdfa5d8d285b833d to your computer and use it in GitHub Desktop.
blobular droplets
This file contains 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
{"editor_editor":{"coffee":false,"vim":true,"emacs":false,"width":528,"height":680,"hide":false},"description":"blobular droplets","endpoint":"","display":"svg","public":true,"require":[],"fileconfigs":{"config.json":{"default":true,"vim":false,"emacs":false,"fontSize":12},"inlet.js":{"default":true,"vim":false,"emacs":false,"fontSize":12},"style.css":{"default":true,"vim":false,"emacs":false,"fontSize":12},"_.md":{"default":true,"vim":false,"emacs":false,"fontSize":12}},"fullscreen":false,"play":false,"loop":false,"restart":false,"autoinit":true,"pause":true,"loop_type":"period","bv":false,"nclones":15,"clone_opacity":0.4,"duration":3000,"ease":"linear","dt":0.01,"thumbnail":"http://i.imgur.com/Zi8r6bS.png","ajax-caching":true} |
This file contains 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
//trying to recreate the effect from here: | |
//www.themaninblue.com/experiment/Blobular/ | |
var a = { x: tributary.sw/2, y: 303, r: 249 }; | |
var b = { x: tributary.sw - 120, y: 90, r: 43 }; | |
var join = { r: 173 }; | |
var color = "#1fea00" | |
var originDistance = a.r - b.r; | |
function renderBlobs() { | |
var data = [a,b]; | |
var svg = d3.select("svg"); | |
var drag = d3.behavior.drag() | |
.on("drag", function(d) { | |
var evt = d3.event; | |
d.x += evt.dx; | |
d.y += evt.dy; | |
d3.select(this) | |
.attr("cx", function(d) { return d.x }) | |
.attr("cy", function(d) {return d.y }) | |
renderGoo(a, b) | |
}) | |
// Add the original circles | |
var blobs = svg.selectAll("circle.blob") | |
.data(data) | |
.enter() | |
.append("circle") | |
.classed("blob", true) | |
.call(drag) | |
/* | |
.on("mousedown", function(d) { d.drag = true; }) | |
.on("mouseup", function(d) { d.drag = false; }) | |
.on("mousemove", function(d) { | |
if(d.drag) { | |
var m = d3.mouse(this); | |
d.x = m[0]; | |
d.y = m[1]; | |
d3.select(this) | |
.attr("cx", function(d) { return d.x }) | |
.attr("cy", function(d) {return d.y }) | |
renderGoo(a, b) | |
} | |
}); | |
*/ | |
// Update the circles | |
blobs.attr("cx", function(d) { return d.x }) | |
.attr("cy", function(d) {return d.y }) | |
.attr("r", function(d) { return d.r }) | |
.style("fill", function(d,i) { return "red"; }); | |
} | |
function renderGoo(a, b, add) { | |
var svg = d3.select("svg"); | |
//a.area = Math.PI * Math.pow(a.r, 2); | |
//b.area = Math.PI * Math.pow(b.r, 2); | |
//var afterCircleArea = a.area - b.area; | |
var distance = calculateDistance(a,b); | |
var distanceDiff = distance - originDistance; | |
if(distanceDiff < 1) { distanceDiff = 1 } | |
var dontdraw = false; | |
if(distance > 2*join.r + a.r + b.r) { | |
dontdraw = true; | |
} | |
var angle = calculateAngle(a,b); | |
b.h = 0; | |
b.k = 0 - a.r + b.r - distanceDiff; | |
var triangleA = a.r + join.r; // Side a | |
var triangleB = b.r + join.r; // Side b | |
var triangleC = Math.abs(b.k); // Side c | |
var triangleP = (triangleA + triangleB + triangleC) / 2; // Triangle half perimeter | |
var triangleArea = Math.sqrt(triangleP * (triangleP - triangleA) * (triangleP - triangleB) * (triangleP - triangleC)); // Triangle area | |
if (triangleC >= triangleA) | |
{ | |
var triangleH = 2 * triangleArea / triangleC; // Triangle height | |
var triangleD = Math.sqrt(Math.pow(triangleA, 2) - Math.pow(triangleH, 2)); // Big circle bisection of triangleC | |
} | |
else | |
{ | |
var triangleH = 2 * triangleArea / triangleA; // Triangle height | |
var triangleD = Math.sqrt(Math.pow(triangleC, 2) - Math.pow(triangleH, 2)); // Small circle bisection of triangleA | |
} | |
a.tan = triangleH / triangleD; | |
a.angle = Math.atan(a.tan); | |
a.sin = Math.sin(a.angle); | |
a.intersectX = a.sin * a.r; | |
a.cos = Math.cos(a.angle); | |
a.intersectY = a.cos * a.r; | |
join.x = 0 + a.sin * (a.r + join.r); | |
join.y = 0 - a.cos * (a.r + join.r); | |
console.log(a); | |
console.log("Distance: " + distance); | |
console.log("DistanceDiff: " + distanceDiff); | |
console.log("triangleA: " + triangleA); | |
console.log("triangleB: " + triangleB); | |
console.log("triangleC: " + triangleC); | |
console.log("triangleP: " + triangleP); | |
console.log("triangleArea: " + triangleArea); | |
console.log("triangleH: " + triangleH); | |
console.log("triangleD: " + triangleD); | |
var coord1 = { x: -a.intersectX, y: -a.intersectY }; | |
var coord2 = { x: a.intersectX, y: -a.intersectY } | |
b.tan = (b.k - join.y) / (b.h - join.x); | |
b.angle = Math.atan(b.tan); | |
b.intersectX = join.x - Math.cos(b.angle) * (join.r); | |
b.intersectY = join.y - Math.sin(b.angle) * (join.r); | |
var lavaPathD = "M " + coord1.x + " " + coord1.y + " A " + a.r + " " + a.r + " 0 1 0 " + coord2.x + " " + coord2.y; | |
if (join.x - join.r <= 0 && b.k < join.y) | |
{ | |
var crossOverY = circleYFromX(join, 0); | |
lavaPathD += "A " + join.r + " " + join.r + " 0 0 1 0 " + (join.y + crossOverY); | |
lavaPathD += "m 0 -" + (crossOverY * 2); | |
} | |
lavaPathD += "A " + join.r + " " + join.r + " 0 0 1 " + b.intersectX + " " + b.intersectY; | |
var largeArcFlag = 1; | |
if (join.y < b.k) | |
{ | |
largeArcFlag = 0; | |
} | |
lavaPathD += "a " + b.r + " " + b.r + " 0 " + largeArcFlag + " 0 " + (b.intersectX * -2) + " 0"; | |
if (join.x - join.r <= 0 && b.k < join.y) | |
{ | |
lavaPathD += "A " + join.r + " " + join.r + " 0 0 1 0 " + (join.y - crossOverY); | |
lavaPathD += "m 0 " + (crossOverY * 2); | |
} | |
lavaPathD += "A " + join.r + " " + join.r + " 0 0 1 " + coord1.x + " " + coord1.y; | |
lavaPathD += "A " + join.r + " " + join.r + " 0 0 1 " + coord1.x + " " + coord1.y; | |
console.log(lavaPathD); | |
if(!dontdraw) { | |
if(add) { | |
var lavaPath = svg.append("path") | |
.classed("lava", true) | |
.attr("transform", function() { | |
var translate = "translate(" + [a.x, a.y] + ")"; | |
var rotate = "rotate(" + [angle, 0, 0] + ")"; | |
return translate + rotate; | |
}) | |
.style("fill", "none") | |
.style("stroke", color) | |
.style("fill", color) | |
.style("stroke-linecap", "round") | |
.style("stroke-width", 17) | |
lavaPath.attr("d", lavaPathD) | |
} else { | |
svg.selectAll("path.lava") | |
.attr("transform", function() { | |
var translate = "translate(" + [a.x, a.y] + ")"; | |
var rotate = "rotate(" + [angle, 0, 0] + ")"; | |
return translate + rotate; | |
}) | |
.attr("d", lavaPathD); | |
} | |
} | |
} | |
function calculateDistance(origin, point) { | |
var xx = point.x - origin.x; | |
var yy = point.y - origin.y; | |
return Math.sqrt(xx*xx + yy*yy) | |
} | |
function calculateAngle(origin, point) | |
{ | |
var tan = (point.y - origin.y) / (point.x - origin.x); | |
var angle = Math.atan(tan) / Math.PI * 180 + 90; | |
if (point.x < origin.x) | |
{ | |
angle += 180; | |
} | |
return angle; | |
} | |
function circleYFromX (circle, x) | |
{ | |
return Math.sqrt(Math.pow(circle.r, 2) - Math.pow(x - circle.x, 2)); | |
}; | |
renderGoo(a, b, true); | |
renderBlobs(); | |
This file contains 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
#display { | |
background-color: #001b3d; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment