Skip to content

Commit ea883e6

Browse files
committed
cache bounding boxes by node contents instead of by data-bb attr
means we get a lot more caching, and a lot less DOM manipulation and getBoundingClientRect
1 parent b9c33c9 commit ea883e6

File tree

4 files changed

+34
-18
lines changed

4 files changed

+34
-18
lines changed

src/components/drawing/index.js

+34-12
Original file line numberDiff line numberDiff line change
@@ -610,19 +610,18 @@ drawing.makeTester = function() {
610610
// in a reference frame where it isn't translated and its anchor
611611
// point is at (0,0)
612612
// always returns a copy of the bbox, so the caller can modify it safely
613-
var savedBBoxes = [];
613+
var savedBBoxes = {};
614+
var savedBBoxesCount = 0;
614615
var maxSavedBBoxes = 10000;
615616

616617
drawing.bBox = function(node) {
617618
// cache elements we've already measured so we don't have to
618619
// remeasure the same thing many times
619-
var saveNum = node.attributes['data-bb'];
620-
if(saveNum && saveNum.value) {
621-
return Lib.extendFlat({}, savedBBoxes[saveNum.value]);
622-
}
620+
var hash = nodeHash(node);
621+
var out = savedBBoxes[hash];
622+
if(out) return Lib.extendFlat({}, out);
623623

624-
var tester3 = drawing.tester;
625-
var tester = tester3.node();
624+
var tester = drawing.tester.node();
626625

627626
// copy the node to test into the tester
628627
var testNode = node.cloneNode(true);
@@ -654,18 +653,41 @@ drawing.bBox = function(node) {
654653
// make sure we don't have too many saved boxes,
655654
// or a long session could overload on memory
656655
// by saving boxes for long-gone elements
657-
if(savedBBoxes.length >= maxSavedBBoxes) {
658-
d3.selectAll('[data-bb]').attr('data-bb', null);
659-
savedBBoxes = [];
656+
if(savedBBoxesCount >= maxSavedBBoxes) {
657+
savedBBoxes = {};
658+
maxSavedBBoxes = 0;
660659
}
661660

662661
// cache this bbox
663-
node.setAttribute('data-bb', savedBBoxes.length);
664-
savedBBoxes.push(bb);
662+
savedBBoxes[hash] = bb;
663+
savedBBoxesCount++;
665664

666665
return Lib.extendFlat({}, bb);
667666
};
668667

668+
// capture everything about a node (at least in our usage) that
669+
// impacts its bounding box, given that bBox clears x, y, and transform
670+
// TODO: is this really everything? Is it worth taking only parts of style,
671+
// so we can share across more changes (like colors)? I guess we can't strip
672+
// colors and stuff from inside innerHTML so maybe not worth bothering outside.
673+
// TODO # 2: this can be long, so could take a lot of memory, do we want to
674+
// hash it? But that can be slow...
675+
// extracting this string from a typical element takes ~3 microsec, where
676+
// doing a simple hash ala https://stackoverflow.com/questions/7616461
677+
// adds ~15 microsec (nearly all of this is spent in charCodeAt)
678+
// function hash(s) {
679+
// var h = 0;
680+
// for (var i = 0; i < s.length; i++) {
681+
// h = (((h << 5) - h) + s.charCodeAt(i)) | 0; // codePointAt?
682+
// }
683+
// return h;
684+
// }
685+
function nodeHash(node) {
686+
return node.innerHTML +
687+
node.getAttribute('text-anchor') +
688+
node.getAttribute('style');
689+
}
690+
669691
/*
670692
* make a robust clipPath url from a local id
671693
* note! We'd better not be exporting from a page

src/lib/svg_text_utils.js

-3
Original file line numberDiff line numberDiff line change
@@ -94,9 +94,6 @@ exports.convertToTspans = function(_context, gd, _callback) {
9494
parent.selectAll('svg.' + svgClass).remove();
9595
parent.selectAll('g.' + svgClass + '-group').remove();
9696
_context.style({visibility: null});
97-
for(var up = _context.node(); up && up.removeAttribute; up = up.parentNode) {
98-
up.removeAttribute('data-bb');
99-
}
10097

10198
function showText() {
10299
if(!parent.empty()) {

src/traces/bar/plot.js

-1
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,6 @@ function appendBarText(gd, bar, calcTrace, i, x0, x1, y0, y1) {
146146
.attr({
147147
'class': 'bartext',
148148
transform: '',
149-
'data-bb': '',
150149
'text-anchor': 'middle',
151150
x: 0,
152151
y: 0

src/traces/pie/plot.js

-2
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,6 @@ module.exports = function plot(gd, cdpie) {
251251
.attr({
252252
'class': 'slicetext',
253253
transform: '',
254-
'data-bb': '',
255254
'text-anchor': 'middle',
256255
x: 0,
257256
y: 0
@@ -274,7 +273,6 @@ module.exports = function plot(gd, cdpie) {
274273
sliceText.call(Drawing.font, trace.outsidetextfont);
275274
if(trace.outsidetextfont.family !== trace.insidetextfont.family ||
276275
trace.outsidetextfont.size !== trace.insidetextfont.size) {
277-
sliceText.attr({'data-bb': ''});
278276
textBB = Drawing.bBox(sliceText.node());
279277
}
280278
transform = transformOutsideText(textBB, pt);

0 commit comments

Comments
 (0)