Javascript 如何为JointJS元素提供移除工具?

Javascript 如何为JointJS元素提供移除工具?,javascript,jquery,graph,jointjs,Javascript,Jquery,Graph,Jointjs,在JointJS中,链接附带了一个方便的删除链接的响应工具(当您将鼠标悬停在链接上时,会出现一个“x”,单击它会删除链接)。另一方面,元素在API中有一个remove()方法,但没有向用户公开该方法的UI“x” 有没有一种简单的方法可以让用户删除UI中的元素?在我的项目中,我定义了一个自定义形状-toolElement,它封装了这种行为,然后根据需要用其他自定义形状扩展它 全面披露:这项技术在很大程度上依赖于链接的jointjs代码——我刚刚修改了它:o) 下面是一个JSFIDLE,显示它的工作

在JointJS中,链接附带了一个方便的删除链接的响应工具(当您将鼠标悬停在链接上时,会出现一个“x”,单击它会删除链接)。另一方面,元素在API中有一个remove()方法,但没有向用户公开该方法的UI“x”


有没有一种简单的方法可以让用户删除UI中的元素?

在我的项目中,我定义了一个自定义形状-
toolElement
,它封装了这种行为,然后根据需要用其他自定义形状扩展它

全面披露:这项技术在很大程度上依赖于链接的jointjs代码——我刚刚修改了它:o)

下面是一个JSFIDLE,显示它的工作原理:

toolElement
的定义如下:

joint.shapes.tm.toolElement = joint.shapes.basic.Generic.extend({

    toolMarkup: ['<g class="element-tools">',
        '<g class="element-tool-remove"><circle fill="red" r="11"/>',
        '<path transform="scale(.8) translate(-16, -16)" d="M24.778,21.419 19.276,15.917 24.777,10.415 21.949,7.585 16.447,13.087 10.945,7.585 8.117,10.415 13.618,15.917 8.116,21.419 10.946,24.248 16.447,18.746 21.948,24.248z"/>',
        '<title>Remove this element from the model</title>',
        '</g>',
        '</g>'].join(''),

    defaults: joint.util.deepSupplement({
        attrs: {
            text: { 'font-weight': 400, 'font-size': 'small', fill: 'black', 'text-anchor': 'middle', 'ref-x': .5, 'ref-y': .5, 'y-alignment': 'middle' },
        },
    }, joint.shapes.basic.Generic.prototype.defaults)

});
然后,您可以扩展这些形状以创建自定义形状。在我的项目中,我正在绘制数据流图,下面是
过程
形状的定义:

joint.shapes.tm.Process = joint.shapes.tm.toolElement.extend({

    markup: '<g class="rotatable"><g class="scalable"><circle class="element-process"/><title class="tooltip"/></g><text/></g>',

    defaults: joint.util.deepSupplement({
        type: 'tm.Process',
        attrs: {
            '.element-process': { 'stroke-width': 1, r: 30, stroke: 'black', transform: 'translate(30, 30)' },
            text: { ref: '.element-process'}
        },
        size: { width: 100, height: 100 }
    }, joint.shapes.tm.toolElement.prototype.defaults)
});
我显示和隐藏工具标记,这取决于是否使用CSS高亮显示元素。如果愿意,您可以在悬停时执行相同的操作(就像链接一样):

.element .element-tools {
    display: none;
    cursor: pointer
}

.element.highlighted .element-tools {
    display: inline;
}
渲染时,它看起来是这样的(注意:在我的例子中,我在工具中有另一个按钮,而不仅仅是删除按钮-这就是绿色的V形按钮。我从上面的代码示例中删除了这个按钮以使它们更简单):

当图元未高亮显示时:

突出显示时:

然后,通过扩展toolElement,我可以非常轻松地定义其他形状。以下是数据存储的数据流图形状:

和外部行为者:

joint.shapes.devs.ModelView = joint.dia.ElementView.extend(_.extend({},joint.shapes.basic.PortsViewInterface,{
         initialize:function(){
         joint.dia.ElementView.prototype.initialize.apply(this,arguments);
 },
    render:function(){
            joint.dia.ElementView.prototype.render.apply(this,arguments);
            this.renderTools();
            this.update();
            return this;
},
    renderTools:function(){
         var toolMarkup = this.model.toolMarkup || this.model.get('toolMarkup');

          if (toolMarkup) {

             var nodes = V(toolMarkup);
             V(this.el).append(nodes);

    }

    return this;
},
    pointerclick: function (evt, x, y) {
        var className = evt.target.parentNode.getAttribute('class');
        switch (className) {

            case 'element-tool-remove':
            this.model.remove();
            return;
            break;

            default:
    }

     joint.dia.CellView.prototype.pointerclick.apply(this, arguments);
}

})))

看一看

正如您可以看到的,元素在那里有一个关闭按钮,因此没有必要通过创建自己的按钮来使事情复杂化。只需为元素创建一个视图,其中包含按钮的HTML代码以及事件处理。这些都在示例的源代码中


请注意,该示例没有为HTML元素提供CSS文件,但您也需要它:

一种更自然的方法可以使用提供的:


你好,迈克。你能把代码上传到某个地方吗?我不太清楚如何把所有的东西拼凑在一起,真是太棒了!!是否可以以某种方式扩展所有元素,使此工具提示位于顶部?这是令人惊讶的,但我不喜欢我的所有对象都必须有Actor作为父对象的想法,例如有dev.Model扩展。我也想扩展它。元素必须从toolElement而不是Actor扩展,但我明白你的意思。对不起,我不知道怎么做。对不起,迈克,再次打扰你。你能给我一些关于如何创建链接按钮的提示吗?你是赋予它磁性,还是从零地开始写功能?
.element .element-tools {
    display: none;
    cursor: pointer
}

.element.highlighted .element-tools {
    display: inline;
}
joint.shapes.devs.ModelView = joint.dia.ElementView.extend(_.extend({},joint.shapes.basic.PortsViewInterface,{
         initialize:function(){
         joint.dia.ElementView.prototype.initialize.apply(this,arguments);
 },
    render:function(){
            joint.dia.ElementView.prototype.render.apply(this,arguments);
            this.renderTools();
            this.update();
            return this;
},
    renderTools:function(){
         var toolMarkup = this.model.toolMarkup || this.model.get('toolMarkup');

          if (toolMarkup) {

             var nodes = V(toolMarkup);
             V(this.el).append(nodes);

    }

    return this;
},
    pointerclick: function (evt, x, y) {
        var className = evt.target.parentNode.getAttribute('class');
        switch (className) {

            case 'element-tool-remove':
            this.model.remove();
            return;
            break;

            default:
    }

     joint.dia.CellView.prototype.pointerclick.apply(this, arguments);
}
const view = element.findView(paper);
const removeButton = new joint.elementTools.Remove({
    focusOpacity: 0.5,
    rotate: true,
    x: '50%',
    y: '0%',
    offset: { x: 10, y: 10 }
});

const toolsView = new joint.dia.ToolsView({
    name: 'basic-tools',
    tools: [removeButton]
});

view.addTools(toolsView);