[Front-end novice can do big projects]: with me, from a zero to create their own online Visio project combat [ReactJS + UmiJS + DvaJS] (a)

This series of tutorials to teach you how the open source js graphics library , to create one of their own online mapping software. Of course, you can also look at this tutorial is to develop graphics library. If you feel good, like a welcome point, let us be more motivated to do a good job!

This tutorial series focuses on how to develop their own mapping software, therefore, react foundation and framework is not in this introduction. I can recommend the official website to learn react, or " React family bucket free video ."

This series of tutorials Source Address: Github

First, build a framework for environmental react

Here, we have chosen Ali UmiJS  +  DvaJS  +  Ant.Desgin  light application framework.

1. Install UmiJS

// 推荐使用yarn
npm install yarn -g

yarn global add umi

2. Install UmiJS scaffolding

mkdir topology-react
 yarn create umi
 
 // 创建项目文件后,安装依赖包
 yarn

Here, we choose typescript, dva, etc. (dll can not have been out of date).

3. The css into less

A. typings.d.ts added less

declare module '*.less';

B. global.css into global.less, and the introduction of antd theme

@import '~antd/es/style/themes/default.less';

html,
body,
#root {
  height: 100%;
}

.colorWeak {
  filter: invert(80%);
}

.ant-layout {
  min-height: 100vh; } canvas { display: block; } body { text-rendering: optimizeLegibility; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } ul, ol { list-style: none; } @media (max-width: @screen-xs) { .ant-table { width: 100%; overflow-x: auto; &-thead > tr, &-tbody > tr { > th, > td { white-space: pre; > span { display: block; } } } } } 

** C. Css into other css under less ** layouts into pages and less, and to modify the reference tsx.

4. Modify the default single-page template file

According to UmiJS agreement, we can give src / add a template file named document.ejs next pages, instead of the default template. The new template content, reference source.

Specific reference: UmiJS the HTML template document

5. Run

npm start UmiJS you can see the default interface. Code: tag: umi

Which, index.tsx under the layouts for the global template file; pages routing module.

Second, modify the page layout for navigation up and down, left-right layout

Copies of static resource files

Add another image file extensions in the typings.d.ts

declare module '*.ico';
declare module '*.svg'; declare module '*.png'; declare module '*.jpg'; 

Create a public folder into a static resource. There is no use of assets, mainly the public which put some independent static resources.

New top navigation menu bar

We create a new class layouts in Headers, as the navigation menu, add to BasicLayout inside. code show as below:

import React from 'react';
import styles from './index.less'; import Headers from './headers'; const BasicLayout: React.FC = props => { return ( <div className={styles.page}> <Headers /> <div className={styles.body}>{props.children}</div> </div> ); }; export default BasicLayout; 

Navigation menus and dialog boxes invoked onMenuClick see the source code.

Left, right workspace three-column layout

We modify pages under index.tsx, left it in the right hand column 3 is as follows:

import React from 'react';
import styles from './index.less'; import { Tools } from '@/utils/tools'; class Index extends React.Component<{}> { state = { tools: Tools, iconfont: { fontSize: '.24rem' } }; render() { return ( <div className={styles.page}> <div className={styles.tools}/> <div id="workspace" className={styles.full} /> <div className={styles.props}>{}</div> </div> ); } } export default Index; 

le5le-topology - left, right 3 column layout

Realize toolbar on the left

1. Import Fonts icon iconfont Ali introduced iconfont we need in src / pages / document.ejs in

  <link href="//at.alicdn.com/t/font_1113798_0532l8oa6jqp.css" rel="stylesheet" />
  <link href="//at.alicdn.com/t/font_1331132_5lvbai88wkb.css" rel="stylesheet" /> 

Among them, the above is the need to use the left side of the toolbar icon; below is available to the right of the property bar as a user selected node icon library. It can be replaced with its own address (note modify the data in Tools like).

2. Customize the toolbar on the left list of icons we create a new utils directory under src, with UmiJS agreed rules directory distinguished, as our custom modules. Tools.tsx a new file, the array of custom icon toolbar on the left of our list here.

Wherein, tools.tsx the following functions: file

Then, in src / pages / index.tsx import, display and loop through the left side of the toolbar icons :( here, does not define a separate category on the left toolbar, like everyone according to their habits, not a mandatory requirement, nor extreme required)

import React from 'react';
import styles from './index.less'; import { Tools } from '@/utils/tools'; class Index extends React.Component<{}> { state = { tools: Tools, iconfont: { fontSize: '.24rem' } }; render() { return ( <div className={styles.page}> <div className={styles.tools}> { this.state.tools.map((item, index) => { return ( <div key={index}> <div className={styles.title}>{item.group}</div> <div className={styles.buttons}> { item.children.map((btn: any, i: number) => { return ( <a key={i} title={btn.name}> <i className={'iconfont ' + btn.icon} style={this.state.iconfont} /> </a> ) }) } </div> </div> ) }) } </div> <div id="workspace" className={styles.full} /> <div className={styles.props}>{}</div> </div> ); } } export default Index; 

Importing canvas (focus, focus, focus)

Here is the key functional and needs based on official development document to use.

1. Install the canvas of our core library folder in package.json new file:

"topology-activity-diagram": "^0.0.4",
"topology-class-diagram": "^0.0.1",
"topology-core": "^0.0.10", "topology-flow-diagram": "^0.0.1", "topology-sequence-diagram": "^0.0.4" 

Which, topology-core is the core of the library, the other four are extended graphics library; we can develop api documentation, to realize their graphics library, and can choose to share, so that everyone used together. This is the scalability of the topology.

Then, download and install the dependent libraries yarn.

2. 注册扩展图形库 核心库仅包含最简单最基础的图形,其他丰富的图形库需要安装依赖包,并在topology-core里注册。这里我们定义一个canvasRegister的注册函数,如下:

// 先导入库
import { Topology } from 'topology-core';
import { Options } from 'topology-core/options'; import { registerNode } from 'topology-core/middles'; import { flowData, flowDataAnchors, flowDataIconRect, flowDataTextRect, flowSubprocess, flowSubprocessIconRect, flowSubprocessTextRect, flowDb, flowDbIconRect, flowDbTextRect, flowDocument, flowDocumentAnchors, flowDocumentIconRect, flowDocumentTextRect, flowInternalStorage, flowInternalStorageIconRect, flowInternalStorageTextRect, flowExternStorage, flowExternStorageAnchors, flowExternStorageIconRect, flowExternStorageTextRect, flowQueue, flowQueueIconRect, flowQueueTextRect, flowManually, flowManuallyAnchors, flowManuallyIconRect, flowManuallyTextRect, flowDisplay, flowDisplayAnchors, flowDisplayIconRect, flowDisplayTextRect, flowParallel, flowParallelAnchors, flowComment, flowCommentAnchors } from 'topology-flow-diagram'; import { activityFinal, activityFinalIconRect, activityFinalTextRect, swimlaneV, swimlaneVIconRect, swimlaneVTextRect, swimlaneH, swimlaneHIconRect, swimlaneHTextRect, fork, forkHAnchors, forkIconRect, forkTextRect, forkVAnchors } from 'topology-activity-diagram'; import { simpleClass, simpleClassIconRect, simpleClassTextRect, interfaceClass, interfaceClassIconRect, interfaceClassTextRect } from 'topology-class-diagram'; import { lifeline, lifelineAnchors, lifelineIconRect, lifelineTextRect, sequenceFocus, sequenceFocusAnchors, sequenceFocusIconRect, sequenceFocusTextRect } from 'topology-sequence-diagram'; // 使用 canvasRegister() { registerNode('flowData', flowData, flowDataAnchors, flowDataIconRect, flowDataTextRect); registerNode('flowSubprocess', flowSubprocess, null, flowSubprocessIconRect, flowSubprocessTextRect); registerNode('flowDb', flowDb, null, flowDbIconRect, flowDbTextRect); registerNode('flowDocument', flowDocument, flowDocumentAnchors, flowDocumentIconRect, flowDocumentTextRect); registerNode( 'flowInternalStorage', flowInternalStorage, null, flowInternalStorageIconRect, flowInternalStorageTextRect ); registerNode( 'flowExternStorage', flowExternStorage, flowExternStorageAnchors, flowExternStorageIconRect, flowExternStorageTextRect ); registerNode('flowQueue', flowQueue, null, flowQueueIconRect, flowQueueTextRect); registerNode('flowManually', flowManually, flowManuallyAnchors, flowManuallyIconRect, flowManuallyTextRect); registerNode('flowDisplay', flowDisplay, flowDisplayAnchors, flowDisplayIconRect, flowDisplayTextRect); registerNode('flowParallel', flowParallel, flowParallelAnchors, null, null); registerNode('flowComment', flowComment, flowCommentAnchors, null, null); // activity registerNode('activityFinal', activityFinal, null, activityFinalIconRect, activityFinalTextRect); registerNode('swimlaneV', swimlaneV, null, swimlaneVIconRect, swimlaneVTextRect); registerNode('swimlaneH', swimlaneH, null, swimlaneHIconRect, swimlaneHTextRect); registerNode('forkH', fork, forkHAnchors, forkIconRect, forkTextRect); registerNode('forkV', fork, forkVAnchors, forkIconRect, forkTextRect); // class registerNode('simpleClass', simpleClass, null, simpleClassIconRect, simpleClassTextRect); registerNode('interfaceClass', interfaceClass, null, interfaceClassIconRect, interfaceClassTextRect); // sequence registerNode('lifeline', lifeline, lifelineAnchors, lifelineIconRect, lifelineTextRect); registerNode('sequenceFocus', sequenceFocus, sequenceFocusAnchors, sequenceFocusIconRect, sequenceFocusTextRect); } 

3. 声明、定义画布对象 我们给src/pages/index.tsx下的Index类定义两个成员变量:canvas和canvasOptions

class Index extends React.Component<{}> { canvas: Topology; canvasOptions: Options = {}; state = { tools: Tools, iconfont: { fontSize: '.24rem' } }; ... } 

注意,这里并没有定义在state中,因为state用于内部的UI上数据显示和交互,我们的画布是属于一个内部非ui交互的数据。

然后,我们在dom加载完成后componentDidMount里(确保画布的父元素存在)实例化画布:

componentDidMount() {
    this.canvasRegister();
    this.canvasOptions.on = this.onMessage;
    this.canvas = new Topology('topology-canvas', this.canvasOptions); } 

其中,canvasOptions.on为画布的消息回调函数,目前为止,暂时用不到。

4. 添加左侧工具栏拖曳事件,使能够拖放图形

4.1 给图标按钮添加drag属性和事件

<a key={i} title={btn.name} draggable={true} onDragStart={(ev) => { this.onDrag(ev, btn) }}> <i className={'iconfont ' + btn.icon} style={this.state.iconfont} /> </a> 

4.2 定义onDrag函数

onDrag(event: React.DragEvent<HTMLAnchorElement>, node: any) {
  event.dataTransfer.setData('Text', JSON.stringify(node.data));
}

至此,画布的基本操作就完成了。

定义右边属性栏

1. 创建一个简单的属性栏类 同样,我们创建一个src/pages/components文件夹,放我们的组件;然后创建一个canvasProps.tsx文件。

定义props属性接口:

export interface CanvasPropsProps {
  form: FormComponentProps['form'];
  data: {
    node?: Node,
    line?: Line,
    multi?: boolean
  };
  onValuesChange: (props: any, changedValues: any, allValues: any) => void; } 

其中,node不为空表示node节点属性;line不为空表示line连线属性;multi表示多选。

其他内容就是react的表单输入,具体看源码。(这里,我们使用的是ant.design的表单

2. 定义change事件 我们还是通过ant.design的方式,定义表单的change事件:

src/pages/components/canvasProps.tsx

export default Form.create<CanvasPropsProps>({
  onValuesChange({ onValuesChange, ...restProps }, changedValues, allValues) {
    if (onValuesChange) {
      onValuesChange(restProps, changedValues, allValues);
    }
  }
})(CanvasProps);

src/pages/index.tsx

<div className={styles.props}>
  <CanvasProps data={this.state.selected} onValuesChange={this.handlePropsChange} /> </div> 
handlePropsChange = (props: any, changedValues: any, allValues: any) => {
    if (changedValues.node) {
      // 遍历查找修改的属性,赋值给原始Node

      // this.state.selected.node = Object.assign(this.state.selected.node, changedValues.node); for (const key in changedValues.node) { if (Array.isArray(changedValues.node[key])) { } else if (typeof changedValues.node[key] === 'object') { for (const k in changedValues.node[key]) { this.state.selected.node[key][k] = changedValues.node[key][k]; } } else { this.state.selected.node[key] = changedValues.node[key]; } } // 通知属性更新,刷新 this.canvas.updateProps(this.state.selected.node); } } 

简单的属性修改示例就完成了。更多属性,欢迎大家补充并提交GitHub的pr: 0. 阅读开发文档,了解相关属性。

  1. fork仓库到自己名下
  2. 本地修改并提交到自己的git仓库
  3. Find "Pull request" button on his fork warehouse, submitted file

other

Top toolbar and right-click menu function adjourned.

Open source projects is not easy, welcome to participate with, or sponsored server:

file

Guess you like

Origin www.cnblogs.com/Alsmile/p/11863708.html