draw2d
draw2d copied to clipboard
Draw2d very slow
I'm drawing a tree recursively with connections. it takes about 7 seconds to draw 15 node in chrome. Is the paid version better in performance?
painting 15 nodes with draw2d aren't slow. maybe you paint everything again and again if you add one element? the example with more than 15 elements is quite fast.
https://freegroup.github.io/draw2d/galerie_shape_basic/index.html
Hi @freegroup,
You did an awesome job and I am very thankful to you. It is working great but I am facing slowness when generating figures (Table) with lots of child nodes (columns). When I add around 10 columns, it takes 2-3 seconds to render the table which increases linearly when I add more columns.
Here is how I am generating Table.
const productSchema = {
name: "Product",
columns: [
{
type: "Column",
name: "id",
dataType: "int"
},
{
type: "Column",
name: "supplier_id",
dataType: "int"
},
// some more columns, we can simply repeate/copy paste
};
/* global $ eval */
import draw2d from "draw2d";
import Column from "./Column"; // Similar to Table, a Flex Grid with two Labels, one for name, one for type
const Table = draw2d.shape.layout.FlexGridLayout.extend({
export default draw2d.shape.layout.VerticalLayout.extend({
NAME: "Table",
init: function(attr = {}, setter, getter) {
this._super(
$.extend(
{
bgColor: "#cccccc",
stroke: 0,
width: 400
},
attr
),
setter,
getter
);
this.header = new draw2d.shape.layout.HorizontalLayout({
stroke: 0,
radius: 0,
bgColor: "#316896",
padding: 8,
cssClass: "TableHeader",
width: 400
});
this.tableNameLabel = new draw2d.shape.basic.Label({
text: attr.name || "Table",
fontColor: "#ffffff",
stroke: 0,
fontSize: 16,
cssClass: "HeaderLabel",
fontFamily: "Verdana",
padding: 0
});
this.header.add(this.tableNameLabel);
this.add(this.header, { row: 0, col: 0 });
const _this = this;
this.columns = attr.columns;
(attr.columns || []).map(function(obj, j) {
_this.add(new Column({ name: obj.name, dataType: obj.dataType }));
});
this.header.on("click", () => {
this.toFront();
this.getPorts(true).data.forEach(port => port.toFront());
});
},
setName: function(name) {
this.tableNameLabel.setText(name);
return this;
},
addColumns: function(columns) {
const _this = this;
this.columns = columns;
(columns || []).map(function(obj, j) {
_this.add(new Column({ name: obj.name, dataType: obj.dataType }));
});
},
/**
* @method
* Return an objects with all important attributes for XML or JSON serialization
*
* @returns {Object}
*/
getPersistentAttributes: function() {
const memento = this._super();
memento.name = this.tableNameLabel.getText();
memento.columns = [];
this.children.each(function(i, e) {
if (i > 0) {
// skip the header of the figure
memento.columns.push(e.figure.getPersistentAttributes());
}
});
return memento;
},
setPersistentAttributes: function(memento) {
this._super(memento);
this.setName(memento.name);
// this.addColumns(memento.columns);
if (typeof memento.columns !== "undefined") {
$.each(
memento.columns,
$.proxy(function(i, e) {
const column = this.addColumn(e);
column.setDimension(285, 32);
}, this)
);
}
return this;
},
addColumn: function(data) {
const column = new Column(data);
this.add(column);
column.setCssClass("Column");
return column;
}
});
// Here is how I am generating Table;
const table = new Table({ name: 'TableName', columns: productSchema.columns });
const createTableCommand = new draw2d.command.CommandAdd(
canvas,
figure,
x,
y
);
this.getCommandStack().execute(createTableCommand);
Let me know what I am doing wrong. Is there a batch process function like someFigure.addBatch([fig1, fig2, fig3, ..., fign]). In my case, how I can improve my performance.
Looking forward to your suggestions and feedback.
Thanks again :)
I am seeing this issue also. I have nodes that are connected and the more node/connections that are added the rendering of the canvas slows down exponentially.
https://codepen.io/desean1625/pen/WqpXqK
@freegroup Further investigation it looks like the non linear increase in time is caused by the draw2d.shape.basic.Label and other text based objects.
The reason for that seems to be the text dimension calculation. Font handling is very slow....
the BBox calculation is far from perfect and I think this the the main reason for this performance issue
https://github.com/freegroup/draw2d/blob/master/src/shape/basic/Label.js#L511-L544
getMinWidth: function () {
if (this.shape === null) {
return 0
}
if (this.cachedMinWidth === null) {
this.cachedMinWidth = this.svgNodes.getBBox(true).width
+ this.padding.left
+ this.padding.right
+ 2 * this.getStroke()
}
return this.cachedMinWidth
},
/**
*
* This value is relevant for the interactive resize of the figure.
*
* @returns {Number} Returns the min. width of this object.
*/
getMinHeight: function () {
if (this.shape === null) {
return 0
}
if (this.cachedMinHeight === null) {
this.cachedMinHeight = this.svgNodes.getBBox(true).height
+ this.padding.top
+ this.padding.bottom
+ (2 * this.getStroke())
}
return this.cachedMinHeight
},
another hot spot https://github.com/freegroup/draw2d/blob/master/src/shape/basic/Label.js#L158
@freegroup Do you have an update for this? How could I use Labels which doesn't use that BBox calculation so that the performance improved.
@desean1625 Do you have an update for draw2d Label slow performance? Im having this issue right now. I hope you could help me or give some advice.
Hello, I join the question, please help if you have a solution
Hello, @mzohaibqc @freegroup.. I join the question. When I add around 10-15 columns, it takes 2-3 seconds or more.. Is there any solution?
I also had the issue for adding multiple figures and connections on the graph. I created a custom function which adds the figures and connections and then repaints them instead of repainting it after each addition. Here's the code.
canvas.addAll = function (figures) {
for(var i = 0; i < figures.length; i++) {
var figure = figures[i].figure, x = figures[i].x, y = figures[i].y;
if (figure.getCanvas() === this) { return; }
if (figure instanceof draw2d.shape.basic.Line) {
this.lines.add(figure);
} else {
this.figures.add(figure);
if (typeof y !== "undefined") {
figure.setPosition(x, y);
} else if (typeof x !== "undefined") {
figure.setPosition(x);
}
}
figure.setCanvas(this);
// to avoid drag&drop outside of this canvas
figure.installEditPolicy(this.regionDragDropConstraint);
// important inital call
figure.getShapeElement();
// fire the figure:add event before the "move" event and after the figure.repaint() call!
// - the move event can only be fired if the figure part of the canvas.
// and in this case the notification event should be fired to the listener before
this.fireEvent("figure:add", {figure: figure, canvas: this});
// fire the event that the figure is part of the canvas
figure.fireEvent("added", {figure: figure, canvas: this});
// ...now we can fire the initial move event
figure.fireEvent("move", {figure: figure, dx: 0, dy: 0});
if (figure instanceof draw2d.shape.basic.PolyLine) {
this.calculateConnectionIntersection();
}
}
console.debug("Added all figures", performance.now());
console.debug("Repainting figures", performance.now());
this.figures.each(function(i, fig){
fig.repaint();
});
console.debug("Repainted figures", performance.now());
console.debug("Repainting lines", performance.now());
this.lines.each(function (i, line) {
line.svgPathString = null;
line.repaint();
});
console.debug("Repainted lines", performance.now());
return this;
};
@vijay1903 @onrozkrds Guys, I am sorry for you that you invested learning this and finally came to know that this is super slow, same happened to me but it's never late to try something else.
I tried FabricJs, which is fast and api is clean and simple. so have a look, it may help
http://fabricjs.com/demos/
@mzohaibqc this library out of the box can handle ports and connections. I think this is the main reason "to spend time learning it"
@freegroup So what is the issue with text and label rendering and how can it be fixed/avoided?
I have vertical layout objects that use between 10 and 15 labels for data and buttons etc. What is the alternative?
If I have just 3 or more objects on the canvas it is really slow when loading the page and rendering the objects initially.
@mzohaibqc We don't always have a choice to choose a library. Sometimes, we have to work with what we have. Especially when you have a running program.
so no news on the performance of objects with text labels?
Any update for this , if we have more than 100 node and conections, it will take more than 20 second from my PC
I have same problem with vertical layout. Every label which i added to vertical layout cause to the performance issue.
Any updates on this? Anyway to help solve the issue?