Built with blockbuilder.org
forked from anonymous's block: d3.v4 collapsible force zoomable draggable radial tree using svg
license: mit |
Built with blockbuilder.org
forked from anonymous's block: d3.v4 collapsible force zoomable draggable radial tree using svg
{ | |
"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" | |
} | |
] | |
} | |
] | |
} |
<!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> |