svg-text-fit
Version:
SVG utility for fitting text inside a box by resizing or ellipsis
80 lines (72 loc) • 2.58 kB
JavaScript
import Kapsule from 'kapsule';
function _arrayLikeToArray(r, a) {
(null == a || a > r.length) && (a = r.length);
for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e];
return n;
}
function _arrayWithoutHoles(r) {
if (Array.isArray(r)) return _arrayLikeToArray(r);
}
function _iterableToArray(r) {
if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r);
}
function _nonIterableSpread() {
throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
function _toConsumableArray(r) {
return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread();
}
function _unsupportedIterableToArray(r, a) {
if (r) {
if ("string" == typeof r) return _arrayLikeToArray(r, a);
var t = {}.toString.call(r).slice(8, -1);
return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0;
}
}
var fitToBox = Kapsule({
props: {
bbox: {
"default": {
width: null,
height: null
}
},
passes: {
"default": 3
}
},
init: function init(el, state) {
state.el = el;
},
update: function update(state) {
_toConsumableArray(Array(state.passes).keys()).some(function () {
var startSize = parseInt(state.el.style['font-size'].split('px')[0]) || 20;
var bbox = state.el.getBBox();
var newSize = Math.floor(startSize * Math.min(state.bbox.width / bbox.width, state.bbox.height / bbox.height));
if (newSize === startSize) return true; // Shortcut out
state.el.style['font-size'] = newSize + 'px';
});
}
});
var ellipsis = Kapsule({
props: {
maxWidth: {
"default": Infinity
}
},
init: function init(el, state) {
state.el = el;
},
update: function update(state) {
var origTxt = state.el.textContent;
var nChars = Math.round(origTxt.length * state.maxWidth / state.el.getBBox().width * 1.2); // Start above
while (--nChars && state.maxWidth / state.el.getBBox().width < 1) {
state.el.textContent = abbreviateText(origTxt, nChars);
}
//
function abbreviateText(txt, maxChars) {
return txt.length <= maxChars ? txt : txt.substring(0, maxChars * 2 / 3) + '...' + txt.substring(txt.length - maxChars / 3, txt.length);
}
}
});
export { ellipsis, fitToBox };