php+html+canvas实现树状打开的结构
html框架代码dividcontainerclasscontainercanvasidmycanvasclasscon_box mycanvas/canvasdividmydivclasscon_box mydivdivclassroots roots_js/div/div/divjs代码script typetext/javascript$(function(){layui.use([layer,],function(){layerlayui.layer;varecanvasdocument.getElementById(mycanvas);varctxecanvas.getContext(2d);// 画线functionlines_canvas(){// objvarobj_$(.tree_box:nth-child(2)).children();if(!obj_.length){returnfalse;//根节点下没有元素时避免报错}varobj_stobj_.first();varobj_eobj_.last();// leftvarleft_stobj_st.position().left(obj_st.outerWidth(true)/2);varleft_eobj_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_stwindow.innerWidth*0.02;//避免连接线从上面漏出vartop_e$(.tree_box:nth-child(2)).position().top(window.innerWidth*0.15);vartop_centop_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_npobj_p.next();varobj_cnpobj_np.children();varobj_stobj_cnp.first();varobj_eobj_cnp.last();// leftvars_x$(vo).position().left($(vo).outerWidth(true)/2);varfirst_xobj_st.position().left(obj_st.outerWidth(true)/2);varst_xMath.min(s_x,first_x);varlast_xobj_e.position().left(obj_e.outerWidth(true)/2);vare_xMath.max(s_x,last_x);// topvarst_yobj_p.position().topobj_p.outerHeight(true);st_ywindow.innerWidth*0.01;//避免连接线从上面漏出st_y-$(obj_p).height()$(vo).outerHeight(true);//兼容高度不同的元素vare_y$(obj_np).position().top(window.innerWidth*0.15);varcen_yst_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.depth0){$(.roots_js).html(infos.names);$(.roots_js).attr(iid,infos.id);}else{varobj$(.tree_box:nth-child((infos.depth1)));if(!obj.length){$(.mydiv).append(div classtree_box/div);}varobj$(.tree_box:nth-child((infos.depth1)));varclas;if(infos.children){classtart;}if(infos.last1){claslebginfos.linkeva;}// var ids node infos.id;varidsinfos.id;if(!$(#ids).length){obj.append(div idids classtree_cons endclas depthinfos.depth onclickget_tree(infos.id,this)infos.names/div);}}if(infos.children){$.each(infos.children,function(key,vo){show_datas(vo);});}lens;if(lenlens){init_canvas();}}// 获取数据并调整页面内容window.get_treefunction(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);lens0;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));// });});});/scriptphp代码public$t_priids;//主键public$t_ckchildren;//子数据集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 g6last,depth,nuop,linkeva,];}// 树图数据获取functiongets_tree(){$iidintval(input(iid));if(!$iid){$iidDb::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($iid0,$id0){$whe[iid]$iid;$whe[id]$id;$whearray_filter($whe);$listsDb::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){$len0;foreach($listsas$key$value){if(!empty($value[children])){$len;$listsarray_merge($lists,$value[children]);unset($value[children]);}}if($len){$lists$this-to_onelv($lists);}return$lists;}代码效果

相关新闻

API类型全解析:从REST、gRPC到微服务与API网关,一文搞懂接口家族

API类型全解析:从REST、gRPC到微服务与API网关,一文搞懂接口家族

如果你跟任何一位后端工程师聊过天,大概率会听到类似这样的话:“前端不关心你数据库长什么样,你只要把 API 定义好就行。”我第一次听到 API 这个词,是在一场前后端联调会上。当时我甚至不知道它是 Application Programming Inter…

2026/10/18 6:05:47 阅读更多 →
公园场地预约管理系统实战:冲突检测、设施维护与统计设计全解析

公园场地预约管理系统实战:冲突检测、设施维护与统计设计全解析

去年前段时间,我帮一个朋友所在的园区做模拟项目X,需求正好是"公园游玩场地预约管理 设施维护 游客统计"这一套组合。做之前我以为就是个普通的CRUD,后来才发现预约冲突、维护工单流转、统计口径这些东西,每一块都有坑…

2026/10/18 6:05:47 阅读更多 →
基于SpringBoot+Vue的足球赛事社区互动网站开发实战

基于SpringBoot+Vue的足球赛事社区互动网站开发实战

足球赛事社区这东西,我做了差不多两个版本才真正跑顺。第一版用传统的页面改模块,改一个页面动不动就要重启,后端和页面代码混在一起,越到后面越难受。后来彻底推倒,换成 SpringBoot Vue 的前后端分离方案&#xff0c…

2026/10/18 6:05:47 阅读更多 →

最新新闻

多智能体监控与治理:构建云上AI劳力工厂的实用指南

多智能体监控与治理:构建云上AI劳力工厂的实用指南

最近圈子里都在聊“云上劳力工厂”这个概念——把一群 AI 智能体部署到云端,像流水线工人一样自动执行任务,而管理者只需要在中控台盯着一块大屏,看它们谁在干活、谁卡住了、谁在摸鱼烧钱。某 AI 实验室放出的这套方向很有意思:它…

2026/10/18 6:56:58 阅读更多 →
相机标定外参“相对于谁”?一文讲透三种坐标系含义

相机标定外参“相对于谁”?一文讲透三种坐标系含义

做机器视觉的工程师,几乎都要过“相机标定”这一关。单目标定、双目标定、手眼标定,这些词在实际项目里反复出现,很多人也跟着网上的教程跑通了整个流程,但真正被问到“外参里的旋转R和平移t,到底相对于谁”的时候&…

2026/10/18 6:56:58 阅读更多 →
用Joern做Java代码审计:5分钟导入项目并扫描注入漏洞

用Joern做Java代码审计:5分钟导入项目并扫描注入漏洞

做Java安全的人,多多少少都被“漏洞扫描”这四个字折腾过。传统商业SAST不是不好,但贵、慢、误报率高,有时候一份扫描报告发下来,研发团队光是人肉筛告警就得筛一天;自己写正则扫代码,又只能抓到“字符串拼…

2026/10/18 6:56:58 阅读更多 →
SQL进阶必学:连接、视图、事务、约束与权限管理实战

SQL进阶必学:连接、视图、事务、约束与权限管理实战

其实在大二的数据库课上学到这里的时候,我并没有觉得"中级SQL"有什么特别的,无非是多记几个语法。直到后来真刀真枪写业务查询、维护线上数据,才意识到这一章其实是整个SQL能力体系里最实用的一段——单表查询是基础,但…

2026/10/18 6:56:58 阅读更多 →
数字后端log高效排查指南:综合到签核的完整阶段拆解与实战

数字后端log高效排查指南:综合到签核的完整阶段拆解与实战

带过我的师傅说过一句话,做数字后端的人,一半时间在跑流程,另一半时间在看log。当时我以为是夸张,等自己真正开始盯综合、布局布线、时钟树综合、时序收敛、物理验证这一整条线之后,才发现这句话几乎就是日常工作写照。…

2026/10/18 6:56:58 阅读更多 →
vim 回到上次编辑的位置:用 ctrl+O / ctrl+I 在 normal mode 里跳转编辑历史

vim 回到上次编辑的位置:用 ctrl+O / ctrl+I 在 normal mode 里跳转编辑历史

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 6:55:58 阅读更多 →

日新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 0:55:02 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 14:23:36 阅读更多 →