src/helpers/d3.dynamicBackground.js
//d3.svg.dynamicBackground
import Class from "base/class";
export default Class.extend({
init(context, conditions) {
this.context = context;
this.context.classed("vzb-dynamic-background", true);
this.width = 0;
this.height = 0;
this.topOffset = 0;
this.leftOffset = 0;
this.bottomOffset = 0;
this.rightOffset = 0;
this.textWidth = 0;
this.textHeight = 0;
this.widthRatio = 0.9;
this.heightRatio = 0.9;
this.xAlign = "center";
this.yAlign = "center";
this.element = this.context.append("text").style("font-size", "20px");
this._sample = this.context.append("text").style("font-size", "20px").style("opacity", 0);
if (conditions) {
this.setConditions(conditions);
}
},
setConditions(conditions) {
if (!isNaN(parseFloat(conditions.rightOffset)) && isFinite(conditions.rightOffset)) {
this.rightOffset = conditions.rightOffset;
}
if (!isNaN(parseFloat(conditions.leftOffset)) && isFinite(conditions.leftOffset)) {
this.leftOffset = conditions.leftOffset;
}
if (!isNaN(parseFloat(conditions.topOffset)) && isFinite(conditions.topOffset)) {
this.topOffset = conditions.topOffset;
}
if (!isNaN(parseFloat(conditions.bottomOffset)) && isFinite(conditions.bottomOffset)) {
this.bottomOffset = conditions.bottomOffset;
}
if (conditions.xAlign) {
this.xAlign = conditions.xAlign;
}
if (conditions.yAlign) {
this.yAlign = conditions.yAlign;
}
if (!isNaN(parseFloat(conditions.widthRatio)) && conditions.widthRatio > 0 && conditions.widthRatio <= 1) {
this.widthRatio = conditions.widthRatio;
}
if (!isNaN(parseFloat(conditions.heightRatio)) && conditions.heightRatio > 0 && conditions.heightRatio <= 1) {
this.heightRatio = conditions.heightRatio;
}
return this;
},
resize(width, height, topOffset, leftOffset) {
this.width = parseInt(width, 10) || 0;
this.height = parseInt(height, 10) || 0;
if (topOffset) {
this.topOffset = topOffset;
}
if (leftOffset) {
this.leftOffset = leftOffset;
}
this._resizeText();
},
setText(text, delay = 0) {
const callback = () => {
this._sample.text(text);
this._resizeText();
this.element.text(text);
};
const clear = () => {
clearTimeout(this._text.timeout);
delete this._text;
};
if (!delay) {
if (this._text) {
clear();
}
callback();
} else {
if (this._text) {
this._text.callback();
clear();
}
this._text = {
callback,
timeout: setTimeout(() => {
callback();
clear();
}, delay)
};
}
return this;
},
_resizeText() {
const bbox = this._sample.node().getBBox();
if (!bbox.width || !bbox.height || !this.width || !this.height) return this;
// method from http://stackoverflow.com/a/22580176
const widthTransform = this.width * this.widthRatio / bbox.width;
const heightTransform = this.height * this.heightRatio / bbox.height;
this.scalar = Math.min(widthTransform, heightTransform);
this.element.attr("transform", "scale(" + this.scalar + ")");
this.textHeight = bbox.height * this.scalar;
this.textWidth = bbox.width * this.scalar;
switch (this.yAlign) {
case "bottom": this.context.select("text").attr("dy", ".325em"); break;
case "center": this.context.select("text").attr("dy", ".325em"); break;
case "top": this.context.select("text").attr("dy", "0"); break;
}
this.context.attr("transform", "translate(" + this._getLeftOffset() + "," + this._getTopOffset() + ")");
return this;
},
_getLeftOffset() {
switch (this.xAlign) {
case "right":
return this.width - this.textWidth / 2 - this.rightOffset;
case "left":
return this.textWidth / 2 + this.leftOffset;
default :
return this.width / 2;
}
},
_getTopOffset() {
switch (this.yAlign) {
case "top":
return this.textHeight / 2 + this.topOffset;
case "bottom":
return this.height - this.textHeight / 2 - this.bottomOffset;
default :
return this.height / 2;
}
}
});