react hocks ggeditor 脑图开发(双向细目表), 实用技巧

ggeditor脑图开发

目录

  1. 配置说明
  2. api介绍
    ①,引入插件
    ②,获取api (withPropsAPI)
    ③,获取node api
    ④,常用api汇总
    ⑤,绑定事件
  3. 功能实现,api使用
    ①,查找节点,并居中显示 (setSelect 不居中)
    ②,切换数据之后居中显示
    ③,禁止指定node被修改

1,配置说明

ggeidtor 版本: 2.0.2
其他版本:很高(node,react,umi,  Ant Design)
说明:
	用的 Ant Design Pro 为底子开发的项目,他给的ggeditor版本较低,但样式不错,且工具模块好用,所以不做升级

参考网址
g6官网: https://g6.antv.antgroup.com/api/graph           (某些api能用)
语雀文档: https://www.yuque.com/blueju/gg-editor

因项目实际需求,本文侧重点:1,选择node,2,获取点dom以及canvas内部点,3,一部分api介绍

2, api介绍

①,引入插件
// 引入
// cnpm install --save gg-editor
// yarn add --save gg-editor
import GGEditor, { Mind, withPropsAPI } from 'gg-editor';

// 初始化
const mindContent = useRef();
<GGEditor ref={mindContent} className={styles.editor}>
<Mind 
	onNodeClick={(obj: any) => {bindCruxGroupHandler(obj)}} 
	onMouseDown={(obj: any) => {mindShouldUpdate(obj)}} 
	data={data} 
	className={styles.mind} 
/>
</GGEditor>

// data
//   1, 引入 json
import drawDataGroup from './drawDataGroup.json';
//   2, 数据格式 (根据ggeidtor版本不同,数据格式也不同)
const [data, setData] = useState({
    roots:[
      {
        id: '0',
        key: '0',
        label: '知识点',
        children: []
      }
    ]
});
const [data, setData] = useState([
      {
        id: '0',
        key: '0',
        label: '知识点',
        children: []
      }
]);

样式调整

// 新版本中, 如果遇到样式问题(典型问题:node之间间距太大,留白太多)等问题,可参考以下配置
/**
 * 注意, 以下配置仅做参考,并未投入测试以及使用,只作参考, 只作参考, 只作参考, 只作参考
*/
<Mind 
data={data} 
graphConfig={{
          defaultNode: {// 节点配置
            // style: {{fill: '#333'}}
            size: [100, 30],
            // top: -15,
            // shape: 'rect',
            type: 'rect',// 形状 // rect circle dagre
            // fontSize: 30;
            // type: 'startNode',// 'easeLinear' | 'easePolyIn' | 'easePolyOut' | 'easePolyInOut' | 'easeQuad' | 'easeQuadIn' | 'easeQuadOut' | 'easeQuadInOut'
            anchorPoints: [ // 左右接入点的位置
                [0, 0.5], // 左中 [0, 0] 左下 [0, 1] 左上
                [1, 0.5], // 右中
            ]
          },
          nodeStateStyles:{
            // fill: '#fff',
            // size: 10,
            // stroke: '#fff',
          },
          edgeStateStyles: {
            // fill: '#fff',
            // stroke: '#fff',
            lineWidth: '2',
          },
          comboStateStyles: {
            fill: 'red',
            stroke: 'red',
          },
          defaultEdge: {// 边的配置
            type: 'cubic-horizontal', // 类型
            // style: {
            //     stroke: '#A3B1BF',
            // },
            // style: {
            //   fill: 'red'
            // }
            // size: 1
          },
          defaultCombo: {
            // type: 'rect',
            shape: 'rect',
            size: '0'
          },
          // layout: {
          //   // type: 'force2',
          //   // rankdir: 'LR', // 可选,默认为图的中心
          //   // align: 'DL', // 可选
          //   // nodesep: 0, // 可选
          //   // ranksep: 50, // 可选
          //   // controlPoints: true, // 可选
          // },
          layout: { // 默认布局
            type: 'mindmap', // 类型
            direction: 'H', // 方向
            // getHeight: () => { // 节点的高度
            //     return 16;
            // },
            // getWidth: () => { // 节点的宽度
            //     return 16;
            // },
            getVGap: () => { // 节点的垂直间隙
                return 10;
            },
            getHGap: () => { // 节点的水平间隙
                return 50;
            },
          },
          // fitView:true, // 初始位置居中显示全
          fitCenter: true,
          directed: true,
          fitViewPadding: [1, 1, 1, 1],// 初始位置居中显示 , 不考虑能否显示完整
          autoPaint: true,
          // groupStyle: {
          //   style: {
          //     'fill': 'red'
          //   }
          // }
          // groupByTypes: false,// 节点是否在分组内
          // linkCenter: true, // 是否连接在节点中间
          modes: { // 设置默认mode 和 behavior
            default: [
                {
                    type: 'collapse-expand',
                    onChange: function onChange(item, collapsed) {
                        const data = item.get('model').data;
                        data.collapsed = collapsed;
                        return true;
                    },
                },
                'drag-canvas',
                'zoom-canvas',
            ],
          }
        }}
 >
 </Mind>
② 获取api (withPropsAPI)
console.log(mindContent.current)
// 下方api, 很多都没用, 酌情研究
// 重点查看的api为 .current.propsAPI.currentPage 这个是整个canvas的api

在这里插入图片描述

③ 获取node api
// 注意看上方 mindContent 为标签<GGEditor>的 ref
let node = mindContent.current.propsAPI.find('0') 
console.log(node)

在这里插入图片描述

④ 常用api汇总
  mindContent.current.propsAPI.currentPage.setSelected(node, text)
api功能
mindContent.current.propsAPI.find(‘0’) ( ‘0’为node 的 id)查找结点
node.graph.getPoint({x: document.body.clientWidth/2,y: document.body.clientHeight/2-60})获取canvas点的位置
node.graph.getCanvasPoint({x:0,y:0})获取canvas点位置,在dom中使用
mindContent.current.propsAPI.currentPage.clearSelected()清除所有选中节点
mindContent.current.propsAPI.currentPage.clearActived()清除所选选中节点
mindContent.current.propsAPI.currentPage.clearItemActived(item)清除所选节点
mindContent.current.propsAPI.currentPage.update(item,{label: text})更新节点
mindContent.current.propsAPI.currentPage.getSelected()获取所选节点
mindContent.current.propsAPI.currentPage.getZoom()放大倍数
⑤ 绑定事件

上方有介绍

<Mind 
	onNodeClick={(obj: any) => {bindCruxGroupHandler(obj)}} 
	onMouseDown={(obj: any) => {mindShouldUpdate(obj)}} 
	data={data} 
	className={styles.mind} 
/>

3, 功能实现,api使用

①, 查找节点,并居中显示 (setSelect 不居中)
 <TreeSelect 
     allowClear 
     onChange={(value) => {onSearchText(value)}}
     placeholder={'请输入...'}
     treeNodeFilterProp="label"
     showSearch
     style={{width: '240px'}}
     onFocus={() => updateSearchData()}
     treeData={searchData}//  data.roots[0].children searchData
     treeDefaultExpandAll
>
// 查询脑图 node
  const onSearchText = (text) => {
    let node = mindContent.current.propsAPI.find(text);
    if(node){
      // 改变视图位置显示节点
      let posObj = node.graph.getPoint({x: document.body.clientWidth/2,y: document.body.clientHeight/2-60});
      let zoom = node.graph.getZoom();
      node.graph.translate( zoom * ( posObj.x - node.bbox.centerX ), zoom * ( posObj.y - node.bbox.centerY))
      // 高亮显示节点
      mindContent.current.propsAPI.currentPage.clearSelected()
      mindContent.current.propsAPI.currentPage.setSelected(node, text)
    }
  }
② ,切换数据之后居中显示
const moveToCanvasCenter = () => {
    let node = mindContent.current.propsAPI.find('0');
    if(node){
      let posObj = node.graph.getPoint({x: document.body.clientWidth/2,y: document.body.clientHeight/2-60});
      let zoom = node.graph.getZoom();
      node.graph.translate( zoom * ( posObj.x - node.bbox.centerX ), zoom * ( posObj.y - node.bbox.centerY ))
    }
  }
③, 禁止指定node被修改

重点说明, 因为是低版本,没有 visible 等参数使用, 且 clearSelected 无法生效。

所以想到一个办法: 在canvas外部构造div,在mouseDown node节点的时候,瞬间将div移至节点上方进行遮挡。

  const [coverVisible, setCoverVisible] = useState(false);
  const [coverWidth, setCoverWidth] = useState(100);
  const [coverHeight, setCoverHeight] = useState(100);
  const [coverLeft, setCoverLeft] = useState(100);
  const [coverTop, setCoverTop] = useState(100);
  
  const mindShouldUpdate = (obj: any) => {
    if(obj.item && obj.item.model.id == 0){
      setCoverVisible(true);
      setCoverWidth(obj.item.bbox.width);
      setCoverHeight(obj.item.bbox.height+5);
      let posObj = obj.item.graph.getClientPoint({x: obj.item.bbox.centerX-obj.item.bbox.width/2, y: obj.item.bbox.centerY-80});
      setCoverLeft( posObj.x);
      setCoverTop(  posObj.y);
    }else{
      setCoverVisible(false);
    }
  }
  
  <div className={styles.coverDiv} style={{
        width: coverWidth + 'px',
        height: coverHeight + 'px',
        left: coverLeft + 'px',
        top: coverTop + 'px',
        display: coverVisible ? 'block' : 'none'
  }}></div>
/**
.coverDiv{
  position: absolute;
  z-index: 9999;
}
*/

总结

不得不说 ggeditor 还是非常好用的,有了这个就可以自己制作头脑风暴,计划等图,简单好用。
缺点:api不好使,且没有明确文档,建议参考最上方给的两个网址使用,g6的一些api,ggeditor也有。
扩展:谁学了这个不想自己做一个头脑风暴的网站帮自己建立计划呢? 事半功倍有木有?但想想老板给的工资,还是算了。
划~~划~~划~~,摸~~摸~~摸~~
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
React开发中,有一些小技巧可以帮助提高开发效率和代码质量。以下是一些常用的React开发小技巧: 1. 使用函数组件代替类组件:函数组件具有更简洁的语法和更好的性能,在不需要使用生命周期方法和状态管理的情况下,优先考虑使用函数组件来编写代码。 2. 使用React Fragments来包裹组件:React Fragments可以帮助我们避免多余的DOM节点,提高代码的可读性和性能。 3. 使用解构赋值来获取props:使用解构赋值可以更方便地获取和使用props,使代码更简洁。 4. 使用箭头函数来定义组件方法:箭头函数可以解决绑定this的问题,使代码更简洁易读。 5. 使用条件渲染来控制组件显示:使用条件渲染可以根据不同的条件来显示不同的组件或内容,提高代码的灵活性和可复用性。 6. 使用ES6的模板字符串来拼接字符串:使用模板字符串可以更方便地拼接字符串,避免繁琐的字符串拼接操作。 7. 使用PropTypes或TypeScript来进行类型检查:使用PropTypes或TypeScript可以帮助我们在开发过程中及时发现潜在的类型错误,提高代码的健壮性和可维护性。 8. 使用React DevTools进行调试:React DevTools是一个强大的调试工具,可以帮助我们分析组件的渲染过程、性能优化和状态管理等问题。 这些小技巧可以使React开发更加高效和优雅。但需要根据具体的项目需求和个人经验选择合适的技巧来应用。 <span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [React 开发必须知道的 34个技巧](https://blog.csdn.net/sinat_17775997/article/details/117035521)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值