raphael
raphael copied to clipboard
Solution to: getBBox NaN or Infinity
getBBox on a set will return Infinity and -Infinity for all of the bbox values. If done on one with a child set that is empty it would return NaN.
And this can also happen for a set with hidden elements. (We should probably also take their bboxs into consideration. Being able to pass an argument to also include hidden bounding boxes would be a good idea)
Returning a NaN or Infinity or -Infinity can be troublesome. The width and height calculation needs an isFinite check.
Basic code example of issue
Math.min.apply(0, [])
Would show Infinity.
Infinity - Infinity is a problem just like -Infinity - -Infinity would be a problem both result in NaN.
But then when calculating the width/height we need to do this
Raphael.st.getBBox = function () {
var x = [],
y = [],
x2 = [],
y2 = [];
for (var i = this.items.length; i--;) if (!this.items[i].removed) {
var box = this.items[i].getBBox();
x.push(box.x);
y.push(box.y);
x2.push(box.x + box.width);
y2.push(box.y + box.height);
}
x = mmin[apply](0, x);
y = mmin[apply](0, y);
x2 = mmax[apply](0, x2);
y2 = mmax[apply](0, y2);
return {
x: x,
y: y,
x2: x2,
y2: y2,
width: isFinite(x2) && isFinite(x) ? x2 - x : 0,
height: isFinite(y2) && isFinite(y) ? y2 - y : 0
};
};
See the isFinite checks if both dimension parts are finite then its fine to use them to calculate a dimension size. Otherwise we should just return a dimension size of 0 because its sane, we cant draw to infinity on a finite system and infinite width or height has no use?.
An update for IE 9, 10, 11 as they do not let you over write the returned object from this.node.getBBox(); Also works as an extension too Raphael :)
Raphael.el.origional_getBBox = Raphael.el._getBBox;
Raphael.el._getBBox = function () {
if (this.node.style.display == "none") {
this.show();
var hide = true;
}
var bbox = {};
try {
// Copy the objects values because IE does not like you writing too them.
var tmp = this.node.getBBox();
bbox.x = tmp.x;
bbox.y = tmp.y;
bbox.width = tmp.width;
bbox.height = tmp.height;
} catch(e) {
// Firefox 3.0.x plays badly here
} finally {
bbox = bbox || {};
// does not take rotation into consideration
if (bbox.x === 0 && this.attrs.x !== 0) {
bbox.x = this.attrs.x;
}
if (bbox.y === 0 && this.attrs.y !== 0) {
bbox.y = this.attrs.y;
}
}
hide && this.hide();
return bbox;
};