mxGraph 及其与 angular 8 的类型集成

mxGraph and it's Types integration with angular 8

当我使用任何一个 mxgraph methods/values 我的 mxgraph 是 'undefined'

我已经尝试过此线程上的维克斯答案:

但即使这给了我打字和智能感知工作正常我仍然有我的 mxgraph 未定义。

我应该提一下,这是一个全新的 angular 项目,我只是按照 viks 的教程来到这里。

import { mxgraph } from "mxgraph";

declare var require: any;

const mx = require('mxgraph')({
  mxBasePath: 'assets/mxgraph'
});
@Component({...})
export class LetestComponent implements OnInit {
  ngOnInit() {
    var container = document.getElementById('graphContainer');
    var graph = new mx.mxGraph(container);
  }
}

在 HTML 文件中

<div id="graphContainer"></div>

我应该不会有任何错误,我应该能够使用 mx 调用任何 mxGraph 方法。

当我编译代码时它似乎工作正常,但是当我在浏览器的控制台上查看它时我有:

"Uncaught TypeError: Cannot set property 'mxBasePath' of undefined at build.js:11 at Module../src/app/letest/letest.component.ts (letest.component.ts:6)"

我不知道这是否是个问题,因为我使用的是 angular 8,viks 的答案是 angular 4,或者它是否与 typescript 语法有关,从那时起可能已经改变.

如果有人能帮助我,那就太棒了,

提前致谢!

编辑:我还在尝试很多东西,但我想我并不真正理解 "require('mxgraph')" 部分,它在那里有未定义的甚至认为 mx 常量不是未定义的如果我将它记录到 class 中的控制台。也许 angular 8 中有一种新方法可以做同样的事情?

我还应该提到 mxgraph 的类型似乎在 Visual Code studio 中工作正常,就像我有定义但没有实际代码。

编辑 2:在深入研究之后,我开始使用 https://itnext.io/how-to-integrate-mxgraph-with-angular-6-18c3a2bb8566 但问题是这些类型已有 4 年历史,因此它缺少来自最新 mxgraph 版本的大量 methods/variables。

我发现在这些类型中只有(正在工作)

declare class mxGraph{..}

而最新的类型使用(不工作)

declare namespace mxgraph {
  export class mxGraph {..}
}

有人可以解释一下区别吗?

MxGraph 是一个用 JavaScript 编写的库。 Angular 使用的 TypeScript 具有类型(顾名思义),然后编译为 JavaScript(没有静态类型)。为了让 TypeScript 知道 JS 库中的正确类型等,您需要一些类型定义。

据我所知,MxGraph 不存在此类类型定义。

这并没有阻止我们,我们仍然可以使用 JS 库!以下是我在项目中使用 MxGraph 的方式:

我的 package.json 有正常的依赖性:"mxgraph": "^3.9.12",

但是我们还需要告诉Angular在哪里可以找到 JS 脚本!查看我的 'angular.json' 文件:

{
   "projects": {
      "architect": {
        "build": {
          "options": {
              "assets": [
                    { "glob": "**/*", "input": "src/assets/", "output": "/assets/" },
                    { "glob": "favicon.png", "input": "src/", "output": "/" },
                    { "glob": "**/*", "input": "./node_modules/mxgraph/javascript/src", "output": "/assets/mxgraph" }
        ]
              "scripts": [
                    "node_modules/mxgraph/javascript/mxClient.js"
              ]}
        }
      }
    }
}

注意:我只包含了相关的位。 我需要告诉 angular 这个外部脚本应该被包含并可用。 See docs

我的模板 (mygraph.component.html) 看起来有点不同:

<div #graphContainer
     style="overflow:hidden;width:100%;height:100%; padding: 10px;">
</div>

你看,Angular 使用“#”符号作为模板引用!

这是我的 "mygraph.component.ts":

import 'mxgraph/javascript/mxClient.js';

/**
* externally (in mxClient) defined vars
*/
declare var mxClient: any;
declare var mxUtils: any;
declare var mxRubberband: any;
declare var mxConstants: any;
declare var mxPerimeter: any;
declare var mxEdgeStyle: any;

const mx = require('mxgraph')({
    mxBasePath: 'assets/mxgraph'
});

@Component({
  selector: 'app-graph',
  templateUrl: './graph.component.html',
  styleUrls: ['./graph.component.scss']
})
export class GraphComponent {

  @ViewChild('graphContainer', { static: true }) graphContainer: Element;

  constructor(private http: HttpClient) {}

  // This I'm calling in my custom logic
  private draw() {
   // Checks if the browser is supported
    if (!mxClient.isBrowserSupported()) {
        mxUtils.error('Browser is not supported!', 200, false);
    } else {
        // Creates the graph inside the given container
        this.graphContainer['nativeElement'].innerHTML = '';
        const graph = new mx.mxGraph(this.graphContainer['nativeElement']);

        // Get and clone style, just for demonstration
        let style = graph.getStylesheet().getDefaultVertexStyle();
        let style2 = mxUtils.clone(style);
        graph.getStylesheet().putCellStyle('myStyle', style2);

        // Gets the default parent for inserting new cells. This
        // is normally the first child of the root (ie. layer 0).
        const defaultParent = graph.getDefaultParent();

        // Adds cells to the model in a single step
        graph.getModel().beginUpdate();

        try {
          // Do some drawing
          // graph.insertVertex(...
          // graph.insertEdge(...
        } finally {
          // Updates the display
          graph.getModel().endUpdate();

          // Make Graph not changeable by User
          graph.setEnabled(false);
        }            
    }
  }
}

虽然这不是一个完整的示例(我刚刚从我的代码中提取了一些有趣的部分),但它应该可以帮助您进行设置并开始使用。具体绘制请参考MxGraph文档

我也找不到与此相关的任何资源。于是自己做了几个npm包。您可以尝试在 Angular 项目中使用这些包之一。这些只是原始 mxgraph 库的打字稿包装器。

https://www.npmjs.com/package/ts-mxgraph

https://www.npmjs.com/package/ts-mxgraph-factory

https://www.npmjs.com/package/ts-mxgraph-typings

我在项目中使用了下面的方法。我在项目中创建了 mxgraph.overrides.ts 文件并导入了 mxgraph 原型。您还可以扩展库的原始方法。

import '../../assets/deflate/base64.js'
import '../../assets/deflate/pako.min.js';

import { mxgraph, mxgraphFactory } from "ts-mxgraph";
const mx = mxgraphFactory({
    mxBasePath: 'mxgraph',
    mxLoadResources: false,
    mxLoadStylesheets: false,
});

declare const Base64: any;
declare const pako: any;

let mxActor: any = mx.mxActor;
let mxArrow: any = mx.mxArrow;
let mxArrowConnector: any = mx.mxArrowConnector;
let mxGraph: any = mx.mxGraph;
let mxClient: any = mx.mxClient;
let mxUtils: any = mx.mxUtils;
...
// extends mxgraph prototypes
mxGraph.prototype.updatePageBreaks = function(visible, width, height) {
...
}
// Adds panning for the grid with no page view and disabled scrollbars
const mxGraphPanGraph = mxGraph.prototype.panGraph;
mxGraph.prototype.panGraph = function(dx, dy) {
    mxGraphPanGraph.apply(this, arguments);
    ...
}
...

export {
    mxClient,
    mxUtils,
    mxGraph,
    ...
}

// and then import these where you want to use them

import {
    mxClient,
    mxUtils,
    mxGraph,
    mxGraphModel,
    mxGeometry,
    mxConstants,
    mxCell,
    mxDictionary,
    mxCellEditor,
    mxStyleRegistry
} from './mxgraph.overrides';

import { IMAGE_PATH, STYLE_PATH, STENCIL_PATH, urlParams } from '../config';

declare var Base64: any;
declare var pako: any;

export class Graph extends mxGraph {
...
}