[フロントエンド初心者は大きなプロジェクトを行うことができます]:私と一緒に、ゼロから自分自身のオンラインVisioのプロジェクトの戦闘を作成するには、[ReactJS + UmiJS + DvaJS]()

どのようにチュートリアルのこのシリーズは、あなたを教えるために、オープンソースJSグラフィックスライブラリは、自分のオンラインマッピングソフトウェアの1つを作成します。もちろん、あなたはまた、グラフィックスライブラリを開発することである。このチュートリアルで見ることができます。あなたが良いと感じた場合は、歓迎のポイントのように、私たちは良い仕事をする方がやる気ことができます!

自分のマッピングソフトウェアを開発する方法についてのこのチュートリアルシリーズの焦点は、したがって、基礎を反応させ、フレームワークは、この紹介ではありません。私が反応する、または学ぶために公式サイトをお勧めすることができ、「家族バケツ無料動画を反応させるの。」

チュートリアルのソースアドレスのこのシリーズ:Githubに

まず、環境に反応するためのフレームワークを構築すること

ここでは、アリ選んだUmiJS  +  DvaJS  +  Ant.Desgin  光アプリケーションフレームワークを。

UmiJSをインストール1.

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

yarn global add umi

UmiJS足場をインストール2。

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

ここでは、(DLLが古くなっていることはできません)などtypescriptです、DVAを選択します。

3.以下にCSS

A.のtypings.d.tsは少ない追加します

declare module '*.less';

B.のglobal.lessにいるglobal.css、およびantdテーマの紹介

@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; } } } } } 

**ページと少ないに少ない**レイアウトの下に他のCSSへのC. CSSは、参照TSXを変更します。

4. [変更デフォルトの単一ページのテンプレートファイル

UmiJS合意によると、我々は代わりにデフォルトテンプレートのdocument.ejs次のページという名前のテンプレートファイルを追加/ SRCを与えることができます。新しいテンプレートコンテンツ、参照元。

特定の参照:UmiJS HTMLテンプレートドキュメント

5.ファイル名を指定して実行

NPMデフォルトのインタフェースを見ることができますUmiJSを開始します。コード:タグ:海

これは、グローバルテンプレートファイルのレイアウトの下index.tsx;モジュールをルーティングページ。

第二に、上下のナビゲーションのためのページレイアウトを変更し、左右のレイアウト

静的リソースファイルのコピー

typings.d.tsに別の画像ファイルの拡張子を追加します。

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

静的リソースへのパブリックフォルダを作成します。いくつかの独立した静的リソースを置く主に公共資産のない使用は、ありません。

新しいトップナビゲーションメニューバー

私たちは、ナビゲーションメニューとして、ヘッダに新しいクラスのレイアウトを作成し、BasicLayoutの内側に追加します。コードは以下の通りであります:

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; 

ナビゲーションメニューやダイアログボックスがonMenuClickは、ソースコードを参照してくださいに呼び出されます。

左、右のワークスペース3列のレイアウト

私たちは、index.tsx下のページを変更、右側の列3でそれを残し、次のとおりです。

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トポロジー - 左、右の3列レイアウト

左側のツールバー実現

1.インポートフォントアイコンiconfontアリたちは、SRC /ページ/ document.ejs中に必要なiconfontを導入しました

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

以下、ユーザが選択したノードのアイコンライブラリとしてプロパティバーの右側に利用可能であり、その中でも、上のツールバーアイコンの左側を使用する必要があります。それは自身のアドレス(注などのツールでデータを修正する)と交換することができます。

2.カスタマイズして、我々は、SRCの下に新しいutilsのディレクトリを作成し、アイコンの左のリストにあるツールバーUmiJSルールディレクトリを合意は、当社のカスタムモジュールとして、区別しました。Tools.tsx新しいファイル、ここで私たちのリストの左側にカスタムアイコンのツールバーの配列。

ここで、以下の機能をtools.tsx: ファイル

次に、ツールバーのアイコンの左側を通してのsrc /ページ/ index.tsxインポート、表示、ループ内で:(ここでは、彼らの習慣ではなく必須要件に応じてすべての人のように、左のツールバー上の別のカテゴリを定義していないも極端必須)

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; 

インポートキャンバス(フォーカス、フォーカス、フォーカス)

ここでは、公式に基づいてキーの機能やニーズである開発ドキュメントを使用します。

1. package.json新しいファイルに、当社のコアライブラリフォルダのキャンバスをインストールします。

"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" 

これは、トポロジ・コアライブラリの中核である、他の4つは、ライブラリのグラフィックスを拡張され、我々は彼らのグラフィックスライブラリを実現するために、APIドキュメントを開発することができ、および共有に選択することができ、その誰もが一緒に使用するようにします。これは、トポロジの拡張性です。

その後、依存ライブラリ糸をダウンロードしてインストール。

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. 提出彼のフォーク倉庫の「プルリクエスト」ボタン、検索 ファイル

他の

トップツールバーや右クリックメニュー機能が延期します。

オープンソースプロジェクトは、との参加を歓迎する、または後援サーバー、容易ではありません。

ファイル

おすすめ

転載: www.cnblogs.com/Alsmile/p/11863708.html