通过一段时间的使用和学习,对G6有了更一步的经验,这篇博文主要从以下几个小功能着手介绍,文章最后会给出完整的demo代码。

目录

1. 树图的基本布局和使用

树图的布局,使用的模板是官网所提供的 紧凑树模板,在此基础上,进行一些定制化的改造,官网紧凑树案例

属性说明:

  1. graph = new G6.TreeGraph({
  2. container,
  3. width: document.documentElement.clientWidth,
  4. height:document.documentElement.clientHeight,
  5. // .....
  6. layout: {
  7. type: 'compactBox', // 布局类型
  8. direction: 'LR', // 树图布局方向, 从左向右
  9. getHeight: function getHeight() { // 高度
  10. return 16
  11. },
  12. getWidth: function getWidth() { // 宽度
  13. return 16
  14. },
  15. getVGap: function getVGap() { // 节点之间 垂直间距
  16. return 25
  17. },
  18. getHGap: function getHGap() { // 节点之间 水平间距
  19. return 150
  20. }
  21. }
  22. })

2. 根据返回数据的属性不同,定制不一样的节点样式

大部分在实际项目中,数据都是由后端返回,可能会存在多种类型的数据,需要进行不同的处理和展示,那么此时只在 graph 初始化时,定义defaultNode显然是不够用的,G6支持动态改变节点样式。需要在 graph 实例化之后:

  1. // 以下函数均在下方有实现代码:
  2. graph.node((node)=> {
  3. return {
  4. label: node.label || formatLabel(node),
  5. icon: formatIcon(node),
  6. size: node.size || 40,
  7. labelCfg: { position: setLabelPos(node) }, // label 显示位置
  8. style: {
  9. fill: getNodeColor(),
  10. stroke: getNodeColor()
  11. }
  12. }
  13. })

3. 节点 label 文案显示过长时,通过截断的方式,显示...

首先判断当前节点有无子节点,后续会进行label的拼接,显示叶子节点的数量,在进行结束,此书由于数据的原因,案例中数据labelid使用同一个字段,后续同学们可以自己按实际情况进行调整:我截取的长度是 15

  1. // label 过长截断 显示...
  2. const formatLabel = (node) => {
  3. const hasChildren = node.childrenBak?.length || node.children?.length
  4. const ellipsis = node.id.length > 15 ? '...' : ''
  5. return `${node.id.slice(0, 15)}${ellipsis}${hasChildren ? ' (' + hasChildren + ')' : ''}`
  6. }

4. 当一个父节点包含children叶子节点时,label后显示children的长度,格式为:node.label(children.length)

这个小功能,与上一个label 截断,统一都是处理label的,因此放在同一个函数中返回,其主要实现代码为 这一行:

  1. return `${node.id.slice(0, 15)}${ellipsis}${hasChildren ? ' (' + hasChildren + ')' : ''}`

5. 截断后的label ,通过鼠标悬浮,完全显示在 tooltip 中,定义并改写 tooltip 样式

这个小功能设计的改动比较多,同学们在看的时候,不要看错了哈

第一步:首先定义一个函数,返回tooltip,官网的案例中并不是返回的函数,而是直接返回了一个对象,这个在实际使用过程中会存在问题,就是新增的数据无法使用到这个插件,因此通过函数调用的方式 ,可以解决该现象:

  1. // label 显示... 时,显示提示 tip
  2. const treeTooltip = ()=> {
  3. return new G6.Tooltip({
  4. offsetX: 10, // 鼠标偏移量
  5. offsetY: 20,
  6. shouldBegin(e: any) {
  7. return e.item?.get('model')?.label?.includes('...') // label中有...才显示,表示被截断
  8. },
  9. getContent(e: any) {
  10. let outDiv = document.createElement('div') // 设置tip容器和样式
  11. outDiv.innerHTML = `
  12. <p style="max-width:600px;word-wrap:break-word;border-radius:5px;font-size:15px;color:#fff;background:#333;padding:10px">
  13. ${e.item.getModel().id}
  14. </p>`
  15. return outDiv
  16. },
  17. itemTypes: ['node'] // 表示触发的元素类型
  18. })
  19. }

第二步:在new 实例化的options中添加 插件使用

  1. graph = new G6.TreeGraph({
  2. container,
  3. width: document.documentElement.clientWidth,
  4. height:document.documentElement.clientHeight,
  5. plugins: [treeTooltip()],
  6. // .....
  7. })

第三步:完整以上代码后,基本可以看出tip的提示框,但是由于是改写原有的样式,因此还需要 改一下 style, 由于画布操作较多,因此canvas画布,修改鼠标样式,全文只有这里提到了style修改。就写在一起了,实际并不影响 tooltip 功能

  1. <style scoped>
  2. #container >>> .g6-component-tooltip {
  3. background:#333;
  4. color:#fff;
  5. padding: 0 8px;
  6. }
  7. canvas {
  8. cursor: pointer !important;
  9. }
  10. </style>

6. 根据节点展开收起状态 动态变更 label 显示位置,展开时在上,收起时在右

此功能的设计是为了优化,当节点label过长并展开时,父子之间水平间距不够时会出现文案互相重叠等问题,做了一个小优化,

首先判断节点是否是展开状态,以及是否有叶子节点,节点有children并展开时在上,其余情况都显示在右边,这是初始化时的代码:

  1. // 根据节点展开收起状态 动态变更 label 显示位置,展开时在上,收起时在右
  2. const setLabelPos = (node) => {
  3. return !node.collapsed && node.children?.length ? 'top' : 'right'
  4. }

因为树图可以监听节点的展开收起状态,因此在切换的时候,也需要进行 label定位的问题:在new 实例化的options中添加 modes

  1. graph = new G6.TreeGraph({
  2. container,
  3. width: document.documentElement.clientWidth,
  4. height:document.documentElement.clientHeight,
  5. plugins: [treeTooltip()],
  6. // .....
  7. modes: {
  8. default: [
  9. {
  10. type: 'collapse-expand',
  11. onChange: function onChange(item: any, collapsed) {
  12. const data = item?.get('model')
  13. data.collapsed = collapsed
  14. const model = {
  15. id: data.id,
  16. labelCfg: { position: !collapsed ? 'top' : 'right' }
  17. }
  18. item.update(model)
  19. item.refresh()
  20. return true
  21. }
  22. },
  23. 'drag-canvas',
  24. 'zoom-canvas'
  25. ]
  26. }
  27. })

7. 设置节点的icon样式和背景色(随机色可自行定制)

废话不多话,处理节点的icon图表,图表可以使用图片,也可以使用文字,此处就用文字了,截取的label前两个字符串,并设置背景颜色(随机色可自行定制)

  1. // 叶子节点 图标处理 截取ID 前两个字符串
  2. const formatIcon = (node) => {
  3. node.icon = {
  4. text: node.id.slice(0,2),
  5. fill: '#fff',
  6. stroke: '#fff',
  7. textBaseline: 'middle',
  8. fontSize: 20,
  9. width: 25,
  10. height: 25,
  11. show: true
  12. }
  13. }
  14. // 叶子节点 背景颜色随机填充
  15. const getNodeColor = () => {
  16. const colors = ["#8470FF", "#A020F0", "#C0FF3E", "#FF4500", "#66d6d1"];
  17. return colors[Math.floor(Math.random() * colors.length)];
  18. }

8. 叶子节点超过 (xxx)条, 折叠叶子节点,显示展开更多

当叶子节点很多时,并不想全部展开,而是先只展示一部分,其他节点折叠在 展开按钮中,实现思路,定义一个属性,接受原有全部children, 然后进行截取,在push一个 展开按钮,实现:

第一步:定义一个childrenBak属性接受 children数据

  1. // 子还有子,因此需要递归
  2. const splitChild = (node) => {
  3. node.childrenBak = node.children ? [...node.children] : []
  4. let result: any = []
  5. if(node.children){
  6. result = node.children.slice(0, 5)
  7. if (node.children.length > 5) {
  8. result.push({ id: `Expand-${node.id}`, label: ' 展开更多...' })
  9. }
  10. node.children = result
  11. node.children.forEach(child =>{
  12. splitChild(child)
  13. })
  14. }
  15. }

9. 点击展开更多节点,渲染被折叠的叶子节点

第二步:(接功能小8继续)点击展开更多时,显示被折叠的剩余节点,,定义node:click事件

思路:找到展开更多 , 找到展开更多节点的 父节点, 更新父节点的 children

  1. graph.on('node:click', (evt) => {
  2. const { item } = evt
  3. const node = item?.get('model')
  4. if (node.id.includes('Expand')) { // id 中包含Expand 表示是展开更多
  5. const parentNode = graph.getNeighbors(item, 'source')[0].get('model') // 找到展开更多节点的 父节点
  6. graph.updateChildren(parentNode.childrenBak, parentNode.id) // 使用上一步声明的childrenBak 更新父节点的 children
  7. }
  8. })

10. 定义鼠标点击事件,聚焦当前点击节点至画布中心点

小9 说了点击事件,那么点击事件中,还有一个小的优化点,就是将当前点击的节点,移动至画布中心,并赋予高亮选中样式

  1. const animateCfg = { duration: 200, easing: 'easeCubic' }
  2. graph.on('node:click', (evt) => {
  3. const { item } = evt
  4. const node = item?.get('model')
  5. // if (node.id.includes('Expand')) { // 功能点 9 代码
  6. // const parentNode = graph.getNeighbors(item, 'source')[0].get('model')
  7. // console.log(parentNode,parentNode.childrenBak);
  8. // graph.updateChildren(parentNode.childrenBak, parentNode.id)
  9. // }
  10. setTimeout(() => {
  11. if (!node.id.includes('Expand')) {
  12. graph.focusItem(item, true, animateCfg)
  13. graph.getNodes().forEach((node) => {
  14. graph.clearItemStates(node) // 先清空其他节点的 高亮样式
  15. })
  16. graph.setItemState(item, 'selected', true) // selected 需要在实例化处进行定义
  17. }
  18. }, 500)
  19. })

selected 表示的是 nodeStateStyles,也就是节点状态样式

  1. graph = new G6.TreeGraph({
  2. container,
  3. width: document.documentElement.clientWidth,
  4. height:document.documentElement.clientHeight,
  5. plugins: [treeTooltip()],
  6. // .....
  7. nodeStateStyles: {
  8. active: { // 这个用在了 鼠标悬浮,可以自行定义
  9. fill: 'l(0) 0:#FF4500 1:#32CD32',
  10. stroke: 'l(0) 0:#FF4500 1:#32CD32',
  11. lineWidth: 5
  12. },
  13. selected: { // 这个用在了 鼠标选中,可以自行定义
  14. fill: 'l(0) 0:#FF4500 1:#32CD32',
  15. stroke: 'l(0) 0:#FF4500 1:#32CD32',
  16. lineWidth: 5
  17. }
  18. }
  19. })

11. 定义鼠标移入移出事件

  1. graph.on('node:mouseenter', (evt) => {
  2. const { item } = evt
  3. graph.setItemState(item, 'active', true) // active 与 selected 都是节点状态样式
  4. })
  5. graph.on('node:mouseleave', (evt) => {
  6. const { item } = evt
  7. graph.setItemState(item, 'active', false)
  8. })

12. 根据返回数据的属性不同,定制不一样的 边 样式

关于节点的差不多介绍完了,关于连线,内容就比较少了,动态定义连线样式,及连线上的文字样式:

可以根据 link的不同属性自定义 连线颜色和label颜色,因为是测试数据,因此就用一个自增长的数判断奇偶性来进行区分,以便明白其中定制化的方法

  1. let selfGrowthNum = 0
  2. graph.edge((edge)=> {
  3. // let {source, target } = edge // 解构连线的 起始节点
  4. selfGrowthNum++
  5. return {
  6. style: {
  7. opacity: 0.5,
  8. stroke: selfGrowthNum % 2 ? '#ADD8E6' : "#FFDEAD",
  9. lineWidth: 2
  10. },
  11. labelCfg: {
  12. position: 'end',
  13. style: {
  14. fontSize: 16,
  15. fill: selfGrowthNum % 2 ? '#ADD8E6' : "#FFDEAD",
  16. }
  17. },
  18. label: selfGrowthNum % 2 ? 'even' : "odd"
  19. }
  20. })

13. 设置连线上关系文案样式

上述代码基本完成了 连线的样式和文案的样式,但此时,线是贯穿文字的,看着比较乱,因此还需要修改连线样式 defaultEdge

  1. graph = new G6.TreeGraph({
  2. container,
  3. width: document.documentElement.clientWidth,
  4. height:document.documentElement.clientHeight,
  5. // .....
  6. defaultEdge: {
  7. type: 'cubic-horizontal',
  8. style: { // 如果不定制化,这个就是默认样式
  9. opacity: 0.5,
  10. stroke: '#ccc',
  11. lineWidth: 2
  12. },
  13. labelCfg: {
  14. position: 'end', // 文字显示在线段的哪个位置,
  15. refX: -15,
  16. style: {
  17. fontSize: 16,
  18. background: {
  19. fill: '#ffffff', // 给文字添加背景色,解决文字被横穿的问题
  20. padding: [2, 2, 2, 2]
  21. }
  22. }
  23. }
  24. }
  25. })

14. 解决画布拖拽,出现黑色残影问题

G6 4.x 依赖的渲染引擎 @antv/g@4.x 版本支持了局部渲染,带了性能提升的同时,也带来了图形更新时可能存在渲染残影的问题。比如拖拽节点时,节点的文本会留下轨迹。由于目前 @antv/g 正在进行大版本的升级(到 5.x),可能不考虑在 4.x 彻底修复这个问题。当我们遇到这个问题的时候,可以通过关闭局部渲染的方法解决,但是这样可能导致性能有所降低。

  1. graph.get('canvas').set('localRefresh', false)。

15. Demo 动图演示

16. 完整Demo案例

  1. <template>
  2. <div id="container"></div>
  3. </template>
  4. <script lang="ts" setup>
  5. import G6 from "@antv/g6";
  6. import { onMounted } from "vue";
  7. let graph: any = null;
  8. // 树图初始数据
  9. const treeData = {
  10. id: "Modeling Methods",
  11. color: "",
  12. children: [
  13. {
  14. id: "Classification",
  15. children: [
  16. { id: "Logistic regression" },
  17. { id: "Linear discriminant analysis" },
  18. { id: "Rules" },
  19. { id: "Decision trees" },
  20. { id: "Naive Bayes" },
  21. { id: "Knearest neighbor" },
  22. { id: "Probabilistic neural network" },
  23. { id: "Support vector machine" },
  24. ],
  25. },
  26. {
  27. id: "Methods",
  28. children: [
  29. { id: "Classifier selection" },
  30. { id: "Models diversity" },
  31. { id: "Classifier fusion" },
  32. ],
  33. },
  34. ],
  35. };
  36. onMounted(() => {
  37. splitChild(treeData);
  38. drawTreeGraph();
  39. });
  40. function drawTreeGraph() {
  41. if (graph) graph.destroy();
  42. const container = document.getElementById("container") as HTMLElement;
  43. graph = new G6.TreeGraph({
  44. container,
  45. width: document.documentElement.clientWidth - 300,
  46. height: document.documentElement.clientHeight,
  47. fitView: false,
  48. fitViewPadding: [10, 50, 10, 50],
  49. animate: true,
  50. plugins: [treeTooltip()],
  51. defaultNode: {
  52. type: "circle",
  53. size: 40,
  54. collapsed: false,
  55. style: {
  56. fill: "#fff",
  57. lineWidth: 2,
  58. cursor: "pointer",
  59. },
  60. labelCfg: {
  61. position: "right",
  62. offset: 10,
  63. style: {
  64. fill: "#333",
  65. fontSize: 20,
  66. stroke: "#fff",
  67. background: {
  68. fill: "#ffffff",
  69. padding: [2, 2, 2, 2],
  70. },
  71. },
  72. },
  73. anchorPoints: [
  74. [0, 0.5],
  75. [1, 0.5],
  76. ],
  77. icon: {
  78. show: true,
  79. width: 25,
  80. height: 25,
  81. },
  82. },
  83. defaultEdge: {
  84. type: "cubic-horizontal",
  85. labelCfg: {
  86. position: "end",
  87. refX: -15,
  88. style: {
  89. fontSize: 16,
  90. background: {
  91. fill: "#ffffff",
  92. padding: [2, 2, 2, 2],
  93. },
  94. },
  95. },
  96. },
  97. modes: {
  98. default: [
  99. {
  100. type: "collapse-expand",
  101. onChange: function onChange(item: any, collapsed) {
  102. const data = item?.get("model");
  103. data.collapsed = collapsed;
  104. const model = {
  105. id: data.id,
  106. labelCfg: { position: !collapsed ? "top" : "right" },
  107. };
  108. item.update(model);
  109. item.refresh();
  110. return true;
  111. },
  112. },
  113. "drag-canvas",
  114. "zoom-canvas",
  115. ],
  116. },
  117. layout: {
  118. type: "compactBox",
  119. direction: "LR",
  120. getHeight: function getHeight() {
  121. return 30;
  122. },
  123. getWidth: function getWidth() {
  124. return 16;
  125. },
  126. getVGap: function getVGap() {
  127. return 30;
  128. },
  129. getHGap: function getHGap() {
  130. return 150;
  131. },
  132. },
  133. nodeStateStyles: {
  134. active: {
  135. fill: "l(0) 0:#FF4500 1:#32CD32",
  136. stroke: "l(0) 0:#FF4500 1:#32CD32",
  137. lineWidth: 5,
  138. },
  139. selected: {
  140. fill: "l(0) 0:#FF4500 1:#32CD32",
  141. stroke: "l(0) 0:#FF4500 1:#32CD32",
  142. lineWidth: 5,
  143. },
  144. },
  145. });
  146. graph.node((node: { label: any; size: any }) => {
  147. return {
  148. label: node.label || formatLabel(node),
  149. icon: formatIcon(node),
  150. size: node.size || 40,
  151. labelCfg: { position: setLabelPos(node) },
  152. style: {
  153. fill: getNodeColor(),
  154. stroke: getNodeColor(),
  155. },
  156. };
  157. });
  158. let selfGrowthNum = 0;
  159. graph.edge((edge: any) => {
  160. // let {source, target } = edge // 也可以根据 link的属性不同自定义 连线颜色和label颜色,因为是测试数据,因此就用一个自增长的数判断奇偶性来进行区分,以便明白其中定制化的方法
  161. selfGrowthNum++;
  162. return {
  163. style: {
  164. opacity: 0.5,
  165. stroke: selfGrowthNum % 2 ? "#ADD8E6" : "#FFDEAD",
  166. lineWidth: 2,
  167. },
  168. labelCfg: {
  169. position: "end",
  170. style: {
  171. fontSize: 16,
  172. fill: selfGrowthNum % 2 ? "#ADD8E6" : "#FFDEAD",
  173. },
  174. },
  175. label: selfGrowthNum % 2 ? "even" : "odd",
  176. };
  177. });
  178. graph.on("node:mouseenter", (evt: { item: any }) => {
  179. const { item } = evt;
  180. graph.setItemState(item, "active", true);
  181. });
  182. graph.on("node:mouseleave", (evt: { item: any }) => {
  183. const { item } = evt;
  184. graph.setItemState(item, "active", false);
  185. });
  186. const animateCfg = { duration: 200, easing: "easeCubic" };
  187. graph.on("node:click", (evt: { item: any }) => {
  188. const { item } = evt;
  189. const node = item?.get("model");
  190. if (node.id.includes("expand")) {
  191. const parentNode = graph.getNeighbors(item, "source")[0].get("model");
  192. console.log(parentNode, parentNode.childrenBak);
  193. graph.updateChildren(parentNode.childrenBak, parentNode.id);
  194. }
  195. setTimeout(() => {
  196. if (!node.id.includes("expand")) {
  197. graph.focusItem(item, true, animateCfg);
  198. graph.getNodes().forEach((node: any) => {
  199. graph.clearItemStates(node);
  200. });
  201. graph.setItemState(item, "selected", true);
  202. }
  203. }, 500);
  204. });
  205. graph.on("canvas:click", () => {
  206. graph.getNodes().forEach((node: any) => {
  207. graph.clearItemStates(node);
  208. });
  209. });
  210. graph.data(treeData);
  211. graph.render();
  212. graph.zoom(0.9);
  213. graph.fitCenter();
  214. graph.get("canvas").set("localRefresh", false);
  215. }
  216. // label 过长截断 显示...
  217. const formatLabel = (node) => {
  218. const hasChildren = node.childrenBak?.length || node.children?.length;
  219. const ellipsis = node.id.length > 15 ? "..." : "";
  220. return `${node.id.slice(0, 15)}${ellipsis}${
  221. hasChildren ? " (" + hasChildren + ")" : ""
  222. }`;
  223. };
  224. // 叶子节点 图标处理 截取ID 前两个字符串
  225. const formatIcon = (node) => {
  226. node.icon = {
  227. text: node.id.slice(0, 2),
  228. fill: "#fff",
  229. stroke: "#fff",
  230. textBaseline: "middle",
  231. fontSize: 20,
  232. width: 25,
  233. height: 25,
  234. show: true,
  235. };
  236. };
  237. // 叶子节点 背景颜色随机填充
  238. const getNodeColor = () => {
  239. const colors = ["#8470FF", "#A020F0", "#C0FF3E", "#FF4500", "#66d6d1"];
  240. return colors[Math.floor(Math.random() * colors.length)];
  241. };
  242. // 根据节点展开收起状态 动态变更 label 显示位置,展开时在上,收起时在右
  243. const setLabelPos = (node: { collapsed: any; children: string | any[] }) => {
  244. return !node.collapsed && node.children?.length ? "top" : "right";
  245. };
  246. // label 显示... 时,显示提示 tip
  247. const treeTooltip = () => {
  248. return new G6.Tooltip({
  249. offsetX: 10,
  250. offsetY: 20,
  251. shouldBegin(e: any) {
  252. return e.item?.get("model")?.label?.includes("...");
  253. },
  254. getContent(e: any) {
  255. let outDiv = document.createElement("p");
  256. outDiv.innerHTML = ` ${e.item.getModel().id} `;
  257. return outDiv;
  258. },
  259. itemTypes: ["node"],
  260. });
  261. };
  262. // 叶子节点超过 5(xxx)条, 折叠叶子节点,显示展开更多
  263. const splitChild = (node: any) => {
  264. node.childrenBak = node.children ? [...node.children] : [];
  265. let result: any = [];
  266. if (node.children) {
  267. result = node.children.slice(0, 5);
  268. if (node.children.length > 5) {
  269. result.push({ id: `expand-${node.id}`, label: " 展开更多..." });
  270. }
  271. node.children = result;
  272. node.children.forEach((child: any) => {
  273. splitChild(child);
  274. });
  275. }
  276. };
  277. </script>
  278. <style scoped>
  279. #container >>> .g6-component-tooltip {
  280. background:#333;
  281. color:#fff;
  282. padding: 0 8px;
  283. }
  284. canvas {
  285. cursor: pointer !important;
  286. }
  287. </style>

可视化—AntV G6 紧凑树实现节点与边动态样式、超过X条展示更多等实用小功能的更多相关文章

  1. 可视化—AntV G6 高亮相邻节点的两种方式

    目录 内置的高亮节点 自定义高亮 自定义高亮时保持原始颜色 总结 案例完整代码 通过官方文档,可知高亮相邻节点分为两种方法,文档描述并不是很清楚,对刚接触这个库的小白并不是很友好,慢慢总结慢慢来吧 内 ...

  2. antV G6流程图在Vue中的使用

    最近我司项目中需要加入流程图制作功能,于是乎百度各种找可视化绘制拓扑图的轮子,大部分都是国外的,看文档太吃力,不过好在最终让我发现了AntV G6流程图图表库,最新版为2.0,不过编辑器在2.0版本还 ...

  3. React使用AntV G6实现流程图

    安装 npm install @antv/g6 --save 引用 import G6 from '@antv/g6' 自定义节点 /** * 方式一 */ G6.registerNode('rect ...

  4. vue结合antV/g6 实现网络拓扑图

    最近很多业务场景都会需要用到拓扑图,翻找了很多资料,最后选择了antV/g6,主要原因有以下几点: 1.阿里出品,所以框架的成熟性有保障 2.业务场景契合(1.规则拓扑图:2.动画流向:每个节点会有流 ...

  5. ztree树 叶子节点路径的集合

    1.Question Description: ztree树各个节点都带有路径,如“/根节点”,"/根节点/一级节点",“根节点/一级节点/二级节点‘; 现在想获取所选的最末级节点 ...

  6. 获取所有树叶子节点 注册添加事件 if ($(node).tree('isLeaf', node.target)) 是否叶子节点

    //获取所有树叶子节点 注册添加事件 if ($(node).tree('isLeaf', node.target)) 是否叶子节点 $(function () { $('.easyui-tree') ...

  7. zTree实现删除树子节点

    zTree实现删除树子节点 1.实现源码 <!DOCTYPE html> <html> <head> <title>zTree实现基本树</tit ...

  8. 探索未知种族之osg类生物---状态树与渲染树以及节点树之间的关系

    节点树 首先我们来看一个场景构建的实例,并通过它来了解一下“状态节点”StateGraph 和“渲染叶”RenderLeaf 所构成的状态树,“渲染台”RenderStage 和“渲染元”Render ...

  9. hdu6035 Colorful Tree 树形dp 给定一棵树,每个节点有一个颜色值。定义每条路径的值为经过的节点的不同颜色数。求所有路径的值和。

    /** 题目:hdu6035 Colorful Tree 链接:http://acm.hdu.edu.cn/showproblem.php?pid=6035 题意:给定一棵树,每个节点有一个颜色值.定 ...

  10. (转载)JavaScript递归查询 json 树 父子节点

    在Json中知道某个属性名,想要确定该属性在Json树具体的节点,然后进行操作还是很麻烦的 可以用以下方法找到该属性所在的节点,和父节点 <!DOCTYPE html> <html ...

随机推荐

  1. 项目实训DAY6

    今天主要的工作是把功能界面丰富了一下,查阅了一下论文,将页面中添加了可视化元素:同时决定了最后几天的工作计划.

  2. element select多选选项卡页面抖动问题

    最近做项目是有个功能需要下拉框多选,然后碰到了一个问题就是选择选项的时候出现频繁抖动的情况 问题描述: 页面选择到三个选项时长度为三的时候就会开始抖动,其他长度没有问题,检索elements是发现选择 ...

  3. Debug --> 使用USTC-TK2016工具对USTC-TFC2016数据集进行处理

    文件介绍: https://blog.csdn.net/u010916338/article/details/86511009?spm=1001.2101.3001.6661.1&utm_me ...

  4. 西瓜书3.3 尝试解题(python)对率回归 极大似然估计

    数据如下: x01=[0.697,0.774,0.634,0.608,0.556,0.403,0.481,0.437,0.666,\ 0.243,0.245,0.343,0.639,0.657,0.3 ...

  5. linux一些指令

    一.           文件操作命令 查看当前目录下的文件或文件夹 详细查看ls –l 每列代表不同的意义: 第一列drwxr-xr-x  表示权限, n  其中第一个字符d表示 目录(可能有b-块 ...

  6. 2.javaOOP_Part2继承

  7. node.js与js的关系

  8. 使用TLS/SSL传输层安全机制实现web项目的通信安全

    自己的web项目在内网ip访问时,浏览器会提示不安全 原因就是因为没有证书,而传输层的TLS/SSL协议,会告诉我们本地客户端的浏览器,我现在访问的web项目的ip地址可能存在安全风险 要解决这个通信 ...

  9. python for houdini——python在houdini中的基础应用02

    内容来源于网上视频 一.houdini python编译器 1.python shell 2.python source editor----代码可以随场景保存 构造的函数可以在外部通过hou.ses ...

  10. 容器数据库(CDB)和传统的非容器数据库的区别

    传统的非容器数据库在系统元数据和实例资源没有进行任何共享.容器数据库把 Oracle 提供的元数据.后台进程以及内存结构进行共享,把每个部门数据库的存储结构以 PDB 的形式独立出来,从而实现了系统资 ...