最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • LogicFlow core解析(一)

    正文概述 掘金(七日夜)   2021-03-16   1190

    1、环境设置与启动项目

    从git下载代码,进入到packages/core文件夹,cnpm install(或者yarn)安装相关依赖包。npm run dev启动项目,访问http://localhost:9090/ 至此LogicFlow core项目已经正常启动了。

    2、代码流程梳理

    0、起步
    import LogicFlow from '@logicflow/core';
    const config = {
      isSilentMode: true,
      stopScrollGraph: true,
      stopZoomGraph: true,
      style: {
        rect: {
          width: 100,
          height: 50
        }
      }
    }
    const data = {
      nodes: [
        {
          id: 10,
          type: 'rect',
          x: 150,
          y: 70,
          text: '矩形1'
        }
      ]
    };
    const lf = new LogicFlow({
      ...config,
      container: document.querySelector('#graph') as HTMLElement
    });
    lf.render(data);
    

    从上面的使用方法可以看出,入口是LogicFlow,先new LogicFlow({})调用LogicFlow的构造函数,之后lf.render(data)绘制data数据到页面中用svg展示。

    1、LogicFlow.tsx

    这是项目的入口文件,文件中定义了class LogicFlow, 其包含需多的方法,根据例子中代码的执行到lf.render(data);,从LogicFlow的render开始(构造函数会初始化一些参数,用到的参数会详细说明)。

    import { render, h } from 'preact';
    export default class LogicFlow {
        constructor(options: Options.Definition) {}
        render(graphData = {}) {//代码有省略
            this.graphModel.graphDataToModel(graphData);
            render((
              <Provider
                graphModel={this.graphModel}
              >
                <Graph
                  eventCenter={this.eventCenter}
                  getView={this.getView}
                  tool={this.tool}
                  options={this.options}
                  dnd={this.dnd}
                  snaplineModel={this.snaplineModel}
                  components={this.components}
                />
              </Provider>
            ), this.container);
      }
    }
    

    外层的render函数是LogicFlow中的,内层的render是preact中的。 render中执行this.graphModel.graphDataToModel(graphData),代码调用GraphModel.ts中的graphDataToModel方法,设置nodes和edges,代码如下

    graphDataToModel(graphData) {//代码有省略
        this.nodes = map(graphData.nodes, node => {
            const Model = this.getModel(node.type);
            return new Model(node, this);
        });
        this.edges = map(graphData.edges, edge => {
            const Model = this.getModel(edge.type);
            return new Model(edge, this);
        });
    }
    
    getModel(type: string) {
        return this.modelMap.get(type);
    }
    

    其中调用this.getModel(type: string)获取Model,函数this.getModel中的this.modelMap的内容是在LogicFlow.tsx中调用 this.graphModel.setModel(type, ModelClass);进行写入的。

    代码new Model(node, this);中的Model最终可以找到RectNodeModel.ts中。

    import { computed, observable } from 'mobx';
    class RectNodeModel extends BaseNodeModel {
        modelType = ModelType.RECT_NODE;
        @observable width = defaultTheme.rect.width;
        @observable height = defaultTheme.rect.height;
        @observable radius = defaultTheme.rect.radius;
    }
    export default class BaseNodeModel implements IBaseModel {}
    

    RectNodeModel继承了BaseNodeModel,两个类中的很多属性前添加了@observable注解(observable表示属性是可观测的,当属性被改变时,将会触发组件的重新渲染展示在页面中)。

    到这里,执行第二个render函数把this.graphModel传递给Provider了。

    <Provider graphModel={this.graphModel}>
        <Graph
        />
    </Provider>
    
    2、Graph.tsx

    LogicFlow的第二个render函数执行渲染,会进入到Graph.tsx组件中。

    import { observer, inject } from 'mobx-react';
    @inject('graphModel')
    @observer
    class Graph extends Component<IProps> {//这是一个组件
        render() {
            return (<div>
                <CanvasOverlay>
                    <g className="lf-base">
                        {
                            map(graphModel.sortElements, (nodeModel) => (
                                this.getComponent(nodeModel, graphModel, eventCenter)
                            ))
                        }
                    </g>
                </CanvasOverlay>
            </div>)
        }
    }
    

    在Graph.tsx中,@inject('graphModel')会引入Provider组件中提供的graphModel参数,至此Graph组件中的this.props属性中含有了graphModel。

    Graph.tsx中render的return中使用了CanvasOverlay组件

    class CanvasOverlay extends Component<IProps, Istate> {
        render() {
        const { transformStyle: { transform } } = this.InjectedProps;
        const { children, dnd } = this.props;
        const { isDraging } = this.state;
            return (
                <svg
                    xmlns="http://www.w3.org/2000/svg"
                    width="100%"
                    height="100%"
                    name="canvas-overlay"
                    onWheel={this.zoomHandler}
                    onMouseDown={this.mouseDownHandler}
                    onContextMenu={this.handleContextMenu}
                    className={isDraging ? 'lf-dragging' : 'lf-drag-able'}
                    {...dnd.eventMap()}
                >
                    <g style={{ transform }}>
                        {children}
                    </g>
                </svg>
            );
        }
    }
    

    CanvasOverlay组件中使用的children,就是Graph提供的。

    <g className="lf-base">
        {
            map(graphModel.sortElements, (nodeModel) => (
                this.getComponent(nodeModel, graphModel, eventCenter)
            ))
        }
    </g>
    

    this.getComponent函数还在Graph.tsx中。

    getComponent() {
        const { getView } = this.props;
        const View = getView(model.type);//'rect'
        return (
            <View
                key={model.id}
                model={model}
                graphModel={graphModel}
                overlay={overlay}
                eventCenter={eventCenter}
            />
        );
    }
    

    getView(model.type)函数在LogicFlow.tsx中。

    getView = (type: string) => this.viewMap.get(type);
    

    this.viewMap中的数据内容是通过this.setView(type, observer(ViewClass as IReactComponent));写入的。 最终可以找到RectNode.tsx中。

    3、RectNode.tsx
    export default class RectNode extends BaseNode {
        getShape() {
            const attributes = this.getAttributes();
            return (
                <Rect
                    {...attributes}
                />
            );
        }
    }
    
    export default abstract class BaseNode extends Component<IProps, Istate> {
        render() {
            const nodeShapeInner = (
                <g className="lf-node-content">
                    {this.getShape()}
                    {this.getText()}
                </g>
            );
            let nodeShape;
            if (!isHitable) {
                nodeShape = (
                    <g className={this.getStateClassName()} id={model.id}>
                        { nodeShapeInner }
                    </g>
                );
            } else {
                nodeShape = (
                    <g
                        className={this.getStateClassName()}
                        id={model.id}
                        onMouseDown={this.handleMouseDown}
                        onMouseUp={this.handleClick}
                        onMouseEnter={this.setHoverON}
                        onMouseLeave={this.setHoverOFF}
                        onContextMenu={this.handleContextMenu}
                    >
                        { nodeShapeInner }
                    </g>
                );
            }
            return nodeShape;
        }
    }
    

    RectNode继承自BaseNode,变成了是一个组件,继承了BaseNode中的render函数。在render函数中调用this.getShape()<Rect {...attributes} />组件。

    4、Rect.tsx
    export default function Rect(props: IProps) {
        return (
            <rect {...attrs} />
        );
    }
    

    这是一个函数组件,是最终渲染到页面中svg标签内的rect标签。

    至此上面实例中rect矩形被成功渲染到了页面中。

    3、详解

    未完待续。。。


    起源地下载网 » LogicFlow core解析(一)

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元