0

我有一个 JointJS 代码的 jsFiddle,它给了我想要的东西: https ://jsfiddle.net/RaymondMH/s46uyq8v/156/

但是,当我尝试在我的实际应用程序中使用此代码时,调用中定义的任何函数ElementView.extend()都不会被调用,并且不会像我想要的那样创建元素。

这就是我把它放在我的代码中的方式:

import { Injectable } from '@angular/core';
import * as joint from '@clientio/rappid';
import * as _ from 'lodash';
import * as V from 'jquery';

@Injectable({
    providedIn: 'root'
})
export class SchematicElementService {

    private SystemElement: any;

    constructor() {
    }

    public GetNodeElement(): { node: joint.dia.Element, embedId: number } {
        let element: joint.dia.Element;
        element = new this.SystemElement();
        element
            .prop('numberOfComponents', 4)
            .position(150, 150);
        return { node: element, embedId: null };
    }

    public InitializeDefinitions() {
        let componentOutlineRect = {
            x: 0, y: 0, width: 215, height: 24,
            fill: '#fafafa', stroke: '#000000', 'stroke-width': '0.1'
        }

        let componentText = {
            x: 0, y: 0,
            fill: 'black',
            'font-size': 13, 'font-family': 'Arial', 'font-weight': 'normal'
        }

        let componentStatusText = {
            x: 14, y: 18,
            'font-size': 13, 'font-family': 'Arial', 'font-weight': '600',
            fill: 'green'
        }

        let componentIconRect = {
            x: 34, y: 5, width: 16, height: 16,
            fill: '#565656'
        }

        this.SystemElement = joint.dia.Element.extend({
            defaults: joint.util.defaultsDeep({
                type: 'custom.Element',
                outlineColor: 'black',
                numberOfComponents: 1,
                size: {
                    width: 215,
                    height: 24
                },
                attrs: {
                    body: {
                        ...componentOutlineRect,
                        fill: '#bebebe'
                    },
                    bodytitle: {
                        ...componentText
                    },
                    components: {
                        ...componentOutlineRect,
                        y: 24,
                    }
                }
            }),
            markup: [
                { tagName: 'rect', selector: 'body' },
                { tagName: 'text', selector: 'bodytitle' },
                { tagName: 'rect', selector: 'components' },
                { tagName: 'text', selector: 'componentStatus' },
                { tagName: 'rect', selector: 'componentIcons' },
                { tagName: 'text', selector: 'text' }
            ]
        });
        this.SystemElement.ElementView = joint.dia.ElementView.extend(
            {
                events: {
                    'dblclick': 'onDblClick',
                    'click .components': 'onComponentClick'
                },

                init: function () {
                    console.log('************* init() function called!');
                    var model = this.model;
                    this.listenTo(model, [
                        'change:fillColor',
                        'change:outlineColor',
                    ].join(' '), this.update);
                    this.listenTo(model, 'change:numberOfComponents', this.render);
                },

                render: function () {
                    console.log('**************** render function called!');
                    var markup = this.constructor.markup;
                    var body = this.vBody = markup.body.clone();
                    var bodyTitle = this.vBodyTitle = markup.bodytitle.clone().text('A - Static Structural');
                    var components = this.vComponents = [];
                    var componentStatus = this.vComponentStatus = [];
                    var componentIcons = this.vComponentIcons = [];
                    var componentLabels = this.vComponentLabels = [];
                    for (var i = 0, n = this.model.prop('numberOfComponents'); i < n; i++) {
                        components.push(markup.components.clone());
                        componentStatus.push(markup.componentStatus.clone().text('✓'));
                        componentIcons.push(markup.componentIcons.clone());
                        componentLabels.push(markup.text.clone().text('Component ' + (i + 1)));
                    }
                    this.vel.empty().append(
                        _.flatten([
                            body,
                            components
                        ])
                    );
                    this.translate();
                    this.update();
                },

                update: function () {
                    this.updateBody();
                    this.updateComponents();
                },

                updateBody: function () {
                    var model = this.model;
                    var bodyAttributes = {
                        ...componentOutlineRect,
                        fill: '#aaaaaa',
                    };
                    this.vBody.attr(bodyAttributes);

                    var bodyTitle = this.vBodyTitle;
                    bodyTitle.attr({
                        ...componentText,
                        'font-weight': '600',
                        transform: 'translate(14,16)'
                    });
                    this.vel.append(bodyTitle);
                },

                updateComponents: function () {
                    console.log('************** updateComponents called!');
                    var model = this.model;
                    var numberOfComponents = model.prop('numberOfComponents');
                    var vComponents = this.vComponents;
                    for (var i = 0; i < numberOfComponents; i++) {
                        vComponents[i].attr({
                            ...componentOutlineRect,
                            y: 24 * (i + 1),
                            'data-index': i
                        });
                    }

                    var vComponentStatus = this.vComponentStatus;
                    for (var i = 0; i < numberOfComponents; i++) {
                        var vStatus = vComponentStatus[i];
                        var tx = 14;
                        var ty = 24 * (i + 1);
                        vStatus.attr({
                            ...componentStatusText,
                            transform: 'translate(' + tx + ',' + ty + ')'
                        });
                        this.vel.append(vStatus);
                    }

                    var vComponentIcons = this.vComponentIcons;
                    for (var i = 0; i < numberOfComponents; i++) {
                        var vIcon = vComponentIcons[i];
                        vIcon.attr({
                            ...componentIconRect,
                            x: 34,
                            y: 24 * (i + 1) + 4
                        });
                        this.vel.append(vIcon);
                    }

                    var vComponentLabels = this.vComponentLabels;
                    for (var i = 0; i < numberOfComponents; i++) {
                        var vText = vComponentLabels[i];
                        var tx = 58;
                        var ty = 24 * (i + 2) - 8;
                        vText.attr({
                            ...componentText,
                            transform: 'translate(' + tx + ',' + ty + ')'
                        });
                        this.vel.append(vText);
                    }
                },

                onComponentClick: function (evt) {
                    var index = +V(evt.target).attr('data-index');

                    var model = this.model;
                    var numberOfComponents = model.prop('numberOfComponents');
                    var vComponents = this.vComponents;
                    for (var i = 0; i < numberOfComponents; i++) {
                        vComponents[i].attr({
                            fill: i === index ? '#dddddd' : "#fafafa"
                        });
                    }
                },

                onDblClick: function () {
                    this.model.prop('faded', !this.model.prop('faded'));
                }
            });

        // SEE COMMENTS BELOW REGARDING THIS COMMENTED CODE:
        //}, {
        //    markup: {
        //        body: V('rect').addClass('body'),
        //        bodytitle: V('text').addClass('bodytitle'),
        //        components: V('rect').addClass('components'),
        //        componentStatus: V('text').addClass('componentStatus'),
        //        componentIcons: V('rect').addClass('componentIcons'),
        //        text: V('text').addClass('text')
        //    }
        //});

    }
}

元素初始化如下:

    ngOnInit(): void {
        this.schematicElementService.InitializeDefinitions();
        this.graph = new joint.dia.Graph();

        this.paper = new joint.dia.Paper({
            model: this.graph,
            cellViewNamespace: joint.shapes.basic,
            el: $('#paper'),
            width: 2400,
            height: 2400,
            origin: { x: 600, y: 600 },
            gridSize: 1,
            // interactive: { addLinkFromMagnet: false },
            linkPinning: false
        });
    }

元素被添加到图表中,如下所示:

        let nodeData = this.schematicElementService.GetNodeElement();
        this.graph.addCell(nodeData.node);

与 jsFiddle 不同的方式是,Markup 被放置在Element.extend()函数中而不是在ElementView.extend()(如 中的注释代码所示ElementView.extend())中。

如上所述实现,我得到了几个“框”,但由于没有使用 ElementView 中的功能,它不会像我期望的那样处理事情。即没有文本,也没有多个框,因为这些是在函数中处理的。

当我从 中删除标记Element.extend()并将其放入ElementView.extend()(即取消注释上面的注释代码)时,处理此错误时出现以下错误:

ERROR Error: dia.ElementView: markup required
    at child.renderMarkup (rappid.js:19452)
    at child.render (rappid.js:19483)
    at child.protoProps.render (rappid.js:18246)
    at child.confirmUpdate (rappid.js:19372)
    at child.updateView (rappid.js:29615)
    at child.updateViewsBatch (rappid.js:29812)
    at child.updateViews (rappid.js:29668)
    at child.requestViewUpdate (rappid.js:29539)
    at child.renderView (rappid.js:30305)
    at child.onCellAdded (rappid.js:29261)

我添加到函数中的console.log()所有调用都不会写入控制台,因此这些函数都不会被调用。在联合数据结构中定义我的自定义元素,如 injoint.shapes.custom = {}并没有什么区别。使用 JointJS 或 Rappid 库时,我遇到了同样的问题。

有人看到我在这里做错了吗?我无法弄清楚如何使这项工作。

提前感谢您提供的任何帮助。

4

1 回答 1

0

我不确定这是否适用于您的情况,但您可以尝试指定初始化纸张时要使用的视图,并带有以下elementView选项:

 this.paper = new joint.dia.Paper({
            model: this.graph,
            cellViewNamespace: joint.shapes.basic,
            elementView: this.schematicElementService.ElementView,
            ...

另外,我不确定元素视图是否应该是元素的子元素。在我的例子中,我将元素视图放在一个单独的变量中。

于 2021-03-31T00:46:25.273 回答