Last active
October 25, 2017 20:21
-
-
Save lsei/76611af6773491d4facf554b703264ff to your computer and use it in GitHub Desktop.
Network of nodes in two groups
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
height: 1000 | |
license: none |
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> | |
<html> | |
<head> | |
<title>The Doors Network</title> | |
<script src="https://unpkg.com/[email protected]/babel.min.js" charset="utf-8"></script> | |
<script src="https://unpkg.com/[email protected]/dist/browser-scss.min.js" charset="utf-8"></script> | |
<script src="https://d3js.org/d3.v4.min.js"></script> | |
<style> | |
body { | |
opacity: 0; | |
} | |
</style> | |
<style type="text/scss"> | |
body, html { | |
opacity: 1; | |
font-family: sans-serif; | |
width: 100%; | |
height: 100%; | |
padding: 0; | |
margin: 0; | |
} | |
svg { | |
position: absolute; | |
top: 50%; | |
left: 50%; | |
transform: translate(-50%, -50%); | |
} | |
.inner { | |
.node { | |
opacity: 0; | |
animation: fadeIn .5s linear forwards; | |
} | |
} | |
.outer { | |
.node { | |
opacity: 0; | |
animation: fadeIn .5s linear forwards; | |
} | |
} | |
.link { | |
opacity: .25; | |
stroke-dasharray: 2000; | |
stroke-dashoffset: 2000; | |
animation: dash 5s linear forwards; | |
} | |
@keyframes fadeIn { | |
to { | |
opacity: 1; | |
} | |
} | |
@keyframes dash { | |
to { | |
stroke-dashoffset: 0; | |
} | |
} | |
@for $i from 1 through 200 { | |
.link:nth-child(#{$i}) { | |
animation-delay: (.025s * $i) + 3s; | |
} | |
} | |
@for $i from 1 through 200 { | |
.inner .node:nth-child(#{$i}) { | |
animation-delay: .05s * $i; | |
} | |
} | |
@for $i from 1 through 200 { | |
.outer .node:nth-child(#{$i}) { | |
animation-delay: (.025s * $i) + .5s; | |
} | |
} | |
</style> | |
</head> | |
<body> | |
<script type="text/babel" src="script.js"></script> | |
</body> | |
</html> |
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
const width = window.innerWidth; | |
const height = window.innerHeight; | |
const innerRadius = 200; | |
const outerRadius = 400; | |
const laneRadii = [ | |
220, | |
230, | |
250, | |
270, | |
280 | |
] | |
var svg = d3.select('body').append('svg') | |
.attr('width', width) | |
.attr('height', height); | |
const data = { | |
inner: ["Ray Manzarek","Bruce Botnick","Robby Krieger","Paul A. Rothchild","Jim Morrison","John Densmore","William S. Harvey","Joel Brodsky","Jac Holzman","Doug Lubahn","Robert L. Heimall","Jerry Scheff","Guy Webster","Paul Ferrara (2)","Carl Cossick","Henry Diltz","Frank Lisciandro","Marc Benno","Wendell Hamick","Curtis Amy","Harvey Brooks","Reinol Andino","Ray Neopolitan","John Haeny","George Bohanon","Champ Webb","Gary Burden","Paul Harris (2)","Jesse McReynolds","Jimmy Buchanan"], | |
outer: ["Van Morrison","The Rolling Stones","Pink Floyd","Frank Zappa","John Lee Hooker","Pearl Jam","U2","Blondie","Joni Mitchell","Bob Dylan","The Who","Rush","Billy Idol","David Bowie","Bruce Springsteen","Neil Young","Michael Jackson","Elton John","Herbie Hancock","ZZ Top","AC\/DC","Jefferson Airplane","Muddy Waters","Miles Davis","Santana","Dire Straits","Jimi Hendrix","Steely Dan","Foo Fighters","The Crusaders","The Beatles","Neil Diamond","Eagles","Carpenters","Jackson Browne","Tom Waits","Janis Joplin","Bryan Adams","Linda Ronstadt","Madonna","Bee Gees","Metallica","Nirvana","Rod Stewart","Black Sabbath","James Taylor (2)","Fleetwood Mac","Carole King","Joe Cocker","Mariah Carey","Prince","Eric Clapton","Tomaso Albinoni","Led Zeppelin","Sting","Def Leppard","Crosby, Stills, Nash & Young","Earth, Wind & Fire","Queen"], | |
links: [ | |
{inner: 3, outer: 30}, | |
// {inner: 3, outer: 0}, | |
// {inner: 3, outer: 20}, | |
] | |
} | |
for (var i = 0; i < 100; i++) { | |
data.links.push({ | |
inner: Math.round(Math.random() * data.inner.length), | |
outer: Math.round(Math.random() * data.outer.length) | |
}) | |
} | |
var inner = svg.append('g') | |
.attr('class', 'inner') | |
.attr('transform', 'translate(' + width/2 + ', ' + height/2 + ')'); | |
var innerNode = inner.selectAll('.node') | |
.data(data.inner) | |
.enter() | |
.append('g') | |
.attr('class','node') | |
.attr('transform', (d, i) => { | |
return 'rotate(' + (360 / data.inner.length * i) +')'; | |
}); | |
innerNode.append('circle') | |
.attr('r', innerRadius) | |
.attr('fill', 'transparent') | |
.attr('cx', 0) | |
.attr('cy', 0); | |
innerNode.append('circle') | |
.attr('r', 5) | |
.attr('fill', 'black') | |
.attr('cx', 0) | |
.attr('cy', -(innerRadius - 5)); | |
innerNode.append('text') | |
.attr('x', (d, i) => ((i < data.inner.length/2) ? -5 : 5)) | |
.attr('y', -(innerRadius - 10)) | |
.attr('transform', (d, i) => { | |
if(i < data.inner.length/2) { | |
return 'rotate(-90, 5, ' + (-(innerRadius - 10)) +')' | |
} | |
return 'rotate(90, -5, ' + (-(innerRadius - 10)) +')' | |
}) | |
.text(d => d) | |
.attr('text-anchor', (d, i) => { | |
return (i < data.inner.length/2) ? 'end' : 'start'; | |
}); | |
var outer = svg.append('g') | |
.attr('class', 'outer') | |
.attr('transform', 'translate(' + width/2 + ', ' + height/2 + ')'); | |
var outerNode = outer.selectAll('.node') | |
.data(data.outer) | |
.enter() | |
.append('g') | |
.attr('class','node') | |
.attr('transform', (d, i) => { | |
return 'rotate(' + (360 / data.outer.length * i) +')'; | |
}); | |
outerNode.append('circle') | |
.attr('r', outerRadius) | |
.attr('fill', 'transparent') | |
.attr('cx', 0) | |
.attr('cy', 0); | |
outerNode.append('circle') | |
.attr('r', 5) | |
.attr('fill', 'black') | |
.attr('cx', 0) | |
.attr('cy', -(outerRadius - 5)); | |
outerNode.append('text') | |
.attr('x', (d, i) => ((i < data.outer.length/2) ? -5 : 5)) | |
.attr('y', -(outerRadius + 20)) | |
.attr('transform', (d, i) => { | |
if(i < data.outer.length/2) { | |
return 'rotate(-90, 5, ' + (-(outerRadius + 20)) +')' | |
} | |
return 'rotate(90, -5, ' + (-(outerRadius + 20)) +')' | |
}) | |
.text(d => d) | |
.attr('text-anchor', (d, i) => { | |
return (i > data.outer.length/2) ? 'end' : 'start'; | |
}); | |
var links = svg.append('g') | |
.attr('class', 'links') | |
.attr('transform', 'translate(' + width/2 + ', ' + height/2 + ')'); | |
var link = links.selectAll('.link') | |
.data(data.links) | |
.enter() | |
.append('g') | |
.attr('class', 'link'); | |
function getPos(y, rotateRad){ | |
const x = 0; | |
const newY = y * Math.cos(rotateRad) - x * Math.sin(rotateRad); | |
const newX = y * Math.sin(rotateRad) + x * Math.cos(rotateRad); | |
return {x: -newX, y: newY} | |
} | |
// link.append('circle') | |
// .attr('r', 5) | |
// .attr('fill', 'blue') | |
// .attr('cx', d => { | |
// const initialY = -((outerRadius - innerRadius)/2 + innerRadius); | |
// const rotateRad = (2*Math.PI) / data.inner.length * d.inner; | |
// return getPos(initialY,rotateRad).x; | |
// }) | |
// .attr('cy', d => { | |
// const initialY = -((outerRadius - innerRadius)/2 + innerRadius); | |
// const rotateRad = (2*Math.PI) / data.inner.length * d.inner; | |
// return getPos(initialY,rotateRad).y; | |
// }) | |
// link.append('circle') | |
// .attr('r', 5) | |
// .attr('fill', 'red') | |
// .attr('cx', d => { | |
// const initialY = -((outerRadius - innerRadius)/2 + innerRadius); | |
// const rotateRad = (2*Math.PI) / data.outer.length * d.outer; | |
// return getPos(initialY,rotateRad).x; | |
// }) | |
// .attr('cy', d => { | |
// const initialY = -((outerRadius - innerRadius)/2 + innerRadius); | |
// const rotateRad = (2*Math.PI) / data.outer.length * d.outer; | |
// return getPos(initialY,rotateRad).y; | |
// }) | |
link.append('path') | |
.attr('fill', 'transparent') | |
.attr('stroke', 'black') | |
.attr('stroke-width', 2) | |
.attr('d', d => { | |
return linkPath(d); | |
}) | |
function linkPath(d) { | |
var middleRadius = -((outerRadius - innerRadius)/2 + innerRadius) | |
var innerRadian = (2*Math.PI) / data.inner.length * d.inner; | |
var outerRadian = (2*Math.PI) / data.outer.length * d.outer; | |
if(Math.abs(innerRadian - outerRadian) > Math.PI) { | |
if(innerRadian > outerRadian) { | |
innerRadian -= 2*Math.PI | |
} else { | |
outerRadian -= 2*Math.PI | |
} | |
} | |
var startPoint = getPos(-innerRadius, innerRadian); | |
var d = M(startPoint); | |
if(Math.abs(Math.abs(innerRadian) - Math.abs(outerRadian)) < Math.PI/1.9) { | |
// smaller than 90deg apart | |
var middleRadian = (outerRadian - innerRadian)/2 + innerRadian; | |
var middleInnerRadian = (outerRadian - innerRadian)/4 + innerRadian; | |
var middleOuterRadian = outerRadian - (outerRadian - innerRadian)/4; | |
// firstCurve | |
var p1 = getPos(middleRadius, innerRadian); | |
var p2 = getPos(middleRadius, middleInnerRadian); | |
d += Q(p1, p2) | |
// secondCurve | |
var p4 = getPos(middleRadius, middleOuterRadian); | |
var p5 = getPos(-outerRadius, outerRadian); | |
d += T(p4, p5); | |
return d; | |
} else { | |
var middleRadian = (outerRadian - innerRadian)/2 + innerRadian; | |
var middleInnerRadian = (outerRadian - innerRadian)/4 + innerRadian; | |
var middleInnerMiddleRadian = (outerRadian - innerRadian)/8 + innerRadian; | |
var middleOuterRadian = outerRadian - (outerRadian - innerRadian)/4; | |
var middleOuterMiddleRadian = outerRadian - (outerRadian - innerRadian)/8; | |
var p1 = getPos(middleRadius, innerRadian); | |
var p2 = getPos(middleRadius, middleInnerMiddleRadian); | |
d += Q(p1, p2); | |
var p = getPos(middleRadius, middleRadian); | |
d += ['T', p.x, p.y, ''].join(' '); | |
var p = getPos(middleRadius, middleOuterMiddleRadian); | |
d += ['T', p.x, p.y, ''].join(' '); | |
var p = getPos(-outerRadius, outerRadian); | |
d += ['T', p.x, p.y, ''].join(' '); | |
return d; | |
} | |
} | |
function M(coords) { | |
return 'M' + coords.x + ' ' + coords.y + ' '; | |
} | |
function C(p1, p2, p3) { | |
return 'C' + p1.x + ' ' + p1.y + ', ' + p2.x + ' ' + p2.y + ', ' + p3.x + ' ' + p3.y + ' '; | |
} | |
function S(p1, p2) { | |
return ['S', p1.x, p1.y, ',', p2.x, p2.y, ''].join(' '); | |
} | |
function Q(p1, p2) { | |
return ['Q', p1.x, p1.y, ',', p2.x, p2.y, ''].join(' '); | |
} | |
function T(p1, p2) { | |
// this should only need one paramater but changing it seems to break stuff | |
return ['T', p1.x, p1.y, ',', p2.x, p2.y, ''].join(' '); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment