Built with blockbuilder.org
Created
May 3, 2018 08:13
-
-
Save nacmacfeegle/aedf839dd5cfd42c37f42e29fb101cd9 to your computer and use it in GitHub Desktop.
d3.v4 collapsible force zoomable draggable radial tree using svg
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
{ | |
"name": "name0", | |
"children": [ | |
{ | |
"name": "name1", | |
"children": [ | |
{ | |
"name": "name2", | |
"children": [ | |
{ | |
"children": [ | |
{ | |
"name": "name4" | |
}, | |
{ | |
"name": "name5" | |
}, | |
{ | |
"name": "name6" | |
}, | |
{ | |
"name": "name7" | |
}, | |
{ | |
"name": "name8" | |
}, | |
{ | |
"name": "name9" | |
}, | |
{ | |
"name": "name10" | |
}, | |
{ | |
"name": "name11" | |
}, | |
{ | |
"name": "name12" | |
}, | |
{ | |
"name": "name13" | |
}, | |
{ | |
"name": "name14" | |
}, | |
{ | |
"name": "name15" | |
}, | |
{ | |
"name": "name16" | |
}, | |
{ | |
"name": "name17" | |
}, | |
{ | |
"name": "name18" | |
}, | |
{ | |
"name": "name19" | |
}, | |
{ | |
"name": "name20" | |
}, | |
{ | |
"name": "name21" | |
}, | |
{ | |
"name": "name22" | |
}, | |
{ | |
"name": "name23" | |
}, | |
{ | |
"name": "name24" | |
}, | |
{ | |
"name": "name25" | |
}, | |
{ | |
"name": "name26" | |
}, | |
{ | |
"name": "name27" | |
}, | |
{ | |
"name": "name28" | |
}, | |
{ | |
"name": "name29" | |
}, | |
{ | |
"name": "name30" | |
}, | |
{ | |
"name": "name31" | |
}, | |
{ | |
"name": "name32" | |
}, | |
{ | |
"name": "name33" | |
}, | |
{ | |
"name": "name34" | |
}, | |
{ | |
"name": "name35" | |
}, | |
{ | |
"name": "name36" | |
}, | |
{ | |
"name": "name37" | |
}, | |
{ | |
"name": "name38" | |
}, | |
{ | |
"name": "name39" | |
}, | |
{ | |
"name": "name40" | |
}, | |
{ | |
"name": "name41" | |
}, | |
{ | |
"name": "name42" | |
}, | |
{ | |
"name": "name43" | |
}, | |
{ | |
"name": "name44" | |
}, | |
{ | |
"name": "name45" | |
}, | |
{ | |
"name": "name46" | |
}, | |
{ | |
"name": "name47" | |
}, | |
{ | |
"name": "name48" | |
}, | |
{ | |
"name": "name49" | |
}, | |
{ | |
"name": "name50" | |
}, | |
{ | |
"name": "name51" | |
}, | |
{ | |
"name": "name52" | |
}, | |
{ | |
"name": "name53" | |
}, | |
{ | |
"name": "name54" | |
}, | |
{ | |
"name": "name55" | |
}, | |
{ | |
"name": "name56" | |
}, | |
{ | |
"name": "name57" | |
}, | |
{ | |
"name": "name58" | |
}, | |
{ | |
"name": "name59" | |
}, | |
{ | |
"name": "name60" | |
}, | |
{ | |
"name": "name61" | |
}, | |
{ | |
"name": "name62" | |
}, | |
{ | |
"name": "name63" | |
}, | |
{ | |
"name": "name64" | |
}, | |
{ | |
"name": "name65" | |
}, | |
{ | |
"name": "name66" | |
}, | |
{ | |
"name": "name67" | |
}, | |
{ | |
"name": "name68" | |
}, | |
{ | |
"name": "name69" | |
}, | |
{ | |
"name": "name70" | |
}, | |
{ | |
"name": "name71" | |
}, | |
{ | |
"name": "name72" | |
}, | |
{ | |
"name": "name73" | |
}, | |
{ | |
"name": "name74" | |
}, | |
{ | |
"name": "name75" | |
}, | |
{ | |
"name": "name76" | |
}, | |
{ | |
"name": "name77" | |
}, | |
{ | |
"name": "name78" | |
}, | |
{ | |
"name": "name79" | |
}, | |
{ | |
"name": "name80" | |
}, | |
{ | |
"name": "name81" | |
}, | |
{ | |
"name": "name82" | |
}, | |
{ | |
"name": "name83" | |
}, | |
{ | |
"name": "name84" | |
}, | |
{ | |
"name": "name85" | |
}, | |
{ | |
"name": "name86" | |
}, | |
{ | |
"name": "name87" | |
}, | |
{ | |
"name": "name88" | |
}, | |
{ | |
"name": "name89" | |
}, | |
{ | |
"name": "name90" | |
}, | |
{ | |
"name": "name91" | |
}, | |
{ | |
"name": "name92" | |
}, | |
{ | |
"name": "name93" | |
}, | |
{ | |
"name": "name94" | |
}, | |
{ | |
"name": "name95" | |
}, | |
{ | |
"name": "name96" | |
}, | |
{ | |
"name": "name97" | |
}, | |
{ | |
"name": "name98" | |
}, | |
{ | |
"name": "name99" | |
}, | |
{ | |
"name": "name100" | |
}, | |
{ | |
"name": "name101" | |
}, | |
{ | |
"name": "name102" | |
} | |
], | |
"name": "name3" | |
}, | |
{ | |
"children": [ | |
{ | |
"name": "name104" | |
}, | |
{ | |
"name": "name105" | |
}, | |
{ | |
"name": "name106" | |
}, | |
{ | |
"name": "name107" | |
}, | |
{ | |
"name": "name108" | |
}, | |
{ | |
"name": "name109" | |
}, | |
{ | |
"name": "name110" | |
}, | |
{ | |
"name": "name111" | |
}, | |
{ | |
"name": "name112" | |
}, | |
{ | |
"name": "name113" | |
}, | |
{ | |
"name": "name114" | |
}, | |
{ | |
"name": "name115" | |
}, | |
{ | |
"name": "name116" | |
}, | |
{ | |
"name": "name117" | |
}, | |
{ | |
"name": "name118" | |
}, | |
{ | |
"name": "name119" | |
}, | |
{ | |
"name": "name120" | |
}, | |
{ | |
"name": "name121" | |
}, | |
{ | |
"name": "name122" | |
}, | |
{ | |
"name": "name123" | |
}, | |
{ | |
"name": "name124" | |
}, | |
{ | |
"name": "name125" | |
}, | |
{ | |
"name": "name126" | |
}, | |
{ | |
"name": "name127" | |
}, | |
{ | |
"name": "name128" | |
}, | |
{ | |
"name": "name129" | |
}, | |
{ | |
"name": "name130" | |
}, | |
{ | |
"name": "name131" | |
}, | |
{ | |
"name": "name132" | |
}, | |
{ | |
"name": "name133" | |
}, | |
{ | |
"name": "name134" | |
}, | |
{ | |
"name": "name135" | |
}, | |
{ | |
"name": "name136" | |
}, | |
{ | |
"name": "name137" | |
}, | |
{ | |
"name": "name138" | |
}, | |
{ | |
"name": "name139" | |
}, | |
{ | |
"name": "name140" | |
}, | |
{ | |
"name": "name141" | |
}, | |
{ | |
"name": "name142" | |
}, | |
{ | |
"name": "name143" | |
}, | |
{ | |
"name": "name144" | |
}, | |
{ | |
"name": "name145" | |
}, | |
{ | |
"name": "name146" | |
}, | |
{ | |
"name": "name147" | |
}, | |
{ | |
"name": "name148" | |
}, | |
{ | |
"name": "name149" | |
}, | |
{ | |
"name": "name150" | |
}, | |
{ | |
"name": "name151" | |
}, | |
{ | |
"name": "name152" | |
}, | |
{ | |
"name": "name153" | |
}, | |
{ | |
"name": "name154" | |
}, | |
{ | |
"name": "name155" | |
}, | |
{ | |
"name": "name156" | |
}, | |
{ | |
"name": "name157" | |
}, | |
{ | |
"name": "name158" | |
}, | |
{ | |
"name": "name159" | |
}, | |
{ | |
"name": "name160" | |
}, | |
{ | |
"name": "name161" | |
}, | |
{ | |
"name": "name162" | |
}, | |
{ | |
"name": "name163" | |
}, | |
{ | |
"name": "name164" | |
}, | |
{ | |
"name": "name165" | |
}, | |
{ | |
"name": "name166" | |
}, | |
{ | |
"name": "name167" | |
}, | |
{ | |
"name": "name168" | |
}, | |
{ | |
"name": "name169" | |
}, | |
{ | |
"name": "name170" | |
}, | |
{ | |
"name": "name171" | |
}, | |
{ | |
"name": "name172" | |
}, | |
{ | |
"name": "name173" | |
}, | |
{ | |
"name": "name174" | |
}, | |
{ | |
"name": "name175" | |
}, | |
{ | |
"name": "name176" | |
}, | |
{ | |
"name": "name177" | |
}, | |
{ | |
"name": "name178" | |
}, | |
{ | |
"name": "name179" | |
}, | |
{ | |
"name": "name180" | |
}, | |
{ | |
"name": "name181" | |
}, | |
{ | |
"name": "name182" | |
}, | |
{ | |
"name": "name183" | |
}, | |
{ | |
"name": "name184" | |
}, | |
{ | |
"name": "name185" | |
}, | |
{ | |
"name": "name186" | |
}, | |
{ | |
"name": "name187" | |
}, | |
{ | |
"name": "name188" | |
}, | |
{ | |
"name": "name189" | |
}, | |
{ | |
"name": "name190" | |
}, | |
{ | |
"name": "name191" | |
}, | |
{ | |
"name": "name192" | |
}, | |
{ | |
"name": "name193" | |
}, | |
{ | |
"name": "name194" | |
}, | |
{ | |
"name": "name195" | |
}, | |
{ | |
"name": "name196" | |
}, | |
{ | |
"name": "name197" | |
}, | |
{ | |
"name": "name198" | |
}, | |
{ | |
"name": "name199" | |
}, | |
{ | |
"name": "name200" | |
}, | |
{ | |
"name": "name201" | |
}, | |
{ | |
"name": "name202" | |
} | |
], | |
"name": "name103" | |
} | |
] | |
}, | |
{ | |
"name": "name203", | |
"children": [ | |
{ | |
"children": [ | |
{ | |
"name": "name205" | |
}, | |
{ | |
"name": "name206" | |
}, | |
{ | |
"name": "name207" | |
}, | |
{ | |
"name": "name208" | |
}, | |
{ | |
"name": "name209" | |
}, | |
{ | |
"name": "name210" | |
}, | |
{ | |
"name": "name211" | |
}, | |
{ | |
"name": "name212" | |
}, | |
{ | |
"name": "name213" | |
}, | |
{ | |
"name": "name214" | |
}, | |
{ | |
"name": "name215" | |
}, | |
{ | |
"name": "name216" | |
}, | |
{ | |
"name": "name217" | |
}, | |
{ | |
"name": "name218" | |
}, | |
{ | |
"name": "name219" | |
}, | |
{ | |
"name": "name220" | |
}, | |
{ | |
"name": "name221" | |
}, | |
{ | |
"name": "name222" | |
}, | |
{ | |
"name": "name223" | |
}, | |
{ | |
"name": "name224" | |
}, | |
{ | |
"name": "name225" | |
}, | |
{ | |
"name": "name226" | |
}, | |
{ | |
"name": "name227" | |
}, | |
{ | |
"name": "name228" | |
}, | |
{ | |
"name": "name229" | |
}, | |
{ | |
"name": "name230" | |
}, | |
{ | |
"name": "name231" | |
}, | |
{ | |
"name": "name232" | |
}, | |
{ | |
"name": "name233" | |
}, | |
{ | |
"name": "name234" | |
}, | |
{ | |
"name": "name235" | |
}, | |
{ | |
"name": "name236" | |
}, | |
{ | |
"name": "name237" | |
}, | |
{ | |
"name": "name238" | |
}, | |
{ | |
"name": "name239" | |
}, | |
{ | |
"name": "name240" | |
}, | |
{ | |
"name": "name241" | |
}, | |
{ | |
"name": "name242" | |
}, | |
{ | |
"name": "name243" | |
}, | |
{ | |
"name": "name244" | |
}, | |
{ | |
"name": "name245" | |
}, | |
{ | |
"name": "name246" | |
}, | |
{ | |
"name": "name247" | |
}, | |
{ | |
"name": "name248" | |
}, | |
{ | |
"name": "name249" | |
}, | |
{ | |
"name": "name250" | |
}, | |
{ | |
"name": "name251" | |
}, | |
{ | |
"name": "name252" | |
}, | |
{ | |
"name": "name253" | |
}, | |
{ | |
"name": "name254" | |
}, | |
{ | |
"name": "name255" | |
}, | |
{ | |
"name": "name256" | |
}, | |
{ | |
"name": "name257" | |
}, | |
{ | |
"name": "name258" | |
}, | |
{ | |
"name": "name259" | |
}, | |
{ | |
"name": "name260" | |
}, | |
{ | |
"name": "name261" | |
}, | |
{ | |
"name": "name262" | |
}, | |
{ | |
"name": "name263" | |
}, | |
{ | |
"name": "name264" | |
}, | |
{ | |
"name": "name265" | |
}, | |
{ | |
"name": "name266" | |
}, | |
{ | |
"name": "name267" | |
}, | |
{ | |
"name": "name268" | |
}, | |
{ | |
"name": "name269" | |
}, | |
{ | |
"name": "name270" | |
}, | |
{ | |
"name": "name271" | |
}, | |
{ | |
"name": "name272" | |
}, | |
{ | |
"name": "name273" | |
}, | |
{ | |
"name": "name274" | |
}, | |
{ | |
"name": "name275" | |
}, | |
{ | |
"name": "name276" | |
}, | |
{ | |
"name": "name277" | |
}, | |
{ | |
"name": "name278" | |
}, | |
{ | |
"name": "name279" | |
}, | |
{ | |
"name": "name280" | |
}, | |
{ | |
"name": "name281" | |
}, | |
{ | |
"name": "name282" | |
}, | |
{ | |
"name": "name283" | |
}, | |
{ | |
"name": "name284" | |
}, | |
{ | |
"name": "name285" | |
}, | |
{ | |
"name": "name286" | |
}, | |
{ | |
"name": "name287" | |
}, | |
{ | |
"name": "name288" | |
}, | |
{ | |
"name": "name289" | |
}, | |
{ | |
"name": "name290" | |
}, | |
{ | |
"name": "name291" | |
}, | |
{ | |
"name": "name292" | |
}, | |
{ | |
"name": "name293" | |
}, | |
{ | |
"name": "name294" | |
}, | |
{ | |
"name": "name295" | |
}, | |
{ | |
"name": "name296" | |
}, | |
{ | |
"name": "name297" | |
}, | |
{ | |
"name": "name298" | |
}, | |
{ | |
"name": "name299" | |
}, | |
{ | |
"name": "name300" | |
}, | |
{ | |
"name": "name301" | |
}, | |
{ | |
"name": "name302" | |
}, | |
{ | |
"name": "name303" | |
} | |
], | |
"name": "name204" | |
}, | |
{ | |
"children": [ | |
{ | |
"name": "name305" | |
}, | |
{ | |
"name": "name306" | |
}, | |
{ | |
"name": "name307" | |
}, | |
{ | |
"name": "name308" | |
}, | |
{ | |
"name": "name309" | |
}, | |
{ | |
"name": "name310" | |
}, | |
{ | |
"name": "name311" | |
}, | |
{ | |
"name": "name312" | |
}, | |
{ | |
"name": "name313" | |
}, | |
{ | |
"name": "name314" | |
}, | |
{ | |
"name": "name315" | |
}, | |
{ | |
"name": "name316" | |
}, | |
{ | |
"name": "name317" | |
}, | |
{ | |
"name": "name318" | |
}, | |
{ | |
"name": "name319" | |
}, | |
{ | |
"name": "name320" | |
}, | |
{ | |
"name": "name321" | |
}, | |
{ | |
"name": "name322" | |
}, | |
{ | |
"name": "name323" | |
}, | |
{ | |
"name": "name324" | |
}, | |
{ | |
"name": "name325" | |
}, | |
{ | |
"name": "name326" | |
}, | |
{ | |
"name": "name327" | |
}, | |
{ | |
"name": "name328" | |
}, | |
{ | |
"name": "name329" | |
}, | |
{ | |
"name": "name330" | |
}, | |
{ | |
"name": "name331" | |
}, | |
{ | |
"name": "name332" | |
}, | |
{ | |
"name": "name333" | |
}, | |
{ | |
"name": "name334" | |
}, | |
{ | |
"name": "name335" | |
}, | |
{ | |
"name": "name336" | |
}, | |
{ | |
"name": "name337" | |
}, | |
{ | |
"name": "name338" | |
}, | |
{ | |
"name": "name339" | |
}, | |
{ | |
"name": "name340" | |
}, | |
{ | |
"name": "name341" | |
}, | |
{ | |
"name": "name342" | |
}, | |
{ | |
"name": "name343" | |
}, | |
{ | |
"name": "name344" | |
}, | |
{ | |
"name": "name345" | |
}, | |
{ | |
"name": "name346" | |
}, | |
{ | |
"name": "name347" | |
}, | |
{ | |
"name": "name348" | |
}, | |
{ | |
"name": "name349" | |
}, | |
{ | |
"name": "name350" | |
}, | |
{ | |
"name": "name351" | |
}, | |
{ | |
"name": "name352" | |
}, | |
{ | |
"name": "name353" | |
}, | |
{ | |
"name": "name354" | |
}, | |
{ | |
"name": "name355" | |
}, | |
{ | |
"name": "name356" | |
}, | |
{ | |
"name": "name357" | |
}, | |
{ | |
"name": "name358" | |
}, | |
{ | |
"name": "name359" | |
}, | |
{ | |
"name": "name360" | |
}, | |
{ | |
"name": "name361" | |
}, | |
{ | |
"name": "name362" | |
}, | |
{ | |
"name": "name363" | |
}, | |
{ | |
"name": "name364" | |
}, | |
{ | |
"name": "name365" | |
}, | |
{ | |
"name": "name366" | |
}, | |
{ | |
"name": "name367" | |
}, | |
{ | |
"name": "name368" | |
}, | |
{ | |
"name": "name369" | |
}, | |
{ | |
"name": "name370" | |
}, | |
{ | |
"name": "name371" | |
}, | |
{ | |
"name": "name372" | |
}, | |
{ | |
"name": "name373" | |
}, | |
{ | |
"name": "name374" | |
}, | |
{ | |
"name": "name375" | |
}, | |
{ | |
"name": "name376" | |
}, | |
{ | |
"name": "name377" | |
}, | |
{ | |
"name": "name378" | |
}, | |
{ | |
"name": "name379" | |
}, | |
{ | |
"name": "name380" | |
}, | |
{ | |
"name": "name381" | |
}, | |
{ | |
"name": "name382" | |
}, | |
{ | |
"name": "name383" | |
}, | |
{ | |
"name": "name384" | |
}, | |
{ | |
"name": "name385" | |
}, | |
{ | |
"name": "name386" | |
}, | |
{ | |
"name": "name387" | |
}, | |
{ | |
"name": "name388" | |
}, | |
{ | |
"name": "name389" | |
}, | |
{ | |
"name": "name390" | |
}, | |
{ | |
"name": "name391" | |
}, | |
{ | |
"name": "name392" | |
}, | |
{ | |
"name": "name393" | |
}, | |
{ | |
"name": "name394" | |
}, | |
{ | |
"name": "name395" | |
}, | |
{ | |
"name": "name396" | |
}, | |
{ | |
"name": "name397" | |
}, | |
{ | |
"name": "name398" | |
}, | |
{ | |
"name": "name399" | |
}, | |
{ | |
"name": "name400" | |
}, | |
{ | |
"name": "name401" | |
}, | |
{ | |
"name": "name402" | |
}, | |
{ | |
"name": "name403" | |
} | |
], | |
"name": "name304" | |
} | |
] | |
} | |
] | |
}, | |
{ | |
"name": "name404", | |
"children": [ | |
{ | |
"name": "name405", | |
"children": [ | |
{ | |
"name": "name406", | |
"children": [ | |
{ | |
"name": "name407" | |
}, | |
{ | |
"name": "name408" | |
}, | |
{ | |
"name": "name409" | |
}, | |
{ | |
"name": "name410" | |
}, | |
{ | |
"name": "name411" | |
}, | |
{ | |
"name": "name412" | |
}, | |
{ | |
"name": "name413" | |
}, | |
{ | |
"name": "name414" | |
}, | |
{ | |
"name": "name415" | |
}, | |
{ | |
"name": "name416" | |
}, | |
{ | |
"name": "name417" | |
}, | |
{ | |
"name": "name418" | |
}, | |
{ | |
"name": "name419" | |
}, | |
{ | |
"name": "name420" | |
}, | |
{ | |
"name": "name421" | |
}, | |
{ | |
"name": "name422" | |
}, | |
{ | |
"name": "name423" | |
}, | |
{ | |
"name": "name424" | |
}, | |
{ | |
"name": "name425" | |
}, | |
{ | |
"name": "name426" | |
}, | |
{ | |
"name": "name427" | |
}, | |
{ | |
"name": "name428" | |
}, | |
{ | |
"name": "name429" | |
}, | |
{ | |
"name": "name430" | |
}, | |
{ | |
"name": "name431" | |
}, | |
{ | |
"name": "name432" | |
}, | |
{ | |
"name": "name433" | |
}, | |
{ | |
"name": "name434" | |
}, | |
{ | |
"name": "name435" | |
}, | |
{ | |
"name": "name436" | |
}, | |
{ | |
"name": "name437" | |
}, | |
{ | |
"name": "name438" | |
}, | |
{ | |
"name": "name439" | |
}, | |
{ | |
"name": "name440" | |
}, | |
{ | |
"name": "name441" | |
}, | |
{ | |
"name": "name442" | |
}, | |
{ | |
"name": "name443" | |
}, | |
{ | |
"name": "name444" | |
}, | |
{ | |
"name": "name445" | |
}, | |
{ | |
"name": "name446" | |
}, | |
{ | |
"name": "name447" | |
}, | |
{ | |
"name": "name448" | |
}, | |
{ | |
"name": "name449" | |
}, | |
{ | |
"name": "name450" | |
}, | |
{ | |
"name": "name451" | |
}, | |
{ | |
"name": "name452" | |
}, | |
{ | |
"name": "name453" | |
}, | |
{ | |
"name": "name454" | |
}, | |
{ | |
"name": "name455" | |
}, | |
{ | |
"name": "name456" | |
}, | |
{ | |
"name": "name457" | |
}, | |
{ | |
"name": "name458" | |
}, | |
{ | |
"name": "name459" | |
}, | |
{ | |
"name": "name460" | |
}, | |
{ | |
"name": "name461" | |
}, | |
{ | |
"name": "name462" | |
}, | |
{ | |
"name": "name463" | |
}, | |
{ | |
"name": "name464" | |
}, | |
{ | |
"name": "name465" | |
}, | |
{ | |
"name": "name466" | |
}, | |
{ | |
"name": "name467" | |
}, | |
{ | |
"name": "name468" | |
}, | |
{ | |
"name": "name469" | |
}, | |
{ | |
"name": "name470" | |
}, | |
{ | |
"name": "name471" | |
}, | |
{ | |
"name": "name472" | |
}, | |
{ | |
"name": "name473" | |
}, | |
{ | |
"name": "name474" | |
}, | |
{ | |
"name": "name475" | |
}, | |
{ | |
"name": "name476" | |
}, | |
{ | |
"name": "name477" | |
}, | |
{ | |
"name": "name478" | |
}, | |
{ | |
"name": "name479" | |
}, | |
{ | |
"name": "name480" | |
}, | |
{ | |
"name": "name481" | |
}, | |
{ | |
"name": "name482" | |
}, | |
{ | |
"name": "name483" | |
}, | |
{ | |
"name": "name484" | |
}, | |
{ | |
"name": "name485" | |
}, | |
{ | |
"name": "name486" | |
}, | |
{ | |
"name": "name487" | |
}, | |
{ | |
"name": "name488" | |
}, | |
{ | |
"name": "name489" | |
}, | |
{ | |
"name": "name490" | |
}, | |
{ | |
"name": "name491" | |
}, | |
{ | |
"name": "name492" | |
}, | |
{ | |
"name": "name493" | |
}, | |
{ | |
"name": "name494" | |
}, | |
{ | |
"name": "name495" | |
}, | |
{ | |
"name": "name496" | |
}, | |
{ | |
"name": "name497" | |
}, | |
{ | |
"name": "name498" | |
}, | |
{ | |
"name": "name499" | |
}, | |
{ | |
"name": "name500" | |
}, | |
{ | |
"name": "name501" | |
}, | |
{ | |
"name": "name502" | |
}, | |
{ | |
"name": "name503" | |
}, | |
{ | |
"name": "name504" | |
}, | |
{ | |
"name": "name505" | |
} | |
] | |
} | |
] | |
} | |
] | |
}, | |
{ | |
"name": "name506", | |
"children": [ | |
{ | |
"name": "name507" | |
}, | |
{ | |
"name": "name508" | |
}, | |
{ | |
"name": "name509" | |
} | |
] | |
}, | |
{ | |
"name": "name510", | |
"children": [ | |
{ | |
"name": "name511" | |
}, | |
{ | |
"name": "name512" | |
} | |
] | |
}, | |
{ | |
"name": "name513", | |
"children": [ | |
{ | |
"name": "name514" | |
}, | |
{ | |
"name": "name515" | |
} | |
] | |
} | |
] | |
} |
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> | |
<head> | |
<meta charset="utf-8"> | |
<script src="https://d3js.org/d3.v4.min.js"></script> | |
<style> | |
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; } | |
</style> | |
</head> | |
<body> | |
<div class=""> | |
<div id="myGraph"></div> | |
</div> | |
<script> | |
d3.json('data.json', data => { | |
networkChart = renderChartCollapsibleNetwork() | |
.svgHeight(window.innerHeight - 30) | |
.svgWidth(window.innerWidth - 30) | |
.container('#myGraph') | |
.data({ root: data }) | |
.debug(true) | |
.run() | |
}) | |
</script> | |
<script> | |
/* | |
This code is based on following convention: | |
https://github.com/bumbeishvili/d3-coding-conventions | |
*/ | |
function renderChartCollapsibleNetwork(params) { | |
// exposed variables | |
var attrs = { | |
id: 'id' + Math.floor(Math.random() * 1000000), | |
svgWidth: 960, | |
svgHeight: 600, | |
marginTop: 0, | |
marginBottom: 5, | |
marginRight: 0, | |
marginLeft: 30, | |
nodeRadius: 18, | |
container: 'body', | |
distance: 100, | |
hiddenChildLevel: 1, | |
//hiddenChildLevel: 5, | |
nodeStroke: '#41302D', | |
nodeTextColor: '#E5E5E5', | |
linkColor: '#303030', | |
activeLinkColor: "blue", | |
hoverOpacity: 0.2, | |
maxTextDisplayZoomLevel: 1, | |
textDisplayed: true, | |
lineStrokeWidth: 1.5, | |
data: null | |
}; | |
/*############### IF EXISTS OVERWRITE ATTRIBUTES FROM PASSED PARAM ####### */ | |
var attrKeys = Object.keys(attrs); | |
attrKeys.forEach(function (key) { | |
if (params && params[key]) { | |
attrs[key] = params[key]; | |
} | |
}) | |
//innerFunctions which will update visuals | |
var updateData; | |
var filter; | |
//main chart object | |
var main = function (selection) { | |
selection.each(function scope() { | |
//calculated properties | |
var calc = {} | |
calc.chartLeftMargin = attrs.marginLeft; | |
calc.chartTopMargin = attrs.marginTop; | |
calc.chartWidth = attrs.svgWidth - attrs.marginRight - calc.chartLeftMargin; | |
calc.chartHeight = attrs.svgHeight - attrs.marginBottom - calc.chartTopMargin; | |
//########################## HIERARCHY STUFF ######################### | |
var hierarchy = {}; | |
hierarchy.root = d3.hierarchy(attrs.data.root); | |
//########################### BEHAVIORS ######################### | |
var behaviors = {}; | |
behaviors.zoom = d3.zoom().scaleExtent([0.75, 100, 8]).on('zoom', zoomed); | |
behaviors.drag = d3.drag().on("start", dragstarted).on("drag", dragged).on("end", dragended); | |
//########################### LAYOUTS ######################### | |
var layouts = {}; | |
// custom radial kayout | |
layouts.radial = d3.radial(); | |
//########################### FORCE STUFF ######################### | |
var force = {}; | |
force.link = d3.forceLink().id(d => d.id); | |
force.charge = d3.forceManyBody() | |
force.center = d3.forceCenter(calc.chartWidth / 2, calc.chartHeight / 2) | |
// prevent collide | |
force.collide = d3.forceCollide().radius(d => { | |
// if parent has many children, reduce collide strength | |
if (d.parent) { | |
if (d.parent.children.length > 10) { | |
// also slow down node movement | |
slowDownNodes(); | |
return 7; | |
} | |
} | |
// increase collide strength | |
if (d.children && d.depth > 2) { | |
return attrs.nodeRadius; | |
} | |
return attrs.nodeRadius * 2; | |
}); | |
//manually set x positions (which is calculated using custom radial layout) | |
force.x = d3.forceX() | |
.strength(0.5) | |
.x(function (d, i) { | |
// if node does not have children and is channel (depth=2) , then position it on parent's coordinate | |
if (!d.children && d.depth > 2) { | |
if (d.parent) { | |
d = d.parent | |
} | |
} | |
// custom circle projection - radius will be - (d.depth - 1) * 150 | |
return projectCircle(d.proportion, (d.depth - 1) * 150)[0]; | |
}); | |
//manually set y positions (which is calculated using d3.cluster) | |
force.y = d3.forceY() | |
.strength(0.5) | |
.y(function (d, i) { | |
// if node does not have children and is channel (depth=2) , then position it on parent's coordinate | |
if (!d.children && d.depth > 2) { | |
if (d.parent) { | |
d = d.parent | |
} | |
} | |
// custom circle projection - radius will be - (d.depth - 1) * 150 | |
return projectCircle(d.proportion, (d.depth - 1) * 150)[1]; | |
}) | |
//--------------------------------- INITIALISE FORCE SIMULATION ---------------------------- | |
// get based on top parameter simulation | |
force.simulation = d3.forceSimulation() | |
.force('link', force.link) | |
.force('charge', force.charge) | |
.force('center', force.center) | |
.force("collide", force.collide) | |
.force('x', force.x) | |
.force('y', force.y) | |
//########################### HIERARCHY STUFF ######################### | |
// flatten root | |
var arr = flatten(hierarchy.root); | |
// hide members based on their depth | |
arr.forEach(d => { | |
if (d.depth > attrs.hiddenChildLevel) { | |
d._children = d.children; | |
d.children = null; | |
} | |
}) | |
//#################################### DRAWINGS ####################### | |
//drawing containers | |
var container = d3.select(this); | |
//add svg | |
var svg = container.patternify({ tag: 'svg', selector: 'svg-chart-container' }) | |
.attr('width', attrs.svgWidth) | |
.attr('height', attrs.svgHeight) | |
.call(behaviors.zoom) | |
//add container g element | |
var chart = svg.patternify({ tag: 'g', selector: 'chart' }) | |
.attr('transform', 'translate(' + (calc.chartLeftMargin) + ',' + calc.chartTopMargin + ')'); | |
//################################ Chart Content Drawing ################################## | |
//link wrapper | |
var linksWrapper = chart.patternify({ tag: 'g', selector: 'links-wrapper' }) | |
//node wrapper | |
var nodesWrapper = chart.patternify({ tag: 'g', selector: 'nodes-wrapper' }) | |
var nodes, links, enteredNodes; | |
// reusable function which updates visual based on data change | |
update(); | |
//update visual based on data change | |
function update(clickedNode) { | |
// set xy and proportion properties with custom radial layout | |
layouts.radial(hierarchy.root); | |
//nodes and links array | |
var nodesArr = flatten(hierarchy.root, true) | |
.orderBy(d => d.depth) | |
.filter(d => !d.hidden); | |
var linksArr = hierarchy.root.links() | |
.filter(d => !d.source.hidden) | |
.filter(d => !d.target.hidden) | |
// make new nodes to appear near the parents | |
nodesArr.forEach(function (d, i) { | |
if (clickedNode && clickedNode.id == (d.parent && d.parent.id)) { | |
d.x = d.parent.x; | |
d.y = d.parent.y; | |
} | |
}); | |
//links | |
links = linksWrapper.selectAll('.link').data(linksArr, d => d.target.id); | |
links.exit().remove(); | |
links = links.enter() | |
.append('line') | |
.attr('class', 'link') | |
.merge(links).attr('stroke', '#9ecae1'); | |
links.attr('stroke', attrs.linkColor).attr('stroke-width', attrs.lineStrokeWidth) | |
//node groups | |
nodes = nodesWrapper.selectAll('.node').data(nodesArr, d => d.id); | |
var exited = nodes.exit().remove(); | |
var enteredNodes = nodes.enter() | |
.append('g') | |
.attr('class', 'node') | |
//bind event handlers | |
enteredNodes.on('click', nodeClick) | |
.on('mouseenter', nodeMouseEnter) | |
.on('mouseleave', nodeMouseLeave) | |
.call(behaviors.drag) | |
//node texts | |
enteredNodes.append('text').attr('class', 'node-texts') | |
.attr('x', 30).attr('fill', attrs.nodeTextColor) | |
.text(d => d.data.name) | |
.style('display', attrs.textDisplayed ? "initial" : "none") | |
//channels grandchildren | |
var channelsGrandchildren = enteredNodes | |
.append("circle") | |
.attr('r', 7) | |
.attr('stroke-width', 5) | |
.attr('stroke', attrs.nodeStroke) | |
//merge node groups and style it | |
nodes = enteredNodes.merge(nodes); | |
nodes | |
.attr('fill', d => { | |
return d._children ? "#3182bd" : d.children ? "#c6dbef" : "#fd8d3c"; | |
}) | |
.style('cursor', 'pointer') | |
//force simulation | |
force.simulation.nodes(nodesArr) | |
.on('tick', ticked); | |
// links simulation | |
force.simulation.force("link").links(links).id(d => d.id).distance(100).strength(d => 1); | |
} | |
//####################################### EVENT HANDLERS ######################## | |
// zoom handler | |
function zoomed() { | |
//get transform event | |
var transform = d3.event.transform; | |
attrs.lastTransform = transform; | |
// apply transform event props to the wrapper | |
chart.attr('transform', transform) | |
svg.selectAll('.node').attr("transform", function (d) { return `translate(${d.x},${d.y}) scale(${1 / (attrs.lastTransform ? attrs.lastTransform.k : 1)})`; }); | |
svg.selectAll('.link').attr("stroke-width", attrs.lineStrokeWidth / (attrs.lastTransform ? attrs.lastTransform.k : 1)); | |
// hide texts if zooming is less than certain level | |
if (transform.k < attrs.maxTextDisplayZoomLevel) { | |
svg.selectAll('.node-texts').style('display', 'none'); | |
attrs.textDisplayed = false; | |
} else { | |
svg.selectAll('.node-texts').style('display', 'initial'); | |
attrs.textDisplayed = true; | |
} | |
} | |
//tick handler | |
function ticked() { | |
// set links position | |
links.attr("x1", function (d) { return d.source.x; }) | |
.attr("y1", function (d) { return d.source.y; }) | |
.attr("x2", function (d) { return d.target.x; }) | |
.attr("y2", function (d) { return d.target.y; }); | |
//set nodes position | |
svg.selectAll('.node').attr("transform", function (d) { return `translate(${d.x},${d.y}) scale(${1 / (attrs.lastTransform ? attrs.lastTransform.k : 1)})`; }); | |
} | |
//handler drag start event | |
function dragstarted(d) { | |
//disable node fixing | |
nodes.each(d => { d.fx = null; d.fy = null }) | |
} | |
// handle dragging event | |
function dragged(d) { | |
// make dragged node fixed | |
d.fx = d3.event.x; | |
d.fy = d3.event.y; | |
} | |
//-------------------- handle drag end event --------------- | |
function dragended(d) { | |
// we are doing nothing, here , aren't we? | |
} | |
//-------------------------- node mouse hover handler --------------- | |
function nodeMouseEnter(d) { | |
//get hovered node | |
var node = d3.select(this); | |
//get links | |
var links = hierarchy.root.links(); | |
//get hovered node connected links | |
var connectedLinks = links.filter(l => l.source.id == d.id || l.target.id == d.id); | |
//get hovered node linked nodes | |
var linkedNodes = connectedLinks.map(s => s.source.id).concat(connectedLinks.map(d => d.target.id)) | |
//reduce all other nodes opacity | |
nodesWrapper.selectAll('.node') | |
.filter(n => linkedNodes.indexOf(n.id) == -1) | |
.attr('opacity', attrs.hoverOpacity); | |
//reduce all other links opacity | |
linksWrapper.selectAll('.link').attr('opacity', attrs.hoverOpacity); | |
//highlight hovered nodes connections | |
linksWrapper.selectAll('.link') | |
.filter(l => l.source.id == d.id || l.target.id == d.id) | |
.attr('opacity', 1) | |
.attr('stroke', attrs.activeLinkColor) | |
} | |
// --------------- handle mouseleave event --------------- | |
function nodeMouseLeave(d) { | |
// return things back to normal | |
nodesWrapper.selectAll('.node').attr('opacity', 1); | |
linksWrapper.selectAll('.link').attr('opacity', 1).attr('stroke', attrs.linkColor) | |
} | |
// --------------- handle node click event --------------- | |
function nodeClick(d) { | |
//free fixed nodes | |
nodes.each(d => { d.fx = null; d.fy = null }) | |
// collapse or expand node | |
if (d.children) { | |
d._children = d.children; | |
d.children = null; | |
update(); | |
force.simulation.restart(); | |
force.simulation.alphaTarget(0.15); | |
} else if (d._children) { | |
d.children = d._children; | |
d._children = null; | |
update(d); | |
force.simulation.restart(); | |
force.simulation.alphaTarget(0.15); | |
} else { | |
//nothing is to collapse or expand | |
} | |
freeNodes(); | |
} | |
//######################################### UTIL FUNCS ################################## | |
updateData = function () { | |
main.run(); | |
} | |
function slowDownNodes() { | |
force.simulation.alphaTarget(0.05); | |
}; | |
function speedUpNodes() { | |
force.simulation.alphaTarget(0.45); | |
} | |
function freeNodes() { | |
d3.selectAll('.node').each(n => { n.fx = null; n.fy = null; }) | |
} | |
function projectCircle(value, radius) { | |
var r = radius || 0; | |
var corner = value * 2 * Math.PI; | |
return [Math.sin(corner) * r, -Math.cos(corner) * r] | |
} | |
//recursively loop on children and extract nodes as an array | |
function flatten(root, clustered) { | |
var nodesArray = []; | |
var i = 0; | |
function recurse(node, depth) { | |
if (node.children) | |
node.children.forEach(function (child) { | |
recurse(child, depth + 1); | |
}); | |
if (!node.id) node.id = ++i; | |
else ++i; | |
node.depth = depth; | |
if (clustered) { | |
if (!node.cluster) { | |
// if cluster coordinates are not set, set it | |
node.cluster = { x: node.x, y: node.y } | |
} | |
} | |
nodesArray.push(node); | |
} | |
recurse(root, 1); | |
return nodesArray; | |
} | |
function debug() { | |
if (attrs.isDebug) { | |
//stringify func | |
var stringified = scope + ""; | |
// parse variable names | |
var groupVariables = stringified | |
//match var x-xx= {}; | |
.match(/var\s+([\w])+\s*=\s*{\s*}/gi) | |
//match xxx | |
.map(d => d.match(/\s+\w*/gi).filter(s => s.trim())) | |
//get xxx | |
.map(v => v[0].trim()) | |
//assign local variables to the scope | |
groupVariables.forEach(v => { | |
main['P_' + v] = eval(v) | |
}) | |
} | |
} | |
debug(); | |
}); | |
}; | |
//----------- PROTOTYEPE FUNCTIONS ---------------------- | |
d3.selection.prototype.patternify = function (params) { | |
var container = this; | |
var selector = params.selector; | |
var elementTag = params.tag; | |
var data = params.data || [selector]; | |
// pattern in action | |
var selection = container.selectAll('.' + selector).data(data) | |
selection.exit().remove(); | |
selection = selection.enter().append(elementTag).merge(selection) | |
selection.attr('class', selector); | |
return selection; | |
} | |
// custom radial layout | |
d3.radial = function () { | |
return function setProportions(root) { | |
recurse(root, 0, 1); | |
function recurse(node, min, max) { | |
node.proportion = (max + min) / 2; | |
if (!node.x) { | |
// if node has parent, match entered node positions to it's parent | |
if (node.parent) { | |
node.x = node.parent.x; | |
} else { | |
node.x = 0; | |
} | |
} | |
// if node had parent, match entered node positions to it's parent | |
if (!node.y) { | |
if (node.parent) { | |
node.y = node.parent.y; | |
} else { | |
node.y = 0; | |
} | |
} | |
//recursively do the same for children | |
if (node.children) { | |
var offset = (max - min) / node.children.length; | |
node.children.forEach(function (child, i, arr) { | |
var newMin = min + offset * i; | |
var newMax = newMin + offset; | |
recurse(child, newMin, newMax); | |
}); | |
} | |
} | |
} | |
} | |
//https://github.com/bumbeishvili/d3js-boilerplates#orderby | |
Array.prototype.orderBy = function (func) { | |
this.sort((a, b) => { | |
var a = func(a); | |
var b = func(b); | |
if (typeof a === 'string' || a instanceof String) { | |
return a.localeCompare(b); | |
} | |
return a - b; | |
}); | |
return this; | |
} | |
//########################## BOILEPLATE STUFF ################ | |
//dinamic keys functions | |
Object.keys(attrs).forEach(key => { | |
// Attach variables to main function | |
return main[key] = function (_) { | |
var string = `attrs['${key}'] = _`; | |
if (!arguments.length) { return eval(` attrs['${key}'];`); } | |
eval(string); | |
return main; | |
}; | |
}); | |
//set attrs as property | |
main.attrs = attrs; | |
//debugging visuals | |
main.debug = function (isDebug) { | |
attrs.isDebug = isDebug; | |
if (isDebug) { | |
if (!window.charts) window.charts = []; | |
window.charts.push(main); | |
} | |
return main; | |
} | |
//exposed update functions | |
main.data = function (value) { | |
if (!arguments.length) return attrs.data; | |
attrs.data = value; | |
if (typeof updateData === 'function') { | |
updateData(); | |
} | |
return main; | |
} | |
// run visual | |
main.run = function () { | |
d3.selectAll(attrs.container).call(main); | |
return main; | |
} | |
main.filter = function (filterParams) { | |
if (!arguments.length) return attrs.filterParams; | |
attrs.filterParams = filterParams; | |
if (typeof filter === 'function') { | |
filter(); | |
} | |
return main; | |
} | |
return main; | |
} | |
</script> | |
</body> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment