效果图:
html代码如下:
<!DOCTYPE html>
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>demo</title>
<link id="bootstrap_221" rel="stylesheet" type="text/css" class="library" href="./bootstrap.min.css">
<script id="others_raphael_210" type="text/javascript" class="library" src="./raphael-min.js"></script>
<script id="jquery_172" type="text/javascript" class="library" src="./jquery-1.7.2.min.js"></script>
<script id="bootstrap_221" type="text/javascript" class="library" src="./bootstrap.min.js"></script>
</head>
<body>
<span id="forkongithub"><a href="https://github.com/lynndon/cloudrelation" target="_blank">Fork me on GitHub</a></span>
<table>
<tbody><tr>
<td valign="top">
<div id="svg-container-view"><div id="cloudSpectrum-1"><svg height="400" version="1.1" width="600" xmlns="http://www.w3.org/2000/svg" style="overflow: hidden; position: relative;"><path fill="none" stroke="#c6d9ec" d="M300,200L399.55535766263915,128.58974528404738" stroke-width="2px" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path><path fill="none" stroke="#c6d9ec" d="M300,200L352.52941850425896,73.6938076840904" stroke-width="2px" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path><path fill="none" stroke="#c6d9ec" d="M242.2011641578457,34.82041719603569L300,200" stroke-width="2px" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path><path fill="none" stroke="#c6d9ec" d="M221.16522405853834,162.03517282721367L242.2011641578457,34.82041719603569" stroke-width="2px" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path><path fill="none" stroke="#c6d9ec" d="M221.16522405853834,162.03517282721367L193.9867423278565,60.76570394568833" stroke-width="2px" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path><path fill="none" stroke="#c6d9ec" d="M221.16522405853834,162.03517282721367L156.14963679661577,100.34021369552093" stroke-width="2px" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path><path fill="none" stroke="#c6d9ec" d="M221.16522405853834,162.03517282721367L132.39360708013714,147.28283012908383" stroke-width="2px" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path><path fill="none" stroke="#c6d9ec" d="M221.16522405853834,162.03517282721367L125.04405888506136,203.9266612517659" stroke-width="2px" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path><path fill="none" stroke="#c6d9ec" d="M221.16522405853834,162.03517282721367L134.82041719603566,251.5488358421543" stroke-width="2px" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path><path fill="none" stroke="#c6d9ec" d="M300,200L221.16522405853834,162.03517282721367" stroke-width="2px" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path><path fill="none" stroke="#c6d9ec" d="M221.16522405853834,237.96482717278633L201.84860977965974,328.4201229908319" stroke-width="2px" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path><path fill="none" stroke="#c6d9ec" d="M300,200L221.16522405853834,237.96482717278633" stroke-width="2px" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path><path fill="none" stroke="#c6d9ec" d="M297.52941827882256,281.3061923159096L201.84860977965974,328.4201229908319" stroke-width="2px" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path><path fill="none" stroke="#c6d9ec" d="M297.52941827882256,281.3061923159096L391.22792401789303,333.6036031331298" stroke-width="2px" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path><path fill="none" stroke="#c6d9ec" d="M300,200L297.52941827882256,281.3061923159096" stroke-width="2px" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path><path fill="none" stroke="#c6d9ec" d="M300,200L416.55535766263915,254.4102547159526" stroke-width="2px" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path><path fill="none" stroke="#c6d9ec" d="M300,200L422.5000000000001,189.00000000000006" stroke-width="2px" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path><desc style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);">Created with Raphaël 2.1.0</desc><defs style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></defs><path fill="#ff0000" stroke="#ff0000" d="M285,225.98076211353316L315,225.98076211353316L330,200L315,174.01923788646684L285,174.01923788646684L270,200" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); cursor: pointer;" transform="matrix(1,0,0,1,0,0)" stroke-width="1.0003308879599382"></path><text x="300" y="200" text-anchor="middle" font="10px "Arial"" stroke="none" fill="#ffffff" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: middle; font-style: normal; font-variant: normal; font-weight: 400; font-size: 14px; line-height: normal; font-family: Arial; cursor: pointer;" font-size="14px" font-weight="400" transform="matrix(1,0,0,1,0,0)" stroke-width="1.0003308879599382"><tspan style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);" dy="5">贾政</tspan></text><circle cx="422.50000000000006" cy="189.00000000000006" r="25" fill="#f16729" stroke="#f16729" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); cursor: pointer;" transform="matrix(1,0,0,1,0,0)" stroke-width="1.0000008980791537"></circle><text x="422.50000000000006" y="189.00000000000006" text-anchor="middle" font="10px "Arial"" stroke="none" fill="#ffffff" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: middle; font-style: normal; font-variant: normal; font-weight: 400; font-size: 14px; line-height: normal; font-family: Arial; cursor: pointer;" font-size="14px" font-weight="400" transform="matrix(1,0,0,1,0,0)" stroke-width="1.0000008980791537"><tspan style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);" dy="5.000000000000057">王夫人</tspan></text><circle cx="416.55535766263915" cy="254.4102547159526" r="25" fill="#ca0d86" stroke="#ca0d86" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); cursor: pointer;" transform="matrix(1,0,0,1,0,0)" stroke-width="1.0001600282913357"></circle><text x="416.55535766263915" y="254.4102547159526" text-anchor="middle" font="10px "Arial"" stroke="none" fill="#ffffff" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: middle; font-style: normal; font-variant: normal; font-weight: 400; font-size: 14px; line-height: normal; font-family: Arial; cursor: pointer;" font-size="14px" font-weight="400" transform="matrix(1,0,0,1,0,0)" stroke-width="1.0001600282913357"><tspan style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);" dy="4.99619221595259">赵姨娘</tspan></text><circle cx="297.52941827882256" cy="281.3061923159096" r="25" fill="#1f1f1f" stroke="#1f1f1f" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); cursor: pointer;" transform="matrix(1,0,0,1,0,0)" stroke-width="1.0000013638603131"></circle><text x="297.52941827882256" y="281.3061923159096" text-anchor="middle" font="10px "Arial"" stroke="none" fill="#ffffff" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: middle; font-style: normal; font-variant: normal; font-weight: 400; font-size: 14px; line-height: normal; font-family: Arial; cursor: pointer;" font-size="14px" font-weight="400" transform="matrix(1,0,0,1,0,0)" stroke-width="1.0000013638603131"><tspan style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);" dy="5.001504815909584">贾珠</tspan></text><circle cx="221.16522405853834" cy="237.96482717278633" r="25" fill="#f89322" stroke="#f89322" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); cursor: pointer;" transform="matrix(1,0,0,1,0,0)" stroke-width="1.0000458191916175"></circle><text x="221.16522405853834" y="237.96482717278633" text-anchor="middle" font="10px "Arial"" stroke="none" fill="#ffffff" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: middle; font-style: normal; font-variant: normal; font-weight: 400; font-size: 14px; line-height: normal; font-family: Arial; cursor: pointer;" font-size="14px" font-weight="400" transform="matrix(1,0,0,1,0,0)" stroke-width="1.0000458191916175"><tspan style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);" dy="5.003889672786329">贾元春</tspan></text><circle cx="221.16522405853834" cy="162.03517282721367" r="25" fill="#f89322" stroke="#f89322" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); cursor: pointer;" transform="matrix(1,0,0,1,0,0)" stroke-width="1.000068243010055"></circle><text x="221.16522405853834" y="162.03517282721367" text-anchor="middle" font="10px "Arial"" stroke="none" fill="#ffffff" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: middle; font-style: normal; font-variant: normal; font-weight: 400; font-size: 14px; line-height: normal; font-family: Arial; cursor: pointer;" font-size="14px" font-weight="400" transform="matrix(1,0,0,1,0,0)" stroke-width="1.000068243010055"><tspan style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);" dy="4.996110327213671">贾宝玉</tspan></text><circle cx="352.52941850425896" cy="73.6938076840904" r="25" fill="#764394" stroke="#764394" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); cursor: pointer;" transform="matrix(1,0,0,1,0,0)" stroke-width="1.00000103678679"></circle><text x="352.52941850425896" y="73.6938076840904" text-anchor="middle" font="10px "Arial"" stroke="none" fill="#ffffff" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: middle; font-style: normal; font-variant: normal; font-weight: 400; font-size: 14px; line-height: normal; font-family: Arial; cursor: pointer;" font-size="14px" font-weight="400" transform="matrix(1,0,0,1,0,0)" stroke-width="1.00000103678679"><tspan style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);" dy="4.998495184090402">贾探春</tspan></text><circle cx="399.55535766263915" cy="128.58974528404738" r="25" fill="#ca0d86" stroke="#ca0d86" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); cursor: pointer;" transform="matrix(1,0,0,1,0,0)" stroke-width="1.0000010922699756"></circle><text x="399.55535766263915" y="128.58974528404738" text-anchor="middle" font="10px "Arial"" stroke="none" fill="#ffffff" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: middle; font-style: normal; font-variant: normal; font-weight: 400; font-size: 14px; line-height: normal; font-family: Arial; cursor: pointer;" font-size="14px" font-weight="400" transform="matrix(1,0,0,1,0,0)" stroke-width="1.0000010922699756"><tspan style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);" dy="5.003807784047382">贾环</tspan></text><circle cx="391.22792401789303" cy="333.6036031331298" r="25" fill="#87b11d" stroke="#87b11d" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); cursor: pointer;" transform="matrix(1,0,0,1,0,0)" stroke-width="1.0000161778477783"></circle><text x="391.22792401789303" y="333.6036031331298" text-anchor="middle" font="10px "Arial"" stroke="none" fill="#ffffff" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: middle; font-style: normal; font-variant: normal; font-weight: 400; font-size: 14px; line-height: normal; font-family: Arial; cursor: pointer;" font-size="14px" font-weight="400" transform="matrix(1,0,0,1,0,0)" stroke-width="1.0000161778477783"><tspan style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);" dy="5.002040633129809">李执</tspan></text><circle cx="201.84860977965974" cy="328.4201229908319" r="25" fill="#3277b5" stroke="#3277b5" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); cursor: pointer;" transform="matrix(1,0,0,1,0,0)" stroke-width="1.0000013760168998"></circle><text x="201.84860977965974" y="328.4201229908319" text-anchor="middle" font="10px "Arial"" stroke="none" fill="#ffffff" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: middle; font-style: normal; font-variant: normal; font-weight: 400; font-size: 14px; line-height: normal; font-family: Arial; cursor: pointer;" font-size="14px" font-weight="400" transform="matrix(1,0,0,1,0,0)" stroke-width="1.0000013760168998"><tspan style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);" dy="5.006060490831885">贾兰</tspan></text><path fill="#ffcf14" stroke="#ffcf14" d="M113.1697821014247,270.2988358421543L156.47105229064664,270.2988358421543L134.82041719603566,232.7988358421543" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); cursor: pointer;"></path><text x="134.82041719603566" y="257.7988358421543" text-anchor="middle" font="10px "Arial"" stroke="none" fill="#ffffff" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: middle; font-style: normal; font-variant: normal; font-weight: 400; font-size: 14px; line-height: normal; font-family: Arial; cursor: pointer;" font-size="14px" font-weight="400"><tspan style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);" dy="4.99414834215429">袭人</tspan></text><rect x="100.04405888506136" y="178.9266612517659" width="50" height="50" r="10" rx="10" ry="10" fill="#ffea0d" stroke="#ffea0d" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); cursor: pointer;" transform="matrix(1,0,0,1,0,0)" stroke-width="1.000001355088498"></rect><text x="125.04405888506136" y="203.9266612517659" text-anchor="middle" font="10px "Arial"" stroke="none" fill="#ffffff" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: middle; font-style: normal; font-variant: normal; font-weight: 400; font-size: 14px; line-height: normal; font-family: Arial; cursor: pointer;" font-size="14px" font-weight="400" transform="matrix(1,0,0,1,0,0)" stroke-width="1.000001355088498"><tspan style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);" dy="4.996973751765893">晴雯</tspan></text><path fill="#87b11d" stroke="#87b11d" d="M117.69897577282532,169.89554255877067L147.08823838744897,169.89554255877067L156.17001998751599,141.94469284002332L132.39360708013714,124.670117699397L108.6171941727583,141.94469284002332" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); cursor: pointer;" transform="matrix(1,0,0,1,0,0)" stroke-width="1.000001216319446"></path><text x="132.39360708013714" y="149.670117699397" text-anchor="middle" font="10px "Arial"" stroke="none" fill="#ffffff" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: middle; font-style: normal; font-variant: normal; font-weight: 400; font-size: 14px; line-height: normal; font-family: Arial; cursor: pointer;" font-size="14px" font-weight="400" transform="matrix(1,0,0,1,0,0)" stroke-width="1.000001216319446"><tspan style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);" dy="5.006055199396997">茜雪</tspan></text><circle cx="156.14963679661577" cy="100.34021369552093" r="25" fill="#008253" stroke="#008253" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); cursor: pointer;" transform="matrix(1,0,0,1,0,0)" stroke-width="1.000010259427918"></circle><text x="156.14963679661577" y="100.34021369552093" text-anchor="middle" font="10px "Arial"" stroke="none" fill="#ffffff" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: middle; font-style: normal; font-variant: normal; font-weight: 400; font-size: 14px; line-height: normal; font-family: Arial; cursor: pointer;" font-size="14px" font-weight="400" transform="matrix(1,0,0,1,0,0)" stroke-width="1.000010259427918"><tspan style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);" dy="5.00427619552093">麝月</tspan></text><ellipse cx="193.9867423278565" cy="60.76570394568833" rx="25" ry="15" fill="#3277b5" stroke="#3277b5" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); cursor: pointer;" transform="matrix(1,0,0,1,0,0)" stroke-width="1.0000431424976306"></ellipse><text x="193.9867423278565" y="60.76570394568833" text-anchor="middle" font="10px "Arial"" stroke="none" fill="#ffffff" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: middle; font-style: normal; font-variant: normal; font-weight: 400; font-size: 14px; line-height: normal; font-family: Arial; cursor: pointer;" font-size="14px" font-weight="400" transform="matrix(1,0,0,1,0,0)" stroke-width="1.0000431424976306"><tspan style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);" dy="4.99226644568833">秋纹</tspan></text><rect x="217.20116415784574" y="9.820417196035692" width="50" height="50" r="0" rx="0" ry="0" fill="#4c549f" stroke="#4c549f" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); cursor: pointer;" transform="matrix(1,0,0,1,0,0)" stroke-width="1.0000003948005014"></rect><text x="242.20116415784574" y="34.82041719603569" text-anchor="middle" font="10px "Arial"" stroke="none" fill="#ffffff" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: middle; font-style: normal; font-variant: normal; font-weight: 400; font-size: 14px; line-height: normal; font-family: Arial; cursor: pointer;" font-size="14px" font-weight="400" transform="matrix(1,0,0,1,0,0)" stroke-width="1.0000003948005014"><tspan style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);" dy="5.000104696035692">惠香</tspan></text><circle cx="361.25000000000006" cy="194.50000000000003" r="8" fill="#bed8ec" stroke="#c6d9ec" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);" transform="matrix(1,0,0,1,0,0)" stroke-width="1.00003175730467"></circle><text x="361.25000000000006" y="194.50000000000003" text-anchor="middle" font="10px "Arial"" stroke="#ffffff" fill="#000000" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: middle; font-style: normal; font-variant: normal; font-weight: normal; font-size: 10px; line-height: normal; font-family: Arial; cursor: pointer;" transform="matrix(1,0,0,1,0,0)" stroke-width="1.00003175730467"><tspan style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);" dy="4.500000000000028">?</tspan></text><circle cx="358.2776788313196" cy="227.2051273579763" r="8" fill="#bed8ec" stroke="#c6d9ec" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></circle><text x="358.2776788313196" y="227.2051273579763" text-anchor="middle" font="10px "Arial"" stroke="#ffffff" fill="#000000" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: middle; font-style: normal; font-variant: normal; font-weight: normal; font-size: 10px; line-height: normal; font-family: Arial; cursor: pointer;"><tspan style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);" dy="4.494189857976295">?</tspan></text><circle cx="298.76470913941125" cy="240.6530961579548" r="8" fill="#bed8ec" stroke="#c6d9ec" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);" transform="matrix(1,0,0,1,0,0)" stroke-width="1.0000445024748408"></circle><text x="298.76470913941125" y="240.6530961579548" text-anchor="middle" font="10px "Arial"" stroke="#ffffff" fill="#000000" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: middle; font-style: normal; font-variant: normal; font-weight: normal; font-size: 10px; line-height: normal; font-family: Arial; cursor: pointer;" transform="matrix(1,0,0,1,0,0)" stroke-width="1.0000445024748408"><tspan style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);" dy="4.504658657954792">?</tspan></text><circle cx="344.3786711483578" cy="307.4548977245197" r="8" fill="#bed8ec" stroke="#c6d9ec" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);" transform="matrix(1,0,0,1,0,0)" stroke-width="1.0000000998670169"></circle><text x="344.3786711483578" y="307.4548977245197" text-anchor="middle" font="10px "Arial"" stroke="#ffffff" fill="#000000" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: middle; font-style: normal; font-variant: normal; font-weight: normal; font-size: 10px; line-height: normal; font-family: Arial; cursor: pointer;" transform="matrix(1,0,0,1,0,0)" stroke-width="1.0000000998670169"><tspan style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);" dy="4.493960224519697">?</tspan></text><circle cx="249.68901402924115" cy="304.86315765337076" r="8" fill="#bed8ec" stroke="#c6d9ec" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);" transform="matrix(1,0,0,1,0,0)" stroke-width="1.0000012013995987"></circle><text x="249.68901402924115" y="304.86315765337076" text-anchor="middle" font="10px "Arial"" stroke="#ffffff" fill="#000000" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: middle; font-style: normal; font-variant: normal; font-weight: normal; font-size: 10px; line-height: normal; font-family: Arial; cursor: pointer;" transform="matrix(1,0,0,1,0,0)" stroke-width="1.0000012013995987"><tspan style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);" dy="4.495970153370763">?</tspan></text><circle cx="260.58261202926917" cy="218.98241358639316" r="8" fill="#bed8ec" stroke="#c6d9ec" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></circle><text x="260.58261202926917" y="218.98241358639316" text-anchor="middle" font="10px "Arial"" stroke="#ffffff" fill="#000000" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: middle; font-style: normal; font-variant: normal; font-weight: normal; font-size: 10px; line-height: normal; font-family: Arial; cursor: pointer;"><tspan style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);" dy="4.5058510863931645">?</tspan></text><circle cx="211.50691691909904" cy="283.1924750818091" r="8" fill="#bed8ec" stroke="#c6d9ec" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);" transform="matrix(1,0,0,1,0,0)" stroke-width="1.0000103346233973"></circle><text x="211.50691691909904" y="283.1924750818091" text-anchor="middle" font="10px "Arial"" stroke="#ffffff" fill="#000000" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: middle; font-style: normal; font-variant: normal; font-weight: normal; font-size: 10px; line-height: normal; font-family: Arial; cursor: pointer;" transform="matrix(1,0,0,1,0,0)" stroke-width="1.0000103346233973"><tspan style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);" dy="4.497162581809107">?</tspan></text><circle cx="260.58261202926917" cy="181.01758641360684" r="8" fill="#bed8ec" stroke="#c6d9ec" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></circle><text x="260.58261202926917" y="181.01758641360684" text-anchor="middle" font="10px "Arial"" stroke="#ffffff" fill="#000000" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: middle; font-style: normal; font-variant: normal; font-weight: normal; font-size: 10px; line-height: normal; font-family: Arial; cursor: pointer;"><tspan style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);" dy="4.4941489136068355">?</tspan></text><circle cx="177.99282062728702" cy="206.79200433468398" r="8" fill="#bed8ec" stroke="#c6d9ec" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></circle><text x="177.99282062728702" y="206.79200433468398" text-anchor="middle" font="10px "Arial"" stroke="#ffffff" fill="#000000" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: middle; font-style: normal; font-variant: normal; font-weight: normal; font-size: 10px; line-height: normal; font-family: Arial; cursor: pointer;"><tspan style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);" dy="4.5029418346839805">?</tspan></text><circle cx="173.10464147179985" cy="182.98091703948978" r="8" fill="#bed8ec" stroke="#c6d9ec" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></circle><text x="173.10464147179985" y="182.98091703948978" text-anchor="middle" font="10px "Arial"" stroke="#ffffff" fill="#000000" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: middle; font-style: normal; font-variant: normal; font-weight: normal; font-size: 10px; line-height: normal; font-family: Arial; cursor: pointer;"><tspan style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);" dy="4.504354539489782">?</tspan></text><circle cx="176.77941556933774" cy="154.65900147814875" r="8" fill="#bed8ec" stroke="#c6d9ec" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></circle><text x="176.77941556933774" y="154.65900147814875" text-anchor="middle" font="10px "Arial"" stroke="#ffffff" fill="#000000" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: middle; font-style: normal; font-variant: normal; font-weight: normal; font-size: 10px; line-height: normal; font-family: Arial; cursor: pointer;"><tspan style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);" dy="4.4949389781487525">?</tspan></text><circle cx="188.65743042757705" cy="131.18769326136731" r="8" fill="#bed8ec" stroke="#c6d9ec" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></circle><text x="188.65743042757705" y="131.18769326136731" text-anchor="middle" font="10px "Arial"" stroke="#ffffff" fill="#000000" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: middle; font-style: normal; font-variant: normal; font-weight: normal; font-size: 10px; line-height: normal; font-family: Arial; cursor: pointer;"><tspan style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);" dy="4.492380761367315">?</tspan></text><circle cx="207.57598319319743" cy="111.400438386451" r="8" fill="#bed8ec" stroke="#c6d9ec" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></circle><text x="207.57598319319743" y="111.400438386451" text-anchor="middle" font="10px "Arial"" stroke="#ffffff" fill="#000000" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: middle; font-style: normal; font-variant: normal; font-weight: normal; font-size: 10px; line-height: normal; font-family: Arial; cursor: pointer;"><tspan style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);" dy="4.502000886451">?</tspan></text><circle cx="231.68319410819203" cy="98.42779501162468" r="8" fill="#bed8ec" stroke="#c6d9ec" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></circle><text x="231.68319410819203" y="98.42779501162468" text-anchor="middle" font="10px "Arial"" stroke="#ffffff" fill="#000000" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: middle; font-style: normal; font-variant: normal; font-weight: normal; font-size: 10px; line-height: normal; font-family: Arial; cursor: pointer;"><tspan style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);" dy="4.498107511624681">?</tspan></text><circle cx="271.10058207892286" cy="117.41020859801785" r="8" fill="#bed8ec" stroke="#c6d9ec" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></circle><text x="271.10058207892286" y="117.41020859801785" text-anchor="middle" font="10px "Arial"" stroke="#ffffff" fill="#000000" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: middle; font-style: normal; font-variant: normal; font-weight: normal; font-size: 10px; line-height: normal; font-family: Arial; cursor: pointer;"><tspan style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);" dy="4.496146098017846">?</tspan></text><circle cx="326.2647092521295" cy="136.8469038420452" r="8" fill="#bed8ec" stroke="#c6d9ec" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);" transform="matrix(1,0,0,1,0,0)" stroke-width="1.0000145437404957"></circle><text x="326.2647092521295" y="136.8469038420452" text-anchor="middle" font="10px "Arial"" stroke="#ffffff" fill="#000000" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: middle; font-style: normal; font-variant: normal; font-weight: normal; font-size: 10px; line-height: normal; font-family: Arial; cursor: pointer;" transform="matrix(1,0,0,1,0,0)" stroke-width="1.0000145437404957"><tspan style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);" dy="4.495341342045208">?</tspan></text><circle cx="349.7776788313196" cy="164.29487264202368" r="8" fill="#bed8ec" stroke="#c6d9ec" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></circle><text x="349.7776788313196" y="164.29487264202368" text-anchor="middle" font="10px "Arial"" stroke="#ffffff" fill="#000000" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: middle; font-style: normal; font-variant: normal; font-weight: normal; font-size: 10px; line-height: normal; font-family: Arial; cursor: pointer;"><tspan style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);" dy="4.505810142023677">?</tspan></text></svg></div></div>
</td>
<td>
<b>使用方法:</b><br>
<code>
var relation = new Relation({node: '#svg-container-view', width:600, height:400, mode: 'edit'});
relation.render(data);
</code>
<br>
数据json格式:<br>
<code>
{"id":"300003", //节点Id<br>
"name":"", //节点名称<br>
"parent":"0", //父节点<br>
"type":"people", //节点类型<br>
"color":"#ff0000", //形状颜色<br>
"shape":6, //形状类型<br>
"weight":15, //权重<br>
"childNodes":[{"id":"400008",<br>
"name":"王夫人",<br>
"parent":"300002",<br>
"weight":10,<br>
"type":"place",<br>
"color":"#F16729",<br>
"shape":1,<br>
"childNodes":[...]}<br>
]<br>
}<br>
</code>
<br>
node: Dom节点<br>
mode:有两种模式,编辑模式和显示模式,编辑模式下形状可以拖动,显示模式下不可以<br>
<b>方法:</b><br>
relation.preview(); //得到树形数据,包含形状形状的坐标<br>
ralation.save(); //得到数据数组,平面数据<br>
<b>事件:</b><br>
relation.on('nodeClick', function(e){}); //节点点击事件<br>
ralation.on('relationClick', function(e){}); //两节点关系单击事件<br>
<br>
e:{x: 967, y: 371, id: "500001", parentId: "400010"}<br>
<br><br>
<a href="http://top.baidu.com/detail?b=258&w=%CD%F5%D1%C7%C6%BD" class="btn btn-large btn-primary" target="_blank" type="button">类似于百度 图谱 点击查看</a>
</td>
</tr>
</tbody></table>
<style>button{
border:1px solid #ccc;
cursor:pointer;
display:block;
margin:auto;
position:relative;
top:100px;
}
#forkongithub a{background:#000;color:#fff;text-decoration:none;font-family:arial, sans-serif;text-align:center;font-weight:bold;padding:5px 40px;font-size:1rem;line-height:2rem;position:relative;transition:0.5s;}
#forkongithub a:hover{background:#060;color:#fff;}
#forkongithub a::before,#forkongithub a::after{content:"";width:100%;display:block;position:absolute;top:1px;left:0;height:1px;background:#fff;}
#forkongithub a::after{bottom:1px;top:auto;}
@media screen and (min-width:800px){#forkongithub{position:absolute;display:block;top:0;right:0;width:200px;overflow:hidden;height:200px;}
#forkongithub a{width:200px;position:absolute;top:60px;right:-60px;transform:rotate(45deg);-webkit-transform:rotate(45deg);box-shadow:4px 4px 10px rgba(0,0,0,0.8);}
}
#newsPanel{position:absolute;left:0;top:0;background:#fff;border:1px #000 solid;padding:10px;width:300px;font-size:14px;}#newsPanel .arrow{position:absolute;width:0;height:0;border:15px dashed transparent;border-right:15px solid #000;top:50%;margin-top:-15px;margin-left:-40px;}#newsPanel .arrow2{position:absolute;width:0;height:0;border:15px dashed transparent;border-right:15px solid #fff;top:50%;margin-top:-15px;margin-left:-39px;}#newsPanel ul,#newsPanel li{margin:0;padding:0;}#newsPanel li{list-style:none;display:block;margin-top:4px;margin-bottom:4px;width:280px;height:16px;overflow:hidden;text-overflow:ellipsis;}#newsPanel a{text-decoration:none;}#newsPanel .close{position:absolute;right:10px;top:0;width:10px;height:10px;font-size:20px;cursor:pointer;}
</style>
<script>var Relation = (function(){
var _uuid = 0;
function CloudRelation(opt) {
'use strict';
var _DEFAULT = {
node: '',
width: 600,
height: 400,
mode: 'edit'
};
this.cfg = this.merge(_DEFAULT, opt);
this.eventHandlers = [];
this.cache = {};
this._init();
}
CloudRelation.prototype = {
constructor: CloudRelation,
_init: function(){
var self = this, cfg = self.cfg, w=cfg.width, h=cfg.height;
node = self.dom().get(cfg.node);
node.width(w);
node.height(h);
var divId = 'cloudSpectrum-'+self._guid();
node.html('<div id="'+divId+'"></div>');
self.paper = Raphael(divId, w, h);
//self.paper.rect(0, 0, w, h, 10).attr({'stroke': "#666"});
//Rapheal插件扩展
Raphael.fn.connection = function (obj1, obj2, nodeOption) {
var line;
if (obj1.line && obj1.from && obj1.to) {
line = obj1;
obj1 = line.from;
obj2 = line.to;
}
var bb1 = obj1.getBBox(),
bb2 = obj2.getBBox(),
po = [{x: bb1.x + bb1.width / 2, y: bb1.y + bb1.height / 2},
{x: bb2.x + bb2.width / 2, y: bb2.y + bb2.height / 2},
{x: bb2.x + bb2.width / 2, y: bb2.y + bb2.height / 2}],
poc = {x: (po[1].x + po[0].x)/2, y: (po[1].y + po[0].y)/2};
//var path = ["M", x1.toFixed(3), y1.toFixed(3), "L", x2, y2, x3, y3, x4.toFixed(3), y4.toFixed(3)].join(",");
var path = ["M", po[0].x, po[0].y, "L", po[1].x, po[1].y].join(",");
if (line && line.line) {
line.line.toBack().attr({path: path});
line.lineNode.attr({x: poc.x, y:poc.y, cx: poc.x, cy: poc.y});
} else {
var color = typeof line == "string" ? line : "#000";
return {
line: this.path(path).toBack().attr({'stroke': '#C6D9EC', 'stroke-width': '2px', fill: "none"}),
from: obj1,
to: obj2,
lineNode: self.paper.set().push(this.circle(poc.x, poc.y, 8).attr({fill: '#BED8EC', stroke: '#C6D9EC'}), this.text(poc.x, poc.y, '?').attr({stroke: '#fff', cursor: 'pointer'})),
lineOpt: nodeOption
};
}
};
},
render: function(data){
var self = this, cfg = self.cfg, dom = self.dom(), r = self.paper;
self.connections = [],
self.shapes = []; //svg形状集合
self.flatData = []; //平面数据(非树状)
self.data = data;
self.cache = {};
self.cache.w = cfg.width; //画布宽
self.cache.h = cfg.height; //画布高
self.objects = {}; //所有元素缓存
var shapes = self.shapes, cache = self.cache,
objs = self.objects, flatData = self.flatData;
//样式
var CENTER_STYLE = {'fill': '#5782C2', 'stroke': '#5782C2'},
TEXT_STYLE = {'fill': '#fff', 'font-size': '14px', 'font-weight': '400'};
//极径
var min = Math.round(Math.max(cache.w, cache.h)/6), circleRadius = Math.round(min/4);
self.circleRadius = circleRadius;
var _stack = [], levelStack=[], level=1;
_stack.push(data);
draw(_stack); //绘制
var ms=false, tar, mar, tardata, delay = false;
function dragger() {
if(this.data('setIndex') && this.data('dataIndex') != undefined){
tar = shapes[this.data('setIndex')];
tardata = flatData[this.data('dataIndex')];
var btar = tar.getBBox();
mar = {};
ms = true;
mar.ox = btar.x;
mar.oy = btar.y;
mar.cox = btar.x + btar.width / 2;
mar.coy = btar.y + btar.height / 2;
}
}
function move(dx, dy){
if(ms){
var finalx = mar.cox + dx, finaly = mar.coy + dy;
var att = {'x': finalx, 'y': finaly, 'cx': finalx, 'cy': finaly};
if(!delay){
tar.attr(att);
tardata.theta = Raphael.rad(Raphael.angle(finalx, finaly, cache.w/2, cache.h/2));
tardata.radius = self._computeLength(cache.w/2, cache.h/2, finalx, finaly);
delay = true;
setTimeout(function(){
delay = false;
}, 40);
}
for (var i = connections.length; i--;) {
r.connection(connections[i]);
}
r.safari();
}
}
function up(){
if(ms){
ms = false;
}
}
for(var i = 0, ii = shapes.length; i < ii; i++) {
var color = Raphael.getColor();
var s = shapes[i];
s.attr({cursor: "pointer"});
if(cfg.mode == 'edit'){
s.attr({cursor: "move"});
s.drag(move, dragger, up); //拖动
}
(function(sha){
sha.mouseover(function () {
sha.stop().animate({transform: "s1.2 1.2"}, 500, "backOut");
}).mouseout(function () {
sha.stop().animate({transform: ""}, 500, "backOut");
});
if(cfg.mode == 'view'){
sha.click(function(e){
var di = this.data('dataIndex');
alert(di);
self._publish('nodeClick', {x:e.pageX, y:e.pageY, id: flatData[di].id});
});
}else{
sha.dblclick(function(e){
var di = this.data('dataIndex');
self._publish('nodeClick', {x:e.pageX, y:e.pageY, id: flatData[di].id});
});
}
})(s);
}
var connections = [];
connect(data, data.childNodes);
function connect(parent, children, pc){
var pobj = objs[parent.id];
if(children.length > 0){
for(var i=0; i<children.length; i++){
if(children[i]){
var child = children[i], id = child.id, obj = objs[id];
connections.push(r.connection(shapes[pobj.index], shapes[obj.index], {pid: parent.id, id:id}));
connect(child, child.childNodes);
}
}
}
}
for (var i = 0, ii = connections.length; i < ii; i++) {
var cs = connections[i];
(function(cln, opt){
if(cln){
cln.mouseover(function () {
cln.stop().animate({'transform': "s1.2 1.2"}, 500, "backOut");
}).mouseout(function () {
cln.stop().animate({'transform': ""}, 500, "backOut");
});
cln.click(function(e){
var clickX = e.pageX;
var clickY = e.pageY;
self._publish('relationClick', {x: clickX, y:clickY, id: opt.id, parentId: opt.pid});
});
}
})(cs.lineNode, cs.lineOpt);
}
/**
* 遍历绘制节点
*@param 栈(先进后出)
*/
function draw(stack){
var pc = 0;
while(stack.length>0){
var node = stack.shift();
if(node){
if(node.parent == 0){
//根节点
var x = cache.w/2, y = cache.h/2;
//中心点
var idx = self.shapes.length;
var sha = drawShape(node.shape+'', [x, y], circleRadius*1.2);
sha.attr({'fill': node.color, 'stroke': node.color}).data('setIndex', idx);
shapes.push(r.set().push(sha, r.text(x, y, node.name).attr(TEXT_STYLE).data('setIndex', idx).data('dataIndex', idx)));
objs[node.id] = {'x': x, 'y': y, 'theta':0, 'index':0};
node.theta = 0;
node.radius = 0;
flatData.push(self.clone(node));
//第一层节点
if(node.childNodes.length > 0){
levelStack.push(node.childNodes.length);
}
drawChildNode({x: x, y: y}, node.childNodes);
stack = stack.concat(node.childNodes);
level++;
}else{
var pos = objs[node.id];
//var x = pos.x, y = pos.y;
//var rad = Math.round(circleRadius), idx = self.shapes.length;
if(pc == levelStack[0]){
levelStack.shift();
pc = 0;
level++;
levelStack.push(node.childNodes.length);
} else {
if(levelStack[1]){
levelStack[1] = levelStack[1] + node.childNodes.length;
}else{
levelStack[1] = node.childNodes.length;
}
}
drawChildNode(pos, node.childNodes);
stack = stack.concat(node.childNodes);
pc++;
}
}
}
}
/**
* 绘制子节点
*@param pos 父节点位置对象,x,y坐标和极角
*@param chidren 子节点数组
*@param angle 极角
*/
function drawChildNode(pos, children){
if(!children.length){
return;
}
var len = children.length, averWeight = self._getAverageWeight(children);
if(pos.theta !== undefined){
//var averAngle = Math.atan(circleRadius*2.2/polarRadius);
//var averAngle = Math.PI/6;
//var a0 = Math.PI/2 - averAngle*(len-1)/2 - pos.theta;
var averAngle = Math.PI/len;
if(level == 2){
averAngle = Math.PI/10;
}
if(level == 3){
if(averAngle>Math.PI/24){
averAngle = Math.PI/24;
}
}
var a0 = averAngle*(len-1)/2 - pos.theta;
//var rad =polarRadius + cache.level*circleRadius;
for(var i=0; i<len; i++){
//var rad =polarRadius*children[i].weight/averWeight;
drawSingleNode(children[i], pos, (level*3.5)*circleRadius, -a0+i*averAngle);
}
}else{
//第一层子节点场合
var averAngle = 2*Math.PI/len;
for(var i=0; i<len; i++){
//var rad =polarRadius*children[i].weight/averWeight;
drawSingleNode(children[i], pos, (level*3.5)*circleRadius, i*averAngle);
}
}
}
/**
* 绘制单个节点
*@param pos 父节点位置对象
*@param rad 极径
*@param angle 极角
*/
function drawSingleNode(node, pos, rad, angle){
if(objs[node.id]){
return;
}
var index = flatData.length;
var p, idx = self.shapes.length;
if(cfg.mode == 'edit'){
p = self._polarToXY(pos, rad, angle);
}else{
p = self._polarToXY(pos, node.radius, node.theta);
}
var nodeShape;
if(cfg.mode == 'edit'){
nodeShape = drawShape('3', p, circleRadius).attr({'fill': node.color, 'stroke': node.color}).data('setIndex', idx);
}else{
nodeShape = drawShape(node.shape+'', p, circleRadius).attr({'fill': node.color, 'stroke': node.color}).data('setIndex', idx);
}
shapes.push(r.set().push(nodeShape, r.text(p[0], p[1], node.name).attr(TEXT_STYLE).data('setIndex', idx).data('dataIndex', index)));
objs[node.id] = {'x': p[0], 'y': p[1], 'theta': angle, 'index': idx};
node.theta = angle;
node.radius = rad;
flatData.push(self.clone(node));
}
function drawShape(shapeType, p, circleRadius){
var shape;
switch(shapeType){
case '1':
shape = r.rect(p[0]-circleRadius, p[1]-circleRadius, circleRadius*2, circleRadius*2);
break;
case '2':
shape = r.ellipse(p[0], p[1], circleRadius, circleRadius*0.6);
break;
case '3':
shape = r.circle(p[0], p[1], circleRadius);
break;
case '4':
shape = drawPentagonal(p[0], p[1], circleRadius);
break;
case '5':
shape = drawTriangle(p[0], p[1], circleRadius);
break;
case '6':
shape = drawHexagon(p[0], p[1], circleRadius);
break;
case '7':
shape = r.rect(p[0]-circleRadius, p[1]-circleRadius, circleRadius*2, circleRadius*2, 10);
break;
default:
shape = r.circle(p[0], p[1], circleRadius);
break;
};
return shape;
}
//三角形
function drawTriangle(x, y, rad){
var cos = rad*Math.cos(Math.PI/3), sin = rad*Math.sin(Math.PI/3);
var x1 = x-sin, y1 = y+cos,
x2 = x+sin, y2 = y+cos,
x3 = x, y3 = y-rad;
var path = ['M', x1, y1, 'L', x2, y2, 'L', x3, y3].join(' ');
return r.path(path);
}
//五角形
function drawPentagonal(x, y, rad){
var cos36 = rad*Math.cos(36*Math.PI/180), sin36 = rad*Math.sin(36*Math.PI/180),
cos18 = rad*Math.cos(18*Math.PI/180), sin18 = rad*Math.sin(18*Math.PI/180);
var x1 = x-sin36, y1 = y+cos36,
x2 = x+sin36, y2 = y+cos36,
x3 = x+cos18, y3 = y-sin18,
x4 = x, y4 = y-rad,
x5 = x-cos18, y5 = y-sin18;
var path = ['M', x1, y1, 'L', x2, y2, 'L', x3, y3, 'L', x4, y4, 'L', x5, y5].join(' ');
return r.path(path);
}
//六角形
function drawHexagon(x, y, rad){
var cos30 = rad*Math.cos(Math.PI/6), sin30 = rad*Math.sin(Math.PI/6);
var x1 = x-sin30, y1 = y+cos30,
x2 = x+sin30, y2 = y+cos30,
x3 = x+rad, y3 = y,
x4 = x+sin30, y4 = y-cos30,
x5 = x-sin30, y5 = y-cos30,
x6 = x-rad, y6 =y;
var path = ['M', x1, y1, 'L', x2, y2, 'L', x3, y3, 'L', x4, y4, 'L', x5, y5, 'L', x6, y6].join(' ');
return r.path(path);
}
},
save: function(){
var self = this, result=[];
for(var i=self.flatData.length-1; i>=0; i--){
var item = self.flatData[i];
result.push(item);
}
return result;
},
preview: function(){
var self = this, data=self.data, flatData=self.flatData;
function iterate(nodes){
for(var i=0, ii=nodes.length; i<ii; i++){
var cur = nodes[i];
for(var j=0; j<flatData.length; j++){
if(cur.id == flatData[j].id){
cur.theta = flatData[j].theta;
cur.radius = flatData[j].radius;
}
iterate(cur.childNodes);
}
}
}
iterate([data]);
return data;
},
on: function(type, func){
var self = this;
self.eventHandlers[type] = func;
},
_publish: function(type, data){
var self = this, handlers = self.eventHandlers;
if(handlers[type]){
handlers[type].call(null, data);
}
},
//generate global unique id
_guid: function(){
return ++_uuid;
},
//极坐标转直角坐标
_polarToXY: function(pos, rad, angle){
var self = this, cache = self.cache, x = cache.w/2, y = cache.h/2, radis = self.circleRadius;
//var a = Raphael.angle(x, y, pos.x+radis*Math.cos(angle), pos.y+radis*Math.sin(angle))*Math.PI/180;
return [x+rad*Math.cos(angle), y+rad*Math.sin(angle)];
},
//计算长度
_computeLength: function(x1, y1, x2, y2){
return Math.sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
},
//取得平均权值
_getAverageWeight: function(arr){
if(!arr.length) return 0;
var sum=0;
for(var i=0, ii=arr.length; i<ii; i++){
sum += arr[i].weight;
}
return sum/arr.length
},
//merge
merge: function(obj1, obj2){
return obj2;
},
clone: function(obj){
var objClone = new Object();
for(var key in obj){
if (Object.prototype.toString.call(obj[key]) == '[object Array]'){
objClone[key] = [];
}else{
objClone[key] = obj[key];
}
}
return objClone;
},
util: {
substitute: function(str, obj){
if (!(Object.prototype.toString.call(str) === '[object String]')) {
return '';
}
if(!(Object.prototype.toString.call(obj) === '[object Object]' && 'isPrototypeOf' in obj)) {
return str;
}
// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String/replace
return str.replace(/\{([^{}]+)\}/g, function(match, key) {
var value = obj[key];
return ( value !== undefined) ? ''+value :'';
});
}
},
//dom封装
dom: function(){
function Dom(){
this.elements=[];
EventTarget.call(this);
}
Dom.prototype = {
constructor: Dom,
_events: [],
get: function(selector, parent){
var element;
if(typeof arguments[0]=="string"){
element=arguments[0];
var prefix=element.slice(0, 1);
if(prefix == '#'){
element = document.getElementById(element.slice(1));
this.elements.push(element);
}else{
if(document.querySelectorAll){
this.elements.concat(document.querySelectorAll(element, parent.elements));
} else {
var es = document.body.getElementsByTagName('*');
for (var i = 0, j = es.length; i < j; i++) {
if (element.indexOf(es[i].className) != -1) {
this.elements.push(es[i]);
}
}
}
}
}else{
element=this;
this.elements.push(element);
}
return this;
},
each: function(fn){
for(var i=0,l=this.elements.length;i<l;i++){
fn.call(this, this.elements[i], i);
}
return this;
},
css: function(prop,v){
if(v){
this.each(function(el){
el.style[prop]=v;
});
}else{
return this.elements[0].style[prop];
}
},
width: function(v){
if(v){
this.elements[0].style.width = v;
return this;
}else{
return this.elements[0].offsetWidth;
}
},
height: function(v){
if(v){
this.elements[0].style.height = v;
return this;
}else{
return this.elements[0].offsetHeight;
}
},
html: function(ele){
this.elements[0].innerHTML = ele;
},
show: function(){
this.each(function(el){
el.style.display = 'block';
});
},
hide: function(){
this.each(function(el){
el.style.display = 'none';
});
},
ua: {
ie: navigator.userAgent.indexOf("IE") < 0 ? false : true,
firefox: navigator.userAgent.indexOf("Firefox") < 0 ? false : true,
chrome: navigator.userAgent.indexOf(&q