Я пытаюсь создать приложение Jointjs на Angular v8, я подготовил то же самое на обычном HTML, JS, и, кажется, работает нормально.
Требование:
- Перетащите &Выпадающие окна из левого бокового меню
- При перетаскивании данные должны быть преобразованы в поля с входными и выходными портами, HTML-закрытие и Div перекрывают поле
var graph = new joint.dia.Graph;
var paper = new joint.dia.Paper({
el: document.getElementById('editor'),
model: graph,
width: '80%',
height: '100%',
gridSize: 1
});
$(function () {
$('#menu').jstree({
'core': {
'data': [
{
"text": "Root node", "children": [
{
"text": "Child node 1", "children": [
{ "text": "Node 11" }, { "text": "Node 12" }]
},
{
"text": "Child node 2", "children": [
{ "text": "Node 21" }, { "text": "Node 22" }]
}
]
}
]
},
'plugins': ['dnd']
});
$(document)
.on('dnd_move.vakata', function (e, data) {
var t = $(data.event.target);
if (!t.closest('.jstree').length) {
if (t.closest('.drop').length) {
//alert("drop zone found") ;
data.helper.find('.jstree-icon').removeClass('jstree-er').addClass('jstree-ok');
}
else {
data.helper.find('.jstree-icon').removeClass('jstree-ok').addClass('jstree-er');
}
}
})
.on('dnd_stop.vakata', function (e, data) {
//alert(data.event.pageX + " : " + data.event.pageY) ;
var t = $(data.event.target);
if (!t.closest('.jstree').length) {
if (t.closest('.drop').length) {
createDropShape(data.event.pageX, data.event.pageY, t.closest('.drop').position(), "hello", "");
//$(data.element).clone().appendTo(t.closest('.drop'));
}
}
});
});
(function () {
// Create a custom element.
// ------------------------
joint.shapes.html = {};
//joint.shapes.test.Element = $.extend(joint.shapes.devs.Model, joint.shapes.basic.Rect);
joint.shapes.html.Element = joint.shapes.devs.Model.extend({
defaults: joint.util.deepSupplement({
type: 'html.Element',
attrs: {
rect: { stroke: 'none', 'fill-opacity': 0 }
}
}, joint.shapes.devs.Model.prototype.defaults)
});
joint.shapes.html.ElementView = joint.dia.ElementView.extend({
template: [
'<div class="html-element">',
'<button class="delete">x</button>',
'<label>Test</label>',
'</div>'
].join(''),
initialize: function () {
_.bindAll(this, 'updateBox');
joint.dia.ElementView.prototype.initialize.apply(this, arguments);
this.$box = $(_.template(this.template)());
// Prevent paper from handling pointerdown.
this.$box.find('input,select').on('mousedown click', function (evt) {
evt.stopPropagation();
});
// This is an example of reacting on the input change and storing the input data in the cell model.
this.$box.find('input').on('change', _.bind(function (evt) {
this.model.set('input', $(evt.target).val());
}, this));
this.$box.find('select').on('change', _.bind(function (evt) {
this.model.set('select', $(evt.target).val());
}, this));
this.$box.find('select').val(this.model.get('select'));
this.$box.find('.delete').on('click', _.bind(this.model.remove, this.model));
// Update the box position whenever the underlying model changes.
this.model.on('change', this.updateBox, this);
// Remove the box when the model gets removed from the graph.
this.model.on('remove', this.removeBox, this);
this.updateBox();
},
render: function () {
joint.dia.ElementView.prototype.render.apply(this, arguments);
this.paper.$el.prepend(this.$box);
this.updateBox();
return this;
},
updateBox: function () {
// Set the position and dimension of the box so that it covers the JointJS element.
var bbox = this.model.getBBox();
// Example of updating the HTML with a data stored in the cell model.
this.$box.find('label').text(this.model.get('label'));
this.$box.find('span').text(this.model.get('select'));
this.$box.css({
width: bbox.width,
height: bbox.height,
left: bbox.x,
top: bbox.y,
transform: 'rotate(' + (this.model.get('angle') || 0) + 'deg)'
});
},
removeBox: function (evt) {
this.$box.remove();
}
});
}());
function createDropShape(pageX, pageY, parentPosition, shapeText, icon) {
var x = pageX - parentPosition.left;
var y = pageY - parentPosition.top;
/*rect.position(x, y);
rect.resize(100, 40);
rect.attr({
body: {
fill: 'blue'
},
label: {
text: shapeText,
fill: 'white'
}
});
rect.addTo(graph);*/
var m1 = new joint.shapes.html.Element({
position: { x:x, y:y },
size: { width: 90, height: 90 },
inPorts: ['in1', 'in2'],
outPorts: ['out'],
ports: {
groups: {
'in': {
attrs: {
'.port-body': {
fill: '#16A085'
}
}
},
'out': {
attrs: {
'.port-body': {
fill: '#E74C3C'
}
}
}
}
},
attrs: {
'.label': { text: 'hello', 'ref-x': .5, 'ref-y': .2 },
rect: { fill: '#2ECC71' }
}
});
graph.addCell(m1);
}
#paper-html-elements {
position: relative;
border: 1px solid gray;
display: inline-block;
background: transparent;
overflow: hidden;
}
#paper-html-elements svg {
background: transparent;
}
#paper-html-elements svg .link {
z-index: 2;
}
.html-element {
position: absolute;
background: #3498DB;
/* Make sure events are propagated to the JointJS element so, e.g. dragging works.*/
pointer-events: none;
-webkit-user-select: none;
border-radius: 4px;
border: 2px solid #2980B9;
box-shadow: inset 0 0 5px black, 2px 2px 1px gray;
padding: 5px;
box-sizing: border-box;
z-index: 2;
}
.html-element select,
.html-element input,
.html-element button {
/* Enable interacting with inputs only. */
pointer-events: auto;
}
.html-element button.delete {
color: white;
border: none;
background-color: #C0392B;
border-radius: 20px;
width: 15px;
height: 15px;
line-height: 15px;
text-align: middle;
position: absolute;
top: -15px;
left: -15px;
padding: 0;
margin: 0;
font-weight: bold;
cursor: pointer;
}
.html-element button.delete:hover {
width: 20px;
height: 20px;
line-height: 20px;
}
.html-element select {
position: absolute;
right: 2px;
bottom: 28px;
}
.html-element input {
position: absolute;
bottom: 0;
left: 0;
right: 0;
border: none;
color: #333;
padding: 5px;
height: 16px;
}
.html-element label {
color: #333;
text-shadow: 1px 0 0 lightgray;
font-weight: bold;
}
.html-element span {
position: absolute;
top: 2px;
right: 9px;
color: white;
font-size: 10px;
}
#menu,
#editor {
float: left;
min-height:500px;
border:1px solid red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.9.1/underscore-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.4.0/backbone-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/jointjs/3.0.4/joint.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jointjs/3.0.4/joint.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/themes/default/style.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/jstree.min.js"></script>
<div id="container">
<div id="menu" class="jstree jstree-default">
</div>
<div id="editor" class="drop">
</div>
</div>
Хотите знать, как это будет работать с angular, пробовал несколько вещей, так как Jointjs работал с Angular, но перекрывающийся HTML на объекте svg jointjs не работает