如何给JointJS元素一个删除工具?
How to give JointJS elements a remove tool?
在 JointJS 中,links 附带了一个方便的响应工具,用于删除 links(当您将鼠标悬停在 link 上时,会出现 "x",然后单击它删除了 link)。另一方面,元素在 API 中有一个 remove() 方法,但没有 UI "x" 向用户公开该方法。
是否有一种直接的方法让用户能够删除 UI 中的元素?
在我的项目中,我定义了一个自定义形状 - toolElement
- 封装了此行为,然后根据需要使用其他自定义形状对其进行扩展。
完全披露:这项技术在很大程度上依赖于链接的 jointjs 代码 - 我刚刚对其进行了调整:o)
这是一个显示它工作的 jsfiddle:
http://jsfiddle.net/kj4bqczd/3/
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.ToolElementView = joint.dia.ElementView.extend({
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) {
this._dx = x;
this._dy = y;
this._action = '';
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);
},
});
然后您可以扩展这些以制作您的自定义形状。在我的项目中,我正在绘制数据流图,这里是 Process
形状的定义:
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)
});
并查看:
joint.shapes.tm.ProcessView = joint.shapes.tm.ToolElementView;
我显示和隐藏工具标记,具体取决于元素是否使用 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 example on the JointJS website。
如您所见,元素有一个关闭按钮,因此无需创建自己的按钮使事情复杂化。只需为您的元素创建一个视图,其中包含按钮的 HTML 代码以及事件处理。都在例子的源码里了
请注意,该示例没有为您提供 HTML 元素的 CSS 文件,但您也需要它:http://resources.jointjs.com/tutorials/joint/tutorials/css/html-elements.css
一种更原生的方法可以使用提供的 elementTools:
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);
在 JointJS 中,links 附带了一个方便的响应工具,用于删除 links(当您将鼠标悬停在 link 上时,会出现 "x",然后单击它删除了 link)。另一方面,元素在 API 中有一个 remove() 方法,但没有 UI "x" 向用户公开该方法。
是否有一种直接的方法让用户能够删除 UI 中的元素?
在我的项目中,我定义了一个自定义形状 - toolElement
- 封装了此行为,然后根据需要使用其他自定义形状对其进行扩展。
完全披露:这项技术在很大程度上依赖于链接的 jointjs 代码 - 我刚刚对其进行了调整:o)
这是一个显示它工作的 jsfiddle:
http://jsfiddle.net/kj4bqczd/3/
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.ToolElementView = joint.dia.ElementView.extend({
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) {
this._dx = x;
this._dy = y;
this._action = '';
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);
},
});
然后您可以扩展这些以制作您的自定义形状。在我的项目中,我正在绘制数据流图,这里是 Process
形状的定义:
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)
});
并查看:
joint.shapes.tm.ProcessView = joint.shapes.tm.ToolElementView;
我显示和隐藏工具标记,具体取决于元素是否使用 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 example on the JointJS website。
如您所见,元素有一个关闭按钮,因此无需创建自己的按钮使事情复杂化。只需为您的元素创建一个视图,其中包含按钮的 HTML 代码以及事件处理。都在例子的源码里了
请注意,该示例没有为您提供 HTML 元素的 CSS 文件,但您也需要它:http://resources.jointjs.com/tutorials/joint/tutorials/css/html-elements.css
一种更原生的方法可以使用提供的 elementTools:
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);