forked from sent/waves
139 lines
4.1 KiB
JavaScript
139 lines
4.1 KiB
JavaScript
// jshint bitwise:true, curly:true, eqeqeq:true, forin:true, immed:true, latedef:true, newcap:true, noarg:true, noempty:true, nonew:true, onevar:true, plusplus:true, quotmark:double, strict:true, undef:true, unused:strict, browser: true
|
|
|
|
/* exported FONT_FIT */
|
|
|
|
/// Nathan Rugg (c) 2015
|
|
/// License: MIT (nate.mit-license.org)
|
|
|
|
var FONT_FIT = function create_font_fit(style)
|
|
{
|
|
"use strict";
|
|
|
|
var body = document.body,
|
|
el = document.createElement("fontSizeTester"),
|
|
obj,
|
|
tries;
|
|
|
|
/// Make sure the element won't be visible. Although, since it removes itself immediately, you won't anyway.
|
|
el.style.visibility = "hidden";
|
|
el.style.pointerEvents = "none";
|
|
el.style.display = "inline";
|
|
|
|
if (style) {
|
|
///TODO: Make a more cross browser version.
|
|
Object.keys(style).forEach(function (key)
|
|
{
|
|
el.style[key] = style[key];
|
|
});
|
|
}
|
|
|
|
function get_optimal_size(size, fit_to, unit, careful, dir)
|
|
{
|
|
var actual_w,
|
|
actual_h,
|
|
ratio,
|
|
w_off,
|
|
h_off,
|
|
new_size;
|
|
|
|
el.style.fontSize = size + unit;
|
|
|
|
actual_w = el.offsetWidth;
|
|
actual_h = el.offsetHeight;
|
|
|
|
w_off = actual_w - fit_to.w ;
|
|
h_off = actual_h - fit_to.h;
|
|
|
|
/// Is it just right or is it small enough and it already tried a bigger size?
|
|
if ((w_off === 0 && h_off === 0) || (w_off <= 0 && h_off <= 0 && dir === "smaller")) {
|
|
return size;
|
|
}
|
|
|
|
/// Can we get bigger and need to?
|
|
if (dir !== "smaller" && w_off < 0 && h_off < 0) {
|
|
dir = "bigger";
|
|
/// Is the width the least off?
|
|
if (w_off > h_off) {
|
|
ratio = fit_to.w / actual_w;
|
|
} else {
|
|
ratio = fit_to.h / actual_h;
|
|
}
|
|
} else {
|
|
dir = "smaller";
|
|
/// Is the width the most off?
|
|
if (w_off > h_off) {
|
|
ratio = fit_to.w / actual_w;
|
|
} else {
|
|
ratio = fit_to.h / actual_h;
|
|
}
|
|
}
|
|
|
|
tries += 1;
|
|
if (tries > 100) {
|
|
throw "Can't fit the font!";
|
|
}
|
|
|
|
/// Make sure to round down.
|
|
if (careful) {
|
|
new_size = Math.floor(size * ((ratio + 1) / 2));
|
|
} else {
|
|
new_size = Math.floor(size * ratio);
|
|
}
|
|
|
|
/// Did the size not change?
|
|
if (new_size === size) {
|
|
return size;
|
|
}
|
|
|
|
/// Try again with a different size.
|
|
return get_optimal_size(new_size, fit_to, unit, careful, dir);
|
|
}
|
|
|
|
obj = {
|
|
destory: function destory()
|
|
{
|
|
el = null;
|
|
obj = null;
|
|
},
|
|
fit: function fit(text, fit_to, unit)
|
|
{
|
|
var res;
|
|
|
|
if (!fit_to) {
|
|
fit_to = {w: window.innerWidth * 0.95, h: window.innerHeight * 0.95};
|
|
} else if (isNaN(fit_to.w) || isNaN(fit_to.h)) {
|
|
throw "I need a number to fit the font!";
|
|
}
|
|
if (!unit) {
|
|
unit = "px";
|
|
}
|
|
|
|
///HACK: IE comes out too big. Make it smaller.
|
|
if (/MSIE|Trident/.test(navigator.userAgent)) {
|
|
fit_to = {w: fit_to.w * 0.88, h: fit_to.h * 0.88};
|
|
}
|
|
|
|
el.textContent = text;
|
|
|
|
body.appendChild(el);
|
|
|
|
/// Are there spaces? Text with spaces need to be treated more carefully.
|
|
if (text.indexOf(" ") > -1) {
|
|
tries = 0;
|
|
el.style.whiteSpace = "normal";
|
|
res = get_optimal_size(fit_to.w * text.length, fit_to, unit, true);
|
|
} else {
|
|
tries = 0;
|
|
el.style.whiteSpace = "nowrap"; /// Word wrapping causes unpredictable behavior.
|
|
res = get_optimal_size(Math.floor(fit_to.w / text.length), fit_to, unit);
|
|
}
|
|
|
|
body.removeChild(el);
|
|
|
|
return res;
|
|
}
|
|
};
|
|
|
|
return obj;
|
|
};
|