IEX API
Last active
April 3, 2017 02:04
-
-
Save iexviz/dd7f2afab6b9dea7fd8b1d70c2489b3b to your computer and use it in GitHub Desktop.
IEX Market - Orbitting Moons
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
license: mit |
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: 10px; | |
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; | |
} | |
.centerText { | |
fill: #666; | |
font-family: SequentialistBB, Arial, sans-serif; | |
font-family: Arial, sans-serif; | |
font-size: 26px; | |
} | |
button { | |
width: 100px; | |
height: 34px; | |
border-radius: 4px; | |
border: none; | |
background-color: #ddd; | |
pointer-events: all; | |
cursor: pointer; | |
} | |
.d3-tip { | |
font-family: 'Raleway', sans-serif; | |
font-size: .8em; | |
line-height: 1; | |
padding: 7px; | |
background: black; | |
color: lightgray; | |
border-radius: 20px; | |
} | |
</style> | |
<body align=center bgcolor=black> | |
<div class=dropdown></div> | |
<script src="http://d3js.org/d3.v3.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 src="http://cdnjs.cloudflare.com/ajax/libs/d3-tip/0.6.3/d3-tip.min.js"> </script> | |
<script src="karthiviz.js"></script> | |
<script> | |
function updateviz(key){ | |
var svg = d3.select("body").append('svg') | |
.attr('width', 960) | |
.attr('height', 960); | |
// animation | |
var eases = ["sine", "quad", "cubic", "bounce","back"]; | |
var curEase = eases[2]; | |
var curScale = 1; | |
// dummy data | |
var centerX = $(window).width() / 2; | |
var centerY = $(window).height() / 2.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: 100, angle: 0}; | |
var mainBubble = _.clone(bubble); | |
mainBubble.title = ""; | |
mainBubble.frequency = 1200; | |
mainBubble.trend = 0; | |
mainBubble.x = 100; | |
var bubbleData = [mainBubble]; | |
data.forEach(function(d,index){ | |
var subBubble = _.clone(bubble); | |
subBubble.title = d.name; | |
subBubble.value2 = d.value2; | |
subBubble.frequency = d.value*5; | |
subBubble.trend = index + 1; | |
subBubble.x = 300 * (index + 1 ); | |
bubbleData.push(subBubble); | |
}) | |
////////////////////////////// UTILITIES | |
var getRadius = function( d,i ){ | |
if(i ==0){ | |
return d.radius = 120 | |
} | |
return d.radius = 30; | |
return d.radius = Math.floor( d.frequency / 4.75 ); | |
} | |
var getColor = function( i ){ | |
if(i ==0){ | |
return "orange" | |
} | |
return color(i) | |
} | |
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+20; | |
return distance; | |
} | |
var getSubBubblePoint = function(d,index){ | |
var angles = [-45, -140, -235, -320, -330]; | |
var centerPoint = {x: centerX, y: centerY}; | |
var distance = getDistance(d); | |
var angle = index*-28+100 | |
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"); | |
} | |
var gradientRadial = svg.append("defs").selectAll("radialGradient") | |
.data(bubbles) | |
.enter().append("radialGradient") | |
.attr("id", function(d,i){ return "gradient-" + i; }) | |
.attr("cx", "30%") | |
.attr("cy", "30%") | |
.attr("r", "65%"); | |
//Append the color stops | |
gradientRadial.append("stop") | |
.attr("offset", "0%") | |
.attr("stop-color", function(d,i) { return d3.rgb(getColor(i)).brighter(1); }); | |
gradientRadial.append("stop") | |
.attr("offset", "50%") | |
.attr("stop-color", function(d,i) { return getColor(i); }); | |
gradientRadial.append("stop") | |
.attr("offset", "100%") | |
.attr("stop-color", function(d,i) { return d3.rgb(getColor(i)).darker(1.5); }); | |
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("class", function(d,i){ | |
if(i==0){return ""} | |
return "circle"} ) | |
.attr("r", function(d,i){return getRadius(d,i)} ) | |
//.attr("stroke","black") | |
//.attr("stroke-width","0") | |
.style("fill", function(d,i) { return "url(#gradient-" + i + ")"; }); | |
bubbles | |
.each(function (d, i) { | |
var container = d3.select(this); | |
var dy0 = -(d.title.length - 1) / 2; | |
var magicNum = 1.75; | |
container | |
.append('svg:text') | |
.attr('pointer-events', 'none') | |
.attr("text-anchor", "middle") | |
.attr("dy", "0em") | |
.attr("class", function(d,i){ | |
if(i==0){return "centerText"} | |
return"circleText" | |
}) .attr("style", function(d) { return getTextStyle(d, null); }) | |
.text(function(d) { | |
if(i ==0){ | |
return key | |
} | |
return d.title; }) | |
container | |
.append('svg:text') | |
.attr('pointer-events', 'none') | |
.attr("text-anchor", "middle") | |
.attr("dy", "1em") | |
.attr("class", function(d,i){ | |
if(i==0){return "centerText"} | |
return"circleText" | |
}) | |
.attr("style", function(d) { return getTextStyle(d, null); }) | |
.text(function(d) { | |
if(i ==0){ | |
return total | |
} | |
return formatAbbreviation(d.value2); }) | |
; | |
}); | |
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
d3.jsonp = function (url, callback) { | |
function rand() { | |
var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', | |
c = '', i = -1; | |
while (++i < 15) c += chars.charAt(Math.floor(Math.random() * 52)); | |
return c; | |
} | |
function create(url) { | |
var e = url.match(/callback=d3.jsonp.(\w+)/), | |
c = e ? e[1] : rand(); | |
d3.jsonp[c] = function(data) { | |
callback(data); | |
delete d3.jsonp[c]; | |
script.remove(); | |
}; | |
return 'd3.jsonp.' + c; | |
} | |
var cb = create(url), | |
script = d3.select('head') | |
.append('script') | |
.attr('type', 'text/javascript') | |
.attr('src', url.replace(/(\{|%7B)callback(\{|%7D)/, cb)); | |
}; | |
d3.jsonp("https://api.iextrading.com/1.0/market?callback=visualise"); | |
function visualise(data){ | |
window.data = data; | |
var option = [ "marketPercent", "volume", "tapeA", "tapeB", "tapeC"] | |
var key = option[0] | |
var select = d3.select('.dropdown') | |
.append('select') | |
.style('font-size', '20px') | |
.attr('class','select') | |
.on('change',onchange); | |
var options = select | |
.selectAll('option') | |
.data(option).enter() | |
.append('option') | |
.text(function (d) { return d; }); | |
function onchange() { | |
renderviz(d3.select('select').property('value')) | |
} | |
data.forEach(function(d,i) { | |
d.marketPercent = (d.marketPercent*100).toFixed(2); | |
}); | |
renderviz(key) | |
}; | |
function renderviz(key) { | |
var circs = [] | |
data.forEach(function(d){ circs.push(d[key])}) | |
//console.log(d3.sum(circs).toFixed(0)) | |
var total = formatAbbreviation(d3.sum(circs).toFixed(0)) | |
window.total = total | |
var rscale = d3.scale.sqrt() | |
.domain([0,(d3.sum(circs)).toFixed(0)]) | |
.range([0,200]) | |
data.forEach(function(d,i) { | |
d.name = d.venueName; | |
d.value2 = d[key]; | |
console.log(formatAbbreviation(d.value2)) | |
d.value = rscale(d[key]).toFixed(2); | |
}); | |
color = d3.scale.category20c(); | |
window.color = color; | |
d3.select("body").selectAll("svg").remove(); | |
updateviz(key); | |
setuptip(key); | |
} | |
function setuptip(key) { | |
var format = d3.format(",") | |
tip = d3.tip() | |
.attr('class', 'd3-tip') | |
.html(function(d,i) { | |
return d.name + ": " + format(d[key]) }); | |
d3.selectAll(".circle").call(tip) | |
d3.selectAll('.circle') | |
.data(data) | |
.on('mouseover', tip.show) | |
.on('mouseout', tip.hide); | |
} | |
formatAbbreviation = function(x) { | |
var formatNumber = d3.format(".0f"), | |
formatPercent = d3.format(".2f"), | |
formatBillion = function(x) { return "" + formatNumber(x / 1e9) + "B"; }, | |
formatMillion = function(x) { return "" + formatNumber(x / 1e6) + "M"; }, | |
formatThousand = function(x) { return "" + formatNumber(x / 1e3) + "k"; }; | |
var v = Math.abs(x); | |
return (v >= .9995e9 ? formatBillion | |
: v >= .9995e6 ? formatMillion | |
: v >= .9995e3 ? formatThousand | |
: formatPercent)(x); | |
} | |
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