html框架代码
<divid="container"class="container"><canvasid="mycanvas"class="con_box mycanvas"></canvas><divid="mydiv"class="con_box mydiv"><divclass="roots roots_js"></div></div></div>js代码
<script type="text/javascript">$(function(){layui.use(["layer",],function(){layer=layui.layer;varecanvas=document.getElementById("mycanvas");varctx=ecanvas.getContext("2d");// 画线functionlines_canvas(){// objvarobj_=$(".tree_box:nth-child(2)").children();if(!obj_.length){returnfalse;//根节点下没有元素时避免报错}varobj_st=obj_.first();varobj_e=obj_.last();// leftvarleft_st=obj_st.position().left+(obj_st.outerWidth(true)/2);varleft_e=obj_e.position().left+(obj_e.outerWidth(true)/2);varleft_cen=$(".roots").position().left+($(".roots").outerWidth(true)/2);// topvartop_st=$(".roots").position().top+$(".roots").outerHeight(true);top_st+=window.innerWidth*0.02;//避免连接线从上面漏出vartop_e=$(".tree_box:nth-child(2)").position().top+(window.innerWidth*0.15);vartop_cen=top_st+((top_e-top_st)/2);// 从起始点出现的竖线ctx.beginPath();ctx.moveTo(left_cen,top_st);ctx.lineTo(left_cen,top_cen);ctx.stroke();// 覆盖所有子元素的横线ctx.beginPath();ctx.moveTo(left_st,top_cen);ctx.lineTo(left_e,top_cen);ctx.stroke();$.each(obj_,function(key,vo){// 从覆盖线到每一个子元素varleft_tmp=$(vo).position().left+($(vo).outerWidth(true)/2);ctx.beginPath();ctx.moveTo(left_tmp,top_cen);ctx.lineTo(left_tmp,top_e);ctx.stroke();});$.each($(".start"),function(key,vo){// console.log(vo);// objvarobj_p=$(vo).parent();varobj_np=obj_p.next();varobj_cnp=obj_np.children();varobj_st=obj_cnp.first();varobj_e=obj_cnp.last();// leftvars_x=$(vo).position().left+($(vo).outerWidth(true)/2);varfirst_x=obj_st.position().left+(obj_st.outerWidth(true)/2);varst_x=Math.min(s_x,first_x);varlast_x=obj_e.position().left+(obj_e.outerWidth(true)/2);vare_x=Math.max(s_x,last_x);// topvarst_y=obj_p.position().top+obj_p.outerHeight(true);st_y+=window.innerWidth*0.01;//避免连接线从上面漏出st_y+=-$(obj_p).height()+$(vo).outerHeight(true);//兼容高度不同的元素vare_y=$(obj_np).position().top+(window.innerWidth*0.15);varcen_y=st_y+((e_y-st_y)/2);// 从起始点出现的竖线ctx.beginPath();ctx.moveTo(s_x,st_y);ctx.lineTo(s_x,cen_y);ctx.stroke();// 覆盖所有子元素的横线ctx.beginPath();ctx.moveTo(st_x,cen_y);ctx.lineTo(e_x,cen_y);ctx.stroke();$.each(obj_cnp,function(key,vo){// 从覆盖线到每一个子元素varleft_tmp=$(vo).position().left+($(vo).outerWidth(true)/2);ctx.beginPath();ctx.moveTo(left_tmp,cen_y);ctx.lineTo(left_tmp,e_y);ctx.stroke();});});// ecanvas.toDataURL();}// canvasfunctioninit_canvas(){console.log("init_canvas");$("#mycanvas").attr("width",$("#mydiv").outerWidth(true));$("#mycanvas").attr("height",$("#mydiv").outerHeight(true));ctx.save();ctx.restore();ctx.strokeStyle="#a4aabb";//线颜色lines_canvas();}// 数据添加到页面functionshow_datas(infos,len){// console.log(infos);if(infos.depth==0){$(".roots_js").html(infos.names);$(".roots_js").attr("iid",infos.id);}else{varobj=$(".tree_box:nth-child("+(infos.depth+1)+")");if(!obj.length){$(".mydiv").append(`<div class="tree_box"></div>`);}varobj=$(".tree_box:nth-child("+(infos.depth+1)+")");varclas="";if(infos.children){clas+="start";}if(infos.last==1){clas+="lebg"+infos.linkeva;}// var ids = "node" + infos.id;varids=infos.id;if(!$("#"+ids).length){obj.append(`<div id="`+ids+`" class="tree_cons end`+clas+`" depth="`+infos.depth+`" onclick="get_tree(`+infos.id+`,this)">`+infos.names+`</div>`);}}if(infos.children){$.each(infos.children,function(key,vo){show_datas(vo);});}lens++;if(len==lens){init_canvas();}}// 获取数据并调整页面内容window.get_tree=function(iid,that){// console.log($(".roots").attr("iid"));// console.log(iid);// console.log(that);if(iid==$(".roots").attr("iid")){console.log("重复");returnfalse;}if(typeof(ctx)!="undefined"){ctx.save();ctx.restore();}if(typeof(that)!="undefined"){// console.log(1);varobj=$(that).parent();obj.nextAll().remove();$.each(obj.children(),function(key,vo){$(vo).removeClass("start");});}else{// console.log(2);$(".tree_box").remove();}$.post("/index/pro/gets_tree",{iid:iid,},function(params){// console.log(params);// console.log(params.nodes);// console.log(params.len);lens=0;if(params.nodes.children){$(that).addClass("start");}show_datas(params.nodes,params.len);},"json");}get_tree(`{$iid}`);// $(".block2_item").click(function () {// get_tree($(this).attr("iid"));// });});});</script>php代码
public$t_pri="ids";//主键public$t_ck="children";//子数据集keypublic$t_fields;//查询字段function_initialize(){parent::_initialize();$this->t_fields=["id","id"=>$this->t_pri,"names",// "names" => "name", //echarts// "names" => "id", //antv g6// "names" => "label", //antv g6"last","depth","nuop","linkeva",];}// 树图数据获取functiongets_tree(){$iid=intval(input("iid"));if(!$iid){$iid=Db::name("industrial")->where("iid","")->value("id");}$this->assign("iid",$iid);$t_arr=$this->datas_tree(0,$iid);$infos=[];if(!empty($t_arr[0])){$infos=&$t_arr[0];}if(isset($infos[$this->t_pri])){if($infos["depth"]==0){$infos["x"]=1000;}}$res=[];// $res["infos"] = $infos;$res["nodes"]=$infos;$res["len"]=count($this->to_onelv($t_arr));// $res["lists"] = $t_arr;// $res["nodes"] = $this->to_pos($infos);// $res["edges"] = $this->to_edges($infos);// $res["nodes"] = $this->to_onelv($t_arr);$res["code"]=0;return$res;}// 树图数据获取functiondatas_tree($iid=0,$id=0){$whe["iid"]=$iid;$whe["id"]=$id;$whe=array_filter($whe);$lists=Db::name("industrial")->field($this->t_fields)->where($whe)->select();if(!empty($lists[0][$this->t_pri])){$t_arr=$this->datas_tree($lists[0][$this->t_pri]);if(!empty($t_arr)){$lists[0][$this->t_ck]=$t_arr;}}return$lists;}// 树状结构数据展开functionto_onelv($lists){$len=0;foreach($listsas$key=>&$value){if(!empty($value["children"])){$len++;$lists=array_merge($lists,$value["children"]);unset($value["children"]);}}if($len){$lists=$this->to_onelv($lists);}return$lists;}代码效果