relation.js 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952
  1. function Relation(legcerNo,regNo,data){
  2. this.legcerNo = legcerNo;
  3. this.regNo = regNo;
  4. this.data = data;
  5. this.modleFlag = data.nodes.length>15;
  6. this.zoomlevel = 1;
  7. this.w = 0;
  8. this.h = 0;
  9. this.index = -1;
  10. this.redrawflag = false;
  11. this.infovisdiv = null;
  12. this.svg = null;
  13. this.force = null;
  14. this.lines = null;
  15. this.nodes = null;
  16. this.lineLables = null;
  17. this.mouseoverstatus = false;
  18. this.chargeVal = -1600;
  19. this.tickFlag = true;
  20. this.centerNodeX = 0;
  21. this.centerNodeY = 0;
  22. }
  23. Relation.prototype.init = function(){
  24. var thisClass = this;
  25. thisClass.w = $("#entrelation").width();
  26. thisClass.h = $("#entrelation").height();
  27. $("#entrelation-infovis").width(thisClass.w).append(
  28. '<div class="entrelation-controlls hidden-sm hidden-xs">'
  29. +'<div id="entrelation-pattern" class="entrelation-box" title_pos="left">一般模式</div>'
  30. +'<div id="entrelation-verbosemode" class="entrelation-box" title_pos="left">详细模式</div>'
  31. +'<div id="entrelation-fullscreen" class="entrelation-box" title_pos="left">全屏</div>'
  32. +'</div>'
  33. );
  34. //一般模式
  35. $("#entrelation-pattern").click(function(){
  36. thisClass.pattern();
  37. });
  38. //详细模式
  39. $("#entrelation-verbosemode").click(function(){
  40. thisClass.verbosemode();
  41. });
  42. //全屏
  43. $("#entrelation-fullscreen").click(function(){
  44. thisClass.initFullScreen();
  45. });
  46. if($(".entrelation-controlls").length>0){
  47. $(".entrelation-controlls").css({left:$("#entrelation").width()-$(".entrelation-controlls").width()});
  48. }
  49. //处理全屏
  50. $(document).on('webkitfullscreenchange mozfullscreenchange msfullscreenchange fullscreenchange', function(){
  51. if (!document.fullscreenElement && !document.mozFullScreenElement && !document.webkitFullscreenElement && !document.msFullscreenElement){
  52. //退出
  53. thisClass.cancelFullScreen();
  54. }
  55. });
  56. this.infovisdiv = document.getElementById("entrelation-infovis");
  57. document.onkeydown=function(event){
  58. var e = event || window.event || arguments.callee.caller.arguments[0];
  59. if(e && e.keyCode==122){
  60. event.preventDefault?event.preventDefault():window.event.returnValue = false;
  61. if(!!window.ActiveXObject || "ActiveXObject" in window){//ie下F11不能用,屏蔽掉
  62. if($(".exit").length == 0){
  63. return;
  64. }
  65. }
  66. thisClass.initFullScreen();
  67. }else if(e && e.keyCode==27){
  68. event.preventDefault?event.preventDefault():window.event.returnValue = false;
  69. thisClass.cancelFullScreen();
  70. }
  71. };
  72. $(window).resize(function(){
  73. if(!thisClass.redrawflag){
  74. //1秒后重绘
  75. thisClass.redrawflag=true;
  76. setTimeout(thisClass.redraw,1000);
  77. }
  78. firstresize=false;
  79. });
  80. if(document.getElementById("entrelation-infovis")){
  81. document.getElementById("entrelation-infovis").oncontextmenu=function(){return false;};
  82. }
  83. $("#entrelation-fullscreen").attr("title","进入全屏视图"+((!!window.ActiveXObject || "ActiveXObject" in window)?"":" (F11)"));
  84. ///////////////////////关系网实例////////////////////////////
  85. var htmls="<div style='position:absolute;top:0px;' class='legend'>";
  86. htmls= htmls+ "<div class='legend-text-bg' style='margin-top: 10px;'><div style='background-color: #ff9800;'></div><span style='margin-left: 20px;'>本企业</span></div>";
  87. htmls= htmls+ "<div class='legend-text-bg' style='margin-top: 10px;'><div style='background-color: #cddc39;opacity:0.5;'></div><span style='margin-left: 12px;'>其他企业</span></div>";
  88. htmls= htmls+ "<div class='legend-text-bg' style='margin-top: 10px;'><div style='background-color: #2196f3;'></div><span style='margin-left: 25px;'>个人</span></div>";
  89. htmls= htmls+ "<div class='legend-text-bg' style='margin-top: 10px;margin-bottom: 10px;'><div style='background-color: #cecece;'></div><span style='margin-left: 5px;'>注吊销企业</span></div>";
  90. htmls= htmls+ "<div><span style='font-size: 20px;font-weight: bold;color: #cecece;'>→</span><span style=''>投资关系(股东→企业)</span></div>";
  91. htmls= htmls+ "<div><span style='font-size: 20px;font-weight: bold;color: #cd93d7;'>→</span><span style=''>法定代表人</span></div>";
  92. //htmls= htmls+ "<div style='margin:10px 0px;' class='hidden-sm hidden-xs'><span class='text-muted'>提示:点击鼠标右键可以删除不想看的节点。</span></div>";
  93. htmls= htmls+"</div>"
  94. $("#entrelation").append(htmls);
  95. try{
  96. this.dataProcess();
  97. this.makeRelation();
  98. }catch(e){}
  99. }
  100. Relation.prototype.pattern = function(){
  101. if(this.modleFlag){
  102. return;
  103. }
  104. d3.selectAll("text").each(function (p){
  105. if(p.type == "ce" || p.type == "e"){
  106. $(this).text(p.shortText);
  107. }
  108. });
  109. this.modleFlag = true;
  110. this.makeTextBg();
  111. this.makeTitle();
  112. }
  113. Relation.prototype.verbosemode = function(){
  114. if(!this.modleFlag){
  115. return;
  116. }
  117. d3.selectAll("text").each(function (p){
  118. if(p.type == "ce" || p.type == "e"){
  119. $(this).text(p.text);
  120. }
  121. });
  122. this.modleFlag = false;
  123. this.makeTextBg();
  124. this.makeTitle();
  125. }
  126. Relation.prototype.dataProcess = function(){
  127. var reg = new RegExp(/(有限公司|有限责任公司|股份有限公司|总公司|分公司|公司|事务所|合伙企业)$|\(.*\)|\(.*\)/g);
  128. /*var provinces = [];
  129. $.ajax({
  130. url: "/js/provinceData.min.json",
  131. dataType: "json",
  132. cache: true,
  133. async: false,
  134. success: function(json){
  135. provinces = json;
  136. }
  137. });*/
  138. for(var i=0;i<this.data.nodes.length;i++){
  139. var nodeObj = this.data.nodes[i];
  140. nodeObj.text = $.trim(nodeObj.text);
  141. nodeObj.shortText = nodeObj.text;
  142. if(nodeObj.type == "e" || nodeObj.type == "ce"){
  143. var text = nodeObj.shortText;
  144. if(text.length > 2){//先替换结尾
  145. text = text.replace(reg,"");
  146. }
  147. if(text.length > 2){//再替换开头
  148. //text = this.filterEntName(text);
  149. }
  150. if(text.length > 2){//小于两个字符不生效
  151. nodeObj.shortText = text;
  152. }
  153. if(nodeObj.name == this.regNo){//先找本企业位置
  154. this.index = i;
  155. nodeObj["regcap"] = (typeof(d1) == "undefined")?0:d1;
  156. nodeObj["legcerno"] = this.legcerNo;
  157. }
  158. }
  159. }
  160. /*********************************连线处理***********************************/
  161. var minLink=-1,maxLink=-1;
  162. for(var i=0;i<this.data.links.length;i++){
  163. var linkObj = this.data.links[i];
  164. if(linkObj.target==this.index && this.data.nodes[linkObj.source].name==this.legcerNo){
  165. //this.data.nodes[linkObj.source].type="cp";
  166. linkObj.type = "cp"
  167. linkObj.isLegal = 1;
  168. }
  169. //
  170. this.data.nodes[linkObj.target]["istarget"] = 1;
  171. if(this.data.nodes[linkObj.source].name == this.data.nodes[linkObj.target].invlegcerno || this.data.nodes[linkObj.source].name == this.data.nodes[linkObj.target].legcerno){
  172. linkObj.isLegal = 1;
  173. }
  174. if(typeof(linkObj.invacconam) == "undefined"){
  175. continue;
  176. }
  177. var invacconam = new Number(linkObj.invacconam);
  178. if(minLink == -1 && maxLink == -1){
  179. minLink = invacconam;
  180. maxLink = invacconam;
  181. }else if(invacconam > maxLink){
  182. maxLink = invacconam;
  183. }else if(invacconam < minLink){
  184. minLink = invacconam;
  185. }
  186. }
  187. /////////////
  188. var linkSectionArray = this.getLineSectionArray(minLink,maxLink);
  189. for(var i=0;i<this.data.links.length;i++){
  190. var linksObj = this.data.links[i];
  191. linksObj["linkVal"] = 2;
  192. if(typeof(linkObj.invacconam) == "undefined"){
  193. continue;
  194. }
  195. var invacconam = new Number(linksObj.invacconam);
  196. for(var s in linkSectionArray){
  197. var sectionObj = linkSectionArray[s];
  198. if(invacconam >= sectionObj.minVal && invacconam < sectionObj.maxVal){
  199. linksObj["linkVal"] = sectionObj.linkVal;
  200. continue;
  201. }
  202. }
  203. }
  204. /*********************************节点处理***********************************/
  205. var minNode=-1,maxNode=-1;
  206. for(var i=0;i<this.data.nodes.length;i++){
  207. var nodeObj = this.data.nodes[i];
  208. if(nodeObj.type == "e" || nodeObj.type == "ce"){
  209. var regcap = nodeObj.regcap;
  210. if(minNode == -1 && maxNode == -1){
  211. minNode = regcap;
  212. maxNode = regcap;
  213. }else if(regcap > maxNode){
  214. maxNode = regcap;
  215. }else if(regcap < minNode){
  216. minNode = regcap;
  217. }
  218. }
  219. }
  220. var nodeSectionArray = this.getNodeSectionArray(minNode,maxNode);
  221. for(var i=0;i<this.data.nodes.length;i++){
  222. var nodeObj = this.data.nodes[i];
  223. nodeObj["nodeVal"] = 7;
  224. if(nodeObj.type == "e" || nodeObj.type == "ce"){
  225. var invacconam = new Number(nodeObj.invacconam);
  226. var regcap = new Number(nodeObj.regcap);
  227. for(var s in nodeSectionArray){
  228. var sectionObj = nodeSectionArray[s];
  229. if(regcap >= sectionObj.minVal && regcap < sectionObj.maxVal){
  230. nodeObj["nodeVal"] = sectionObj.nodeVal;
  231. continue;
  232. }
  233. }
  234. }
  235. }
  236. //计算点之间的距离
  237. var chargeArray = [[0,10],[10,20],[20,30],[30,40],[40,50],[50,60],[60,70],[70,80],[80,90],[90,100],[100,110]];
  238. var nodeCount = this.data.nodes.length;
  239. for(var i in chargeArray){
  240. if(nodeCount >= chargeArray[i][0] && nodeCount < chargeArray[i][1]){
  241. this.chargeVal += i*100;
  242. break;
  243. }else if(i == chargeArray.length){
  244. this.chargeVal += i*100;
  245. }
  246. }
  247. }
  248. Relation.prototype.filterEntName = function(text){
  249. this.allProvinces = "河南省、青海省、山西省、黑龙江省、安徽省、广西壮族自治区、西藏自治区";
  250. this.commonReplace = function(t){
  251. if(t.length > 1 && text.startWith(t)){
  252. var textCopy = text.replace(new RegExp("^"+t),"");
  253. if(textCopy.length > 2){
  254. text = textCopy;
  255. }
  256. return true;
  257. }
  258. return false;
  259. };
  260. this.replaceStart = function(t,f){
  261. var flag = false;
  262. var minus = null;
  263. if(this.commonReplace(t)){//替换省、市、县、区
  264. return true;
  265. }
  266. if(f){//不替换
  267. flag = false;
  268. }else if(t.endWith("维吾尔自治区")){
  269. flag = true;
  270. minus = 6;
  271. }else if(t.endWith("回族自治区") || t.endWith("壮族自治区") || t.endWith("特别行政区")){
  272. flag = true;
  273. minus = 5;
  274. }else if(t.endWith("自治州") || t.endWith("自治县") || t.endWith("自治区")){
  275. flag = true;
  276. minus = 3;
  277. }else if(t.endWith("地区")){
  278. flag = true;
  279. minus = 2;
  280. }else if(t.endWith("省") || t.endWith("市") || t.endWith("区")){
  281. flag = true;
  282. minus = 1;
  283. }
  284. if(flag){
  285. return this.commonReplace(t.substring(0,t.length-minus));
  286. }
  287. return false;
  288. };
  289. this.replaceCity = function(citys){
  290. if(citys){
  291. for(var c in citys){//市
  292. var c_name = citys[c].n;
  293. if(this.replaceStart(c_name)){
  294. this.replaceAreas(citys[c].s);
  295. return true;
  296. }else if(this.replaceAreas(citys[c].s)){
  297. return true;
  298. }
  299. }
  300. }
  301. };
  302. this.replaceAreas = function(areas){
  303. if(areas){
  304. for(var a in areas){//县、区
  305. var a_name = areas[a].n;
  306. if(this.replaceStart(a_name,true)){
  307. return true;
  308. }
  309. }
  310. }
  311. };
  312. for(var p in provinces){//省
  313. var p_name = provinces[p].n;
  314. if(this.allProvinces.indexOf(p_name) == -1){
  315. continue;
  316. }
  317. if(this.replaceStart(p_name)){
  318. this.replaceCity(provinces[p].s);
  319. break;
  320. }else if(this.replaceCity(provinces[p].s)){
  321. break;
  322. }
  323. }
  324. return text;
  325. }
  326. Relation.prototype.getLineSectionArray = function(minLink,maxLink){
  327. var countSection = 6;
  328. var section = (maxLink - minLink) / countSection;
  329. var sectionArr = [];
  330. for(var i=2;i<=countSection;i++){
  331. var minVal = minLink;
  332. if(sectionArr.length > 0){
  333. minVal = sectionArr[sectionArr.length - 1].maxVal;
  334. }
  335. var maxVal = minLink+section*i;
  336. if(i == countSection){
  337. maxVal += section;
  338. }
  339. var sectionObj = {linkVal:i,minVal:minVal,maxVal:maxVal};
  340. sectionArr.push(sectionObj);
  341. }
  342. return sectionArr;
  343. }
  344. Relation.prototype.getNodeSectionArray = function(minNode,maxNode){
  345. var countSection = 7;
  346. var section = (maxNode - minNode) / countSection;
  347. var sectionArr = [];
  348. for(var i=1;i<=countSection;i++){
  349. var minVal = minNode;
  350. if(sectionArr.length > 0){
  351. minVal = sectionArr[sectionArr.length - 1].maxVal;
  352. }
  353. var maxVal = minNode+section*i;
  354. if(i == countSection){
  355. maxVal += section;
  356. }
  357. var sectionObj = {nodeVal:6+i,minVal:minVal,maxVal:maxVal};
  358. sectionArr.push(sectionObj);
  359. }
  360. return sectionArr;
  361. }
  362. Relation.prototype.launchFullScreen = function(element) {
  363. if(element){
  364. if (element.requestFullscreen) {
  365. element.requestFullscreen();
  366. } else if (element.msRequestFullscreen) {
  367. element.msRequestFullscreen();
  368. } else if (element.mozRequestFullScreen) {
  369. element.mozRequestFullScreen();
  370. } else if (element.webkitRequestFullscreen) {
  371. // 对 Chrome 特殊处理,
  372. // 参数 Element.ALLOW_KEYBOARD_INPUT 使全屏状态中可以键盘输入。
  373. if ( window.navigator.userAgent.toUpperCase().indexOf( 'CHROME' ) >= 0 ) {
  374. element.webkitRequestFullScreen( Element.ALLOW_KEYBOARD_INPUT );
  375. }else {
  376. // Safari 浏览器中,如果方法内有参数,则 Fullscreen 功能不可用。
  377. element.webkitRequestFullScreen();
  378. }
  379. }
  380. }
  381. }
  382. Relation.prototype.cancelFullScreen = function(){
  383. this.h = $("#entrelation-infovis").height();
  384. $("#entrelation-fullscreen").attr("title","进入全屏视图"+((!!window.ActiveXObject || "ActiveXObject" in window)?"":" (F11)"));
  385. //force.linkDistance(120).charge(-200).size([w,h]).resume();
  386. $("#entrelation-infovis").css({width:this.w,height:this.h});
  387. //设置svg标签的宽度与高度
  388. d3.select("svg").attr("width", this.w).attr("height", this.h);
  389. $(".entrelation-controlls").css({left:$("#entrelation").width()-$(".entrelation-controlls").width()-30});
  390. if(document.exitFullscreen) {
  391. document.exitFullscreen();
  392. } else if (document.msExitFullscreen) {
  393. document.msExitFullscreen();
  394. } else if (document.mozCancelFullScreen) {
  395. document.mozCancelFullScreen();
  396. } else if (document.webkitExitFullscreen) {
  397. document.webkitExitFullscreen();
  398. }
  399. }
  400. Relation.prototype.initFullScreen = function(){
  401. var thisClass = this;
  402. var fullscreenElement =
  403. document.fullscreenElement ||
  404. document.mozFullScreenElement ||
  405. document.webkitFullscreenElement ||
  406. document.msFullscreenElement;
  407. if(!fullscreenElement || fullscreenElement==null){
  408. this.redrawflag = true;
  409. $("#entrelation-fullscreen").attr("title","退出全屏视图 (F11)");
  410. this.launchFullScreen(this.infovisdiv);
  411. var timeout = 100;
  412. if(!!window.ActiveXObject || "ActiveXObject" in window){
  413. timeout = 200;
  414. }
  415. setTimeout(function(){
  416. if(thisClass.force != null){
  417. //重绘
  418. var w=document.body.clientWidth;
  419. var h=document.body.clientHeight;
  420. //if(w>1200){
  421. //w= 1200
  422. //}
  423. $("#entrelation-infovis").css({width:w,height:h});
  424. d3.select("svg").attr("width", w).attr("height", h);
  425. $(".entrelation-controlls").css({left:w-$(".entrelation-controlls").width() - 70});
  426. thisClass.force.linkDistance(h).charge(-700).size([w,h]).resume();
  427. }
  428. },timeout);
  429. }else{
  430. this.cancelFullScreen();
  431. }
  432. }
  433. //重绘
  434. Relation.prototype.redraw = function(){
  435. if(this.force != undefined){
  436. d3.select("svg").attr("width",this.w).attr("height", this.h);
  437. this.force.size([this.w,this.h]).resume();
  438. $("#entrelation-infovis").css({width:this.w,height:this.h});
  439. //
  440. this.redrawflag = false;
  441. }
  442. }
  443. Relation.prototype.removeNode = function(obj){
  444. if(d3.event.which != 3){
  445. return;
  446. }
  447. this.highlightObject(obj,false);
  448. d3.select(obj).remove();
  449. var name = obj.__data__.name;
  450. var removeAloneNode = function(removeNodeName){
  451. var isRemoveAloneNode = true;
  452. d3.selectAll("path").each(function (i){
  453. if(removeNodeName == this.__data__.source.name || removeNodeName == this.__data__.target.name){
  454. isRemoveAloneNode = false;
  455. return true;
  456. }
  457. });
  458. if(isRemoveAloneNode){
  459. d3.selectAll("rect").each(function (){
  460. if(this.__data__.name == removeNodeName){
  461. d3.select(this).remove();
  462. return true;
  463. }
  464. });
  465. d3.selectAll("text").each(function (){
  466. if(this.__data__.name == removeNodeName){
  467. d3.select(this).remove();
  468. return true;
  469. }
  470. });
  471. }
  472. }
  473. d3.selectAll("path").each(function (){
  474. if(name == this.__data__.target.name){
  475. var fromNodeName = this.__data__.source.name;
  476. d3.select(this).remove();
  477. removeAloneNode(fromNodeName);
  478. }else if(name == this.__data__.source.name){
  479. var toNodeName = this.__data__.target.name;
  480. d3.select(this).remove();
  481. removeAloneNode(toNodeName);
  482. }
  483. });
  484. d3.selectAll("rect").each(function (){
  485. if(name == this.__data__.name){
  486. d3.select(this).remove();
  487. }
  488. });
  489. d3.selectAll("text").each(function (){
  490. if(name == this.__data__.name){
  491. d3.select(this).remove();
  492. }
  493. });
  494. }
  495. Relation.prototype.tick = function(){
  496. var thisClass = this;
  497. this.lines.attr("d", function(d){
  498. var sx = d.source.x,
  499. sy = d.source.y,
  500. x = d.target.x,
  501. y = d.target.y;
  502. if(sy > y){
  503. sy -= 12;
  504. }else{
  505. sy += 5;
  506. }
  507. var line = new geo.LineSegment(sx, sy, x, y);
  508. for (var e in d.target.edge) {
  509. var ix = line.intersect(d.target.edge[e].offset(x, y));
  510. if (ix.in1 && ix.in2) {
  511. x = ix.x;
  512. y = ix.y;
  513. break;
  514. }
  515. }
  516. var dx = x - sx,
  517. dy = y - sy,
  518. dr = Math.sqrt(dx * dx + dy * dy),
  519. theta = Math.atan2(dy, dx) + Math.PI / 7.85,
  520. d90 = Math.PI / 2,
  521. dtxs = x - Math.cos(theta),
  522. dtys = y - Math.sin(theta);
  523. //return "M" + sx + "," + sy + "A" + dr + " " + dr + ",0 1 1," + x + "," + y;
  524. return "M" + sx + "," + sy + "A" + dr + " " + dr + ",0 0 1," + x + "," + y + "A" + dr + " " + dr + ",0 0 0," + sx + "," + sy + "M" + dtxs + "," + dtys + "l" + (3.5 * Math.cos(d90 - theta) - 10 * Math.cos(theta)) + "," + (-3.5 * Math.sin(d90 - theta) - 10 * Math.sin(theta)) + "L" + (dtxs - 3.5 * Math.cos(d90 - theta) - 10 * Math.cos(theta)) + "," + (dtys + 3.5 * Math.sin(d90 - theta) - 10 * Math.sin(theta)) + "z";
  525. });
  526. this.nodes.attr("transform", function(d) {
  527. if(thisClass.tickFlag && d.type == "ce"){
  528. d.x = thisClass.centerNodeX;
  529. d.y = thisClass.centerNodeY;
  530. }
  531. return "translate(" + d.x + "," + d.y + ")scale(" + thisClass.zoomlevel+ ")";
  532. });
  533. /*this.lineLables.attr("transform",function(d){
  534. var sx = d.source.x,
  535. sy = d.source.y,
  536. x = d.target.x,
  537. y = d.target.y;
  538. if(sy > y){
  539. sy -= 12;
  540. }else{
  541. sy += 5;
  542. }
  543. var line = new geo.LineSegment(sx, sy, x, y);
  544. for (var e in d.target.edge) {
  545. var ix = line.intersect(d.target.edge[e].offset(x, y));
  546. if (ix.in1 && ix.in2) {
  547. x = ix.x;
  548. y = ix.y;
  549. break;
  550. }
  551. }
  552. var dx = x - sx,
  553. dy = y - sy,
  554. dr = Math.sqrt(dx * dx + dy * dy);
  555. var cx = (sx + x) / 2,
  556. cy = (sy + y) / 2,
  557. cr = dr - Math.sqrt(Math.pow(dr,2) - Math.pow(dr / 2,2));
  558. //var c = convert(sx,sy,x,y,0,0,dr,dr,0);
  559. return "translate("+(cx-cr)+","+(cy-cr)+")";
  560. });*/
  561. if(thisClass.tickFlag){
  562. thisClass.force.tick();
  563. }
  564. }
  565. Relation.prototype.zoomed = function() {
  566. this.svg.attr("transform",
  567. "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
  568. }
  569. Relation.prototype.highlightObject = function(obj,flag){
  570. if(this.mouseoverstatus){
  571. return;
  572. }
  573. if(!flag){
  574. d3.selectAll(".node").each(function (){
  575. d3.select(this).style("opacity","1");
  576. });
  577. d3.selectAll("path").each(function (){
  578. d3.select(this).style("opacity","1");
  579. });
  580. return;
  581. }
  582. var name = obj.__data__.name;
  583. d3.selectAll(".node").each(function (){
  584. if(name != this.__data__.name){
  585. d3.select(this).style("opacity","0.2");
  586. }
  587. });
  588. d3.selectAll("path").each(function (){
  589. var targetName = this.__data__.target.name;
  590. var sourceName = this.__data__.source.name;
  591. if(name != targetName && name != sourceName){
  592. d3.select(this).style("opacity","0.2");
  593. }else{
  594. d3.selectAll(".node").each(function (){
  595. if(targetName == this.__data__.name || sourceName == this.__data__.name){
  596. d3.select(this).style("opacity","1");
  597. }
  598. });
  599. }
  600. });
  601. }
  602. Relation.prototype.makeRelation = function(){
  603. var thisClass = this;
  604. this.force = d3.layout.force()
  605. .nodes(this.data.nodes)
  606. .links(this.data.links)
  607. .size([this.w, this.h])
  608. .linkDistance(function(p){
  609. return Math.floor(Math.random()*60)+90;
  610. })
  611. .chargeDistance(600)
  612. .charge(this.chargeVal)
  613. .linkStrength(1)
  614. .on('tick',function(){
  615. thisClass.tick();
  616. });
  617. var dragstatus = false;
  618. var drag = this.force.drag()
  619. .on("dragstart",function(d,i){
  620. thisClass.tickFlag = false;
  621. d.fixed = true; //拖拽开始后设定被拖拽对象为固定
  622. d3.event.sourceEvent.stopPropagation(); // Prevent panning
  623. })
  624. .on("drag",function(d,i){
  625. dragstatus = true;
  626. thisClass.mouseoverstatus = true;
  627. })
  628. .on("dragend",function(d,i){
  629. thisClass.mouseoverstatus = false;
  630. setTimeout(function(){
  631. dragstatus = false;
  632. },500)
  633. });
  634. //处理缩放
  635. var zoom = d3.behavior.zoom().scaleExtent([0.4, 10]).on("zoom", function(){
  636. thisClass.zoomed();
  637. });
  638. this.svg = d3.select("#entrelation-infovis").append("svg:svg")
  639. .attr("width", this.w)
  640. .attr("height", this.h)
  641. .call(zoom)
  642. .append("g");
  643. var gs = this.svg.append("svg:g")
  644. .selectAll("path")
  645. .data(this.force.links())
  646. .enter();
  647. this.lines = gs.append("path")
  648. .style("fill", function(p){
  649. return (p.type=="cp" || p.isLegal)?"#cd93d7":"#cecece";
  650. })
  651. .style("stroke", function(p){
  652. return (p.type=="cp" || p.isLegal)?"#cd93d7":"#cecece";
  653. })
  654. .attr("stroke-width",function (e,i){
  655. return e.linkVal;
  656. });
  657. /*this.lineLables = gs.append("g").each(function(d){
  658. var invacconam = new Number(d.invacconam);
  659. if(invacconam > 0){
  660. var lenInvacconam = (invacconam + "").length;
  661. if(lenInvacconam > 4 && (invacconam + "").indexOf(".") > -1 && (lenInvacconam - (invacconam + "").indexOf(".")) > 4){
  662. invacconam = (new Number(invacconam)).toFixed(4);
  663. }
  664. d3.select(this).append("text").text(invacconam+"万元");
  665. }else{
  666. d3.select(this).remove();
  667. }
  668. });*/
  669. this.lines.each(function (d,i){
  670. var invacconam = new Number(d.invacconam);
  671. if(invacconam > 0){
  672. var lenInvacconam = (invacconam + "").length;
  673. if(lenInvacconam > 4 && (invacconam + "").indexOf(".") > -1 && (lenInvacconam - (invacconam + "").indexOf(".")) > 4){
  674. invacconam = (new Number(invacconam)).toFixed(4);
  675. }
  676. d3.select(this).append("title").text("投资金额:"+invacconam+"万元");
  677. }
  678. });
  679. this.nodes = this.svg.append("svg:g")
  680. .selectAll(".node")
  681. .data(this.force.nodes())
  682. .enter()
  683. .append("g")
  684. .call(this.force.drag)
  685. .attr('class', 'node')
  686. .on('mouseover', function(d) {
  687. thisClass.highlightObject(this,true);
  688. })
  689. .on('mouseout', function(d) {
  690. thisClass.highlightObject(this,false);
  691. })
  692. .on("mousedown",function (e,i){
  693. d3.event.preventDefault();
  694. thisClass.removeNode(this);
  695. });
  696. this.nodes.append("rect")
  697. .attr("rx", 5)
  698. .attr("ry", 5)
  699. .attr('height', function(p){
  700. if(p.type == "ce"){
  701. return 25;
  702. }else{
  703. return 20;
  704. }
  705. })
  706. .attr("fill", function(p){
  707. if(p.type == "e" && (p.opstate == "11" || p.opstate == "07")){
  708. return "#cecece";
  709. }
  710. return p.type=="p"?"#2196f3":p.type=="ce"?"#ff9800":"#cddc39";
  711. })
  712. .attr("stroke", function(p){
  713. if(p.type == "e" && (p.opstate == "11" || p.opstate == "07")){
  714. return "#cecece";
  715. }
  716. return p.type=="p"?"#2196f3":p.type=="ce"?"#ff9800":"#cddc39";
  717. }).style("opacity",function(p){
  718. if(p.type=="e" && (p.opstate != "11" || p.opstate != "07")){
  719. return "0.5";
  720. }
  721. return "1";
  722. });
  723. this.makeTitle();
  724. this.nodes.append('text')
  725. .text(function(d){
  726. if(this.modleFlag){
  727. return d.shortText;
  728. }else{
  729. return d.text;
  730. }
  731. })
  732. .style("cursor",function (d,i){
  733. if(d.type == "e"){
  734. return "pointer";
  735. }else{
  736. return "auto";
  737. }
  738. })
  739. .style("font-size",function (d,i){
  740. if(d.type == "ce"){
  741. return "16px";
  742. }else{
  743. return "14px";
  744. }
  745. })
  746. .on("click",function (d,i){
  747. if(!dragstatus && d.type == "e"){
  748. window.open("/enterpriseInfoByRegNO/"+d.name+".html");
  749. }
  750. });
  751. thisClass.makeTextBg();
  752. thisClass.force.start();
  753. //var diagonal = d3.svg.diagonal().projection(function(d) { return [d.y, d.x]; });
  754. }
  755. Relation.prototype.makeTitle = function(){
  756. var thisClass = this;
  757. this.nodes.each(function (d,i){
  758. if(d.type == "ce" || d.type == "e"){
  759. var title = "";
  760. if(thisClass.modleFlag){
  761. title = d.text;
  762. }
  763. var regcap = d.regcap;
  764. if(regcap > 0){
  765. var lenRegcap = (regcap + "").length;
  766. if(lenRegcap > 4 && (regcap + "").indexOf(".") > -1 && (lenRegcap - (regcap + "").indexOf(".")) > 4){
  767. regcap = (new Number(regcap)).toFixed(4);
  768. }
  769. if(title != ""){
  770. title += "\n";
  771. }
  772. title += "注册资本:"+regcap+"万元";
  773. }
  774. if(title != ""){
  775. if($(this).children("title").length == 0){
  776. d3.select(this).append("title").text(title);
  777. }else{
  778. $(this).children("title").text(title);
  779. }
  780. }
  781. }
  782. });
  783. }
  784. Relation.prototype.makeTextBg = function(){
  785. var thisClass = this;
  786. this.nodes.each(function(d) {
  787. var node = d3.select(this),
  788. text = node.selectAll('text'),
  789. bounds = {},
  790. first = true;
  791. text.each(function() {
  792. var box = this.getBBox();
  793. box.x = 0;
  794. if (first || box.x < bounds.x1) {
  795. bounds.x1 = box.x;
  796. }
  797. if (first || box.y < bounds.y1) {
  798. bounds.y1 = box.y;
  799. }
  800. if (first || box.x + box.width > bounds.x2) {
  801. bounds.x2 = box.x + box.width;
  802. }
  803. if (first || box.y + box.height > bounds.y2) {
  804. bounds.y2 = box.y + box.height;
  805. }
  806. first = false;
  807. }).attr('text-anchor', 'middle');
  808. var padding = {"left":3,"right":3,"top":2,"bottom":2},
  809. margin = {"left":3,"right":3,"top":2,"bottom":2},
  810. oldWidth = bounds.x2 - bounds.x1;
  811. bounds.x1 -= oldWidth / 2;
  812. bounds.x2 -= oldWidth / 2;
  813. bounds.x1 -= padding.left;
  814. bounds.y1 -= padding.top;
  815. bounds.x2 += padding.left + padding.right;
  816. bounds.y2 += padding.top + padding.bottom;
  817. var width = bounds.x2 - bounds.x1;
  818. if(d.type == "ce"){
  819. thisClass.centerNodeX = thisClass.w / 2;
  820. thisClass.centerNodeY = thisClass.h / 2 + 5;
  821. }
  822. var height = bounds.y2 - bounds.y1;
  823. node.select('rect')
  824. .attr('x', bounds.x1)
  825. .attr('y', bounds.y1)
  826. //.attr('height', height)
  827. .attr('width', width);
  828. d.edge = {
  829. left : new geo.LineSegment(bounds.x1, bounds.y1, bounds.x1, bounds.y2),
  830. right : new geo.LineSegment(bounds.x2, bounds.y1, bounds.x2, bounds.y2),
  831. top : new geo.LineSegment(bounds.x1, bounds.y1, bounds.x2, bounds.y1),
  832. bottom : new geo.LineSegment(bounds.x1, bounds.y2, bounds.x2, bounds.y2)
  833. };
  834. });
  835. }
  836. // svg : [A | a] (rx ry x-axis-rotation large-arc-flag sweep-flag x y)+
  837. /* x1 y1 x2 y2 fA fS rx ry φ */
  838. function radian( ux, uy, vx, vy ) {
  839. var dot = ux * vx + uy * vy;
  840. var mod = Math.sqrt( ( ux * ux + uy * uy ) * ( vx * vx + vy * vy ) );
  841. var rad = Math.acos( dot / mod );
  842. if( ux * vy - uy * vx < 0.0 ) rad = -rad;
  843. return rad;
  844. }
  845. //https://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes
  846. //conversion_from_endpoint_to_center_parameterization
  847. //sample : convert(200,200,300,200,1,1,50,50,0,{})
  848. function convert(x1, y1, x2, y2, fA, fS, rx, ry, phi) {
  849. var cx,cy,theta1,delta_theta;
  850. if( rx == 0.0 || ry == 0.0 ) return -1; // invalid arguments
  851. var s_phi = Math.sin( phi );
  852. var c_phi = Math.cos( phi );
  853. var hd_x = ( x1 - x2 ) / 2.0; // half diff of x
  854. var hd_y = ( y1 - y2 ) / 2.0; // half diff of y
  855. var hs_x = ( x1 + x2 ) / 2.0; // half sum of x
  856. var hs_y = ( y1 + y2 ) / 2.0; // half sum of y
  857. // F6.5.1
  858. var x1_ = c_phi * hd_x + s_phi * hd_y;
  859. var y1_ = c_phi * hd_y - s_phi * hd_x;
  860. var rxry = rx * ry;
  861. var rxy1_ = rx * y1_;
  862. var ryx1_ = ry * x1_;
  863. var sum_of_sq = rxy1_ * rxy1_ + ryx1_ * ryx1_; // sum of square
  864. var coe = Math.sqrt( ( rxry * rxry - sum_of_sq ) / sum_of_sq );
  865. if( fA == fS ) coe = -coe;
  866. // F6.5.2
  867. var cx_ = coe * rxy1_ / ry;
  868. var cy_ = -coe * ryx1_ / rx;
  869. // F6.5.3
  870. cx = c_phi * cx_ - s_phi * cy_ + hs_x;
  871. cy = s_phi * cx_ + c_phi * cy_ + hs_y;
  872. var xcr1 = ( x1_ - cx_ ) / rx;
  873. var xcr2 = ( x1_ + cx_ ) / rx;
  874. var ycr1 = ( y1_ - cy_ ) / ry;
  875. var ycr2 = ( y1_ + cy_ ) / ry;
  876. // F6.5.5
  877. theta1 = radian( 1.0, 0.0, xcr1, ycr1 );
  878. // F6.5.6
  879. delta_theta = radian( xcr1, ycr1, -xcr2, -ycr2 );
  880. var PIx2 = Math.PI * 2.0;
  881. while( delta_theta > PIx2 ) delta_theta -= PIx2;
  882. while( delta_theta < 0.0 ) delta_theta += PIx2;
  883. if( fS == false ) delta_theta -= PIx2;
  884. var outputObj = { /* cx, cy, theta1, delta_theta */
  885. cx : cx,
  886. cy : cy,
  887. theta1 : theta1,
  888. delta_theta : delta_theta
  889. }
  890. console.dir(outputObj);
  891. return outputObj;
  892. }
  893. function convert_tmp(x1, y1, x2, y2, fA, fS, rx, ry, phi) {
  894. var cx,cy,theta1,delta_theta;
  895. if( rx == 0.0 || ry == 0.0 ) return -1; // invalid arguments
  896. var s_phi = Math.sin( phi );
  897. var c_phi = Math.cos( phi );
  898. var hd_x = ( x1 - x2 ) / 2.0; // half diff of x
  899. var hd_y = ( y1 - y2 ) / 2.0; // half diff of y
  900. var hs_x = ( x1 + x2 ) / 2.0; // half sum of x
  901. var hs_y = ( y1 + y2 ) / 2.0; // half sum of y
  902. // F6.5.1
  903. var x1_ = c_phi * hd_x + s_phi * hd_y;
  904. var y1_ = c_phi * hd_y - s_phi * hd_x;
  905. var rxry = rx * ry;
  906. var rxy1_ = rx * y1_;
  907. var ryx1_ = ry * x1_;
  908. var sum_of_sq = rxy1_ * rxy1_ + ryx1_ * ryx1_; // sum of square
  909. var coe = Math.sqrt( ( rxry * rxry - sum_of_sq ) / sum_of_sq );
  910. if( fA == fS ) coe = -coe;
  911. // F6.5.2
  912. var cx_ = coe * rxy1_ / ry;
  913. var cy_ = -coe * ryx1_ / rx;
  914. // F6.5.3
  915. cx = c_phi * cx_ - s_phi * cy_ + hs_x;
  916. cy = s_phi * cx_ + c_phi * cy_ + hs_y;
  917. var outputObj = { /* cx, cy */
  918. cx : rxry,
  919. cy : rxy1_
  920. }
  921. console.dir(outputObj);
  922. return outputObj;
  923. }