Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improving speed by batching dom reads and writes #394

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
146 changes: 120 additions & 26 deletions dist/dagre-d3.core.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/dagre-d3.core.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/dagre-d3.core.min.js.map

Large diffs are not rendered by default.

146 changes: 120 additions & 26 deletions dist/dagre-d3.js

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions dist/dagre-d3.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/dagre-d3.min.js.map

Large diffs are not rendered by default.

5 changes: 4 additions & 1 deletion lib/create-clusters.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,17 @@ function createClusters(selection, g) {
util.applyTransition(svgClusters, g)
.style("opacity", 1);

var itemQueue = [];
svgClusters.each(function(v) {
var node = g.node(v),
thisGroup = d3.select(this);
d3.select(this).append("rect");
var labelGroup = thisGroup.append("g").attr("class", "label");
addLabel(labelGroup, node, node.clusterLabelPos);
itemQueue.push(addLabel.createLabel(labelGroup, node, node.clusterLabelPos));
});

addLabel.styleLabels(itemQueue);

svgClusters.selectAll("rect").each(function(c) {
var node = g.node(c);
var domCluster = d3.select(this);
Expand Down
28 changes: 25 additions & 3 deletions lib/create-edge-labels.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,32 @@ function createEdgeLabels(selection, g) {
.append("g")
.classed("edgeLabel", true)
.style("opacity", 0);

var itemQueue = [];
var labelQueue = [];

svgEdgeLabels.each(function(e) {
var edge = g.edge(e),
label = addLabel(d3.select(this), g.edge(e), 0, 0).classed("label", true),
bbox = label.node().getBBox();
var edge = g.edge(e);

var label = addLabel.createLabel(d3.select(this), g.edge(e), 0, 0);

label.labelSvg.classed("label", true);

labelQueue.push(label);

itemQueue.push({edge: edge, label: label.labelSvg});
});

addLabel.styleLabels(labelQueue);

itemQueue.forEach(function(item) {
item.bbox = item.label.node().getBBox();
});

itemQueue.forEach(function(item) {
var label = item.label;
var edge = item.edge;
var bbox = item.bbox;

if (edge.labelId) { label.attr("id", edge.labelId); }
if (!_.has(edge, "width")) { edge.width = bbox.width; }
Expand Down
24 changes: 16 additions & 8 deletions lib/create-edge-paths.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,14 +105,22 @@ function enter(svgPaths, g) {
.append("g")
.attr("class", "edgePath")
.style("opacity", 0);
svgPathsEnter.append("path")
.attr("class", "path")
.attr("d", function(e) {
var edge = g.edge(e),
sourceElem = g.node(e.v).elem,
points = _.range(edge.points.length).map(function() { return getCoords(sourceElem); });
return createLine(edge, points);
});
var s = svgPathsEnter.append("path")
.attr("class", "path");
var stashed = [];
s.data().map(function(e) {
var edge = g.edge(e),
sourceElem = g.node(e.v).elem,
points = _.range(edge.points.length).map(function() { return getCoords(sourceElem); });
stashed.push({el: e, edge: edge, points: points});
});
s.attr("d", function(e, i) {
var specs = stashed[i];
if (!specs) {
return;
}
return createLine(specs.edge, specs.points);
});
svgPathsEnter.append("defs");
}

Expand Down
55 changes: 46 additions & 9 deletions lib/create-nodes.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,44 @@ function createNodes(selection, g, shapes) {
.append("g")
.attr("class", "node")
.style("opacity", 0);

// create queue for batch processing
// batch reading from then writing to DOM for increased performance
var itemQueue = [];
var labelQueue = [];

svgNodes.each(function(v) {
var node = g.node(v),
thisGroup = d3.select(this),
labelGroup = thisGroup.append("g").attr("class", "label"),
labelDom = addLabel(labelGroup, node),
shape = shapes[node.shape],
bbox = _.pick(labelDom.node().getBBox(), "width", "height");
label = addLabel.createLabel(labelGroup, node),
labelDom = label.labelSvg;

labelQueue.push(label);

// add to queue for further processing
itemQueue.push({self: this, node: node, thisGroup: thisGroup, labelGroup: labelGroup, labelDom: labelDom});

});

addLabel.styleLabels(labelQueue);

// get bounding box for each label
itemQueue.forEach(function(item) {
item.bbox = _.pick(item.labelDom.node().getBBox(), "width", "height");
});

// apply styles with bbox info
itemQueue.forEach(function(item) {
var node = item.node,
thisGroup = item.thisGroup,
labelGroup = item.labelGroup,
self = item.self,
bbox = item.bbox;

node.elem = this;
var shape = shapes[node.shape];

node.elem = self;

if (node.id) { thisGroup.attr("id", node.id); }
if (node.labelId) { labelGroup.attr("id", node.labelId); }
Expand All @@ -42,12 +71,20 @@ function createNodes(selection, g, shapes) {
((node.paddingLeft - node.paddingRight) / 2) + "," +
((node.paddingTop - node.paddingBottom) / 2) + ")");

var shapeSvg = shape(d3.select(this), bbox, node);
util.applyStyle(shapeSvg, node.style);
item.shapeSvg = shape(d3.select(self), bbox, node);
});

itemQueue.forEach(function(item) {
util.applyStyle(item.shapeSvg, item.node.style);
});

itemQueue.forEach(function(item) {
item.shapeBBox = item.shapeSvg.node().getBBox();
});

var shapeBBox = shapeSvg.node().getBBox();
node.width = shapeBBox.width;
node.height = shapeBBox.height;
itemQueue.forEach(function(item) {
item.node.width = item.shapeBBox.width;
item.node.height = item.shapeBBox.height;
});

util.applyTransition(svgNodes.exit(), g)
Expand Down
32 changes: 28 additions & 4 deletions lib/label/add-label.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@ var addTextLabel = require("./add-text-label"),
addHtmlLabel = require("./add-html-label"),
addSVGLabel = require("./add-svg-label");

module.exports = addLabel;

function addLabel(root, node, location) {
function createLabel(root, node, location) {
var label = node.label;
var labelSvg = root.append("g");

Expand All @@ -18,7 +17,20 @@ function addLabel(root, node, location) {
addTextLabel(labelSvg, node);
}

var labelBBox = labelSvg.node().getBBox();
return {labelSvg: labelSvg, node: node, location: location};

}

function getLabelBBox(item) {
item.labelBBox = item.labelSvg.node().getBBox();
}

function finishStyling(item) {
var node = item.node;
var labelSvg = item.labelSvg;
var labelBBox = item.labelBBox;
var location = item.location;

var y;
switch(location) {
case "top":
Expand All @@ -31,7 +43,19 @@ function addLabel(root, node, location) {
y = (-labelBBox.height / 2);
}
labelSvg.attr("transform",
"translate(" + (-labelBBox.width / 2) + "," + y + ")");
"translate(" + (-labelBBox.width / 2) + "," + y + ")");

return labelSvg;
}

function styleLabels(items) {
items.forEach(getLabelBBox);

return items.map(finishStyling);
}


module.exports.createLabel = createLabel;
module.exports.getLabelBBox = getLabelBBox;
module.exports.finishStyling = finishStyling;
module.exports.styleLabels = styleLabels;
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,5 +55,6 @@
"type": "git",
"url": "https://github.com/dagrejs/dagre-d3.git"
},
"license": "MIT"
"license": "MIT",
"main": "dist/dagre-d3.core.min.js"
}