experimenting with circles and pi
Last active
April 16, 2016 20:23
-
-
Save headwinds/8457979 to your computer and use it in GitHub Desktop.
Orbitting Moons
A Pen by brandon flowers on CodePen.
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
<!DOCTYPE html> | |
<meta charset="utf-8"> | |
<style> | |
.experiment { | |
font-family: Arial, sans-serif; | |
font-size: 16px; | |
} | |
div.container { | |
display: block; | |
position: absolute; | |
top: 0px; | |
left:0px; | |
margin: 0px; | |
padding: 0px; | |
width: 100%; | |
height: 100%; | |
} | |
svg { | |
display: block; | |
position: relative; | |
margin: 0px; | |
padding: 0px; | |
width: 100%; | |
height: 100%; | |
} | |
.circleText { | |
fill: #666; | |
font-family: SequentialistBB, Arial, sans-serif; | |
} | |
button { | |
width: 100px; | |
height: 34px; | |
border-radius: 4px; | |
border: none; | |
background-color: #ddd; | |
pointer-events: all; | |
cursor: pointer; | |
} | |
</style> | |
<body> | |
<div class="container"> | |
<svg id="stage"></svg> | |
</div> | |
<script src="//d3js.org/d3.v4.0.0-alpha.28.min.js"></script> | |
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script> | |
<script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script> | |
<script> | |
var svg = d3.select("#stage"); | |
// animation | |
var eases = ["sine", "quad", "cubic", "bounce","back"]; | |
var curEase = eases[3]; | |
var curScale = 1; | |
// dummy data | |
var centerX = $(window).width() / 2; | |
var centerY = $(window).height() / 2; | |
var mainTitle = "ripley".toUpperCase().split(' ') | |
var titleA = "bishop".toUpperCase().split(' '); | |
var titleB = "vasquez".toUpperCase().split(' '); | |
var titleC = "gorman".toUpperCase().split(' '); | |
var titleD = "hicks".toUpperCase().split(' '); | |
var titles = [titleA,titleB,titleC,titleD]; | |
var bubble = {title: "", frequency: 0, trend: 0, x: 0, y: 200, angle: 0}; | |
var mainBubble = _.clone(bubble); | |
mainBubble.title = mainTitle; | |
mainBubble.frequency = 600; | |
mainBubble.trend = 0; | |
mainBubble.x = 100; | |
var bubbleData = [mainBubble]; | |
_.times(4, function(index){ | |
var subBubble = _.clone(bubble); | |
subBubble.title = titles[index]; | |
subBubble.frequency = Math.floor(Math.random() * 500 + 200); | |
subBubble.trend = index + 1; | |
subBubble.x = 300 * (index + 1 ); | |
bubbleData.push(subBubble); | |
}) | |
////////////////////////////// UTILITIES | |
var getRadius = function( d ){ | |
return d.radius = Math.floor( d.frequency / 4.75 ); | |
} | |
var getColor = function( trend ){ | |
var colors = ["lightblue", "yellow", "orange", "lightgrey", "pink"]; | |
return colors[trend]; | |
} | |
var getEase = function(){ | |
var index = Math.floor( Math.random() * eases.length); | |
return eases[index]; | |
} | |
var getTextStyle = function (d, textColor) { | |
var that = this; | |
var magicNum = 1.7; | |
var textColor = (undefined !== textColor && null !== textColor) ? textColor : "#000"; | |
//var bubbleRadius = (null !== selRadius ) ? ( selRadius + 20 ) : d.radius; | |
var longestStrNum = _.max( d.title, function(name){ return name.length; }).length; | |
// if its 5 or less letters... just use 5 so small words like CAT don't look oddly large | |
var longestSizeNum = ( longestStrNum <= 5 ) ? 5 : longestStrNum; | |
var fontSize = Math.round ( d.radius / ( longestSizeNum / magicNum ) ); | |
var styleStr = "font-family: Arial, sans-serif; font-weight:bold; font-size: " + fontSize + "px; fill: " + textColor; | |
return styleStr; | |
}; | |
var getFontSize = function( textArray ) { | |
var textSizeArray = []; | |
for (var i = 0; i < textArray.length; i++) { | |
textSizeArray.push( textArray[i].length ); | |
} | |
return Math.max.apply(Math, textSizeArray); | |
} | |
var getDestinationVector = function( originVector, angle, distance) { | |
var destinationVector = {x: 0, y: 0}; | |
destinationVector.x = Math.round(Math.cos(angle * Math.PI / 180) * distance + originVector.x); | |
destinationVector.y = Math.round(Math.sin(angle * Math.PI / 180) * distance + originVector.y); | |
return destinationVector; | |
} | |
var getDistance = function(d){ | |
var mainBubbleRadius = bubbleData[0].radius; | |
var centerPoint = {x: centerX, y: centerY}; | |
var targetRadius = d.radius; | |
var distance = mainBubbleRadius + targetRadius; | |
return distance; | |
} | |
var getSubBubblePoint = function(d,index){ | |
var angles = [-45, -140, -235, -320]; | |
var centerPoint = {x: centerX, y: centerY}; | |
var distance = getDistance(d); | |
var angle = angles[index-1]; | |
d.angle = angle; | |
var targetPoint = getDestinationVector(centerPoint, angle, distance); | |
return targetPoint; | |
} | |
var getOrbitPoint = function(d, direction){ | |
if (direction === "negative") d.angle++; | |
else d.angle--; | |
if (d.angle > 360 || d.angle < -360) d.angle = 0; | |
var angle = d.angle; | |
var centerPoint = {x: centerX, y: centerY}; | |
var distance = getDistance(d); | |
var targetPoint = getDestinationVector(centerPoint, angle, distance); | |
return targetPoint; | |
} | |
var getTranslation = function(d,index){ | |
// move 0 to the center; | |
var bubbleGroupX; | |
var bubbleGroupY; | |
switch( d.trend) { | |
case 0 : | |
bubbleGroupX = centerX; | |
bubbleGroupY = centerY; | |
break; | |
default : | |
var subBubblePoint = getSubBubblePoint(d, index); | |
bubbleGroupX = subBubblePoint.x; | |
bubbleGroupY = subBubblePoint.y; | |
break; | |
} | |
d.x = bubbleGroupX; | |
d.y = bubbleGroupY; | |
return "translate(" + bubbleGroupX + "," + bubbleGroupY + ") scale(1)"; | |
} | |
var getOrbitTranslation = function(d, index, direction) { | |
var vector = getOrbitPoint(d,direction); | |
return "translate(" + vector.x + "," + vector.y + ") scale(1)"; | |
} | |
////////////////////////////// DRAW | |
var bubbles; | |
var orbitInterval; | |
var draw = function( bubbles ){ | |
var onBubbleClickHandler = function(d,i){ | |
clearInterval(orbitInterval); | |
orbit("positive"); | |
} | |
bubbles = svg.selectAll("g myCircleText") | |
.data(bubbles) | |
.enter() | |
.append("g") | |
.attr("transform", function(d){return "translate("+d.x+","+d.y+")"}); | |
bubbles | |
.each(function (d, i) { | |
if (i === 0 ) { | |
d3.select(this) | |
.on("click", onBubbleClickHandler) | |
.attr("pointer-events", "all") | |
.attr("cursor", "pointer"); | |
} | |
}); | |
bubbles | |
.append("svg:circle") | |
.attr("r", function(d){return getRadius(d)} ) | |
.attr("stroke","black") | |
.attr("stroke-width","0") | |
.attr("fill", function(d){return getColor(d.trend)}); | |
bubbles | |
.each(function (d, i) { | |
var container = d3.select(this); | |
var dy0 = -(d.title.length - 1) / 2; | |
var magicNum = 1.75; | |
for (var i = 0; i < d.title.length; i++) | |
{ | |
container | |
.append('svg:text') | |
.attr('pointer-events', 'none') | |
.attr("text-anchor", "middle") | |
.attr("dy", (dy0 + i) + "em") | |
.attr("class", "circleText") | |
.attr("style", function(d) { return getTextStyle(d, null); }) | |
.text(function(d) { return d.title[i]; }) | |
; | |
} | |
}); | |
bubbles | |
.transition() | |
.duration(2000) | |
.attr("transform", function(d, index){ return getTranslation(d, index)} ); | |
var orbit = function(direction){ | |
bubbles | |
.each(function (d, i) { | |
if (i !== 0 ) { | |
d3.select(this) | |
.attr("transform", function(d, index){ return getOrbitTranslation(d, index, direction)} ); | |
//console.log("after: ", d) | |
} | |
}); | |
} | |
var animateOrbit = function(){ | |
orbitInterval = setInterval( function(){ | |
orbit("negative"); | |
}, 50); | |
} | |
setTimeout( function(){ | |
animateOrbit(); | |
}, 500); | |
} | |
draw(bubbleData); | |
</script> |
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
var svg = d3.select("#stage"); | |
var drawCycle = function(){ | |
var createViz = function() { | |
var dateObj = new Date(); | |
var timeStr = dateObj.toLocaleTimeString(); | |
document.getElementById("drawing").innerHTML = "drawing interval: " + timeStr; | |
svg.selectAll("g").remove(); | |
var ranFreqA = Math.floor((Math.random()*100)+1); | |
var ranFreqB = Math.floor((Math.random()*100)+1); | |
var ranFreqC = Math.floor((Math.random()*100)+1); | |
var titleA = "toronto walking tours".toUpperCase().split(' '); | |
var titleB = "san francisco hyperloop".toUpperCase().split(' '); | |
var titleC = "tokyo and back again".toUpperCase().split(' '); | |
var responseA = {title: titleA, frequency: ranFreqA, x: 75 }; | |
var responseB = {title: titleB, frequency: ranFreqB, x: 175 }; | |
var responseC = {title: titleC, frequency: ranFreqC, x: 300 }; | |
var responseData = [responseA, responseB, responseC]; | |
// font scaling has to be based on the longest string in the series | |
var getFontSize = function( textArray ) { | |
var textSizeArray = []; | |
for (var i = 0; i < textArray.length; i++) { | |
textSizeArray.push( textArray[i].length ); | |
} | |
return Math.max.apply(Math, textSizeArray); | |
} | |
var elem = svg.selectAll("g myCircleText") | |
.data(responseData) | |
var group = elem.enter() | |
.append("g") | |
.attr("transform", function(d){return "translate("+d.x+", 150)"}) | |
var circles = group.append("svg:circle") | |
.attr("r", function(d){return d.frequency } ) | |
.attr("stroke","black") | |
.attr("stroke-width","4") | |
.attr("fill", "white") | |
group | |
.each(function (d, i) { | |
var container = d3.select(this); | |
var dy0 = -(d.title.length - 1) / 3; | |
var magicNum = 1.75; // my math isn't the greatest so I got this by trial and error | |
var longestStrSize = getFontSize(d.title); | |
for (var i = 0; i < d.title.length; i++) | |
{ | |
container | |
.append('svg:text') | |
.attr('pointer-events', 'none') | |
.attr("text-anchor", "middle") | |
.attr("dy", (dy0 + i) + "em") | |
.attr("class", "circleText") | |
.style("fill", "black") | |
.style("font-size", function(d) { return ( d.frequency / ( longestStrSize / magicNum ) ) + "px" }) | |
.text(function(d) { return d.title[i]; }) | |
; | |
} | |
}); | |
}; | |
var cycleInterval = setInterval( function(){ createViz(); }, 500 ); | |
//createViz(); | |
} | |
drawCycle(); |
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
.experiment { | |
font-family: Helvetica, Arial, sans-serif; | |
font-size: 16px; | |
} | |
.circleText { | |
color: #D7BF00; | |
font-family: Georgia, serif; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment