const resultContainer = document.querySelector("#slide-container");
const chosenText = document.querySelector("#ChosenText");
const chosenFont = document.querySelector("#ChosenFont");
const textOnPicture = document.querySelector(".textOnPicture");
function refreshPicture() {
textOnPicture.textContent = chosenText.value;
textFit(resultContainer);
}
function reloadPicture(manualChoose) { //function is called by pressing "Reload" button
changeFontFamily(manualChoose); //here is the thing, I want to change font family
refreshPicture();
}
function changeFontFamily(manualChoose) {
let fontFamily;
if (!!manualChoose) {//when triggered by changing value of input
fontFamily = chosenFont.value;
textOnPicture.style.setProperty("--font-family", fontFamily); //in css this property is obviously assigned to font-family of textOnPicture
textFit(resultContainer);
} else {//when triggered by "Reload" button, then random picture, font and color are chosen
fontFamily = fonts[Math.floor(Math.random() * fonts.length)].name;//random font from an array where I have all of my fonts
textOnPicture.style.setProperty("--font-family", fontFamily);
chosenFont.value = fontFamily;
}
}
function resizePicture() {
resultContainer.style.height = resultContainer.offsetWidth * (screen.height / screen.width) + "px";
}
window.onresize = (e) => {
resizePicture();
textFit(resultContainer);
};
(async () => {
resizePicture();
})();
.textOnPicture {
font-family: var(--font-family);
text-align: center;
position: absolute;
padding: 0.2em;
}
#slide-container {
width: 100%;
background-color: red;
background-size: cover;
background-position: center;
display: flex;
justify-content: center;
align-items: center;
position: relative;
margin-top: 40px;
}
<link href="https://fonts.googleapis.com/css2?family=Amita:wght@400;700&family=Averia+Serif+Libre:ital,wght@0,300;0,400;0,700;1,300;1,400;1,700&family=Madimi+One&family=Underdog&family=VT323&family=Victor+Mono:ital,wght@0,100..700;1,100..700&family=Ysabeau+SC:[email protected]&display=swap" rel="stylesheet">
<input type="text" id="ChosenText" autocomplete="off" placeholder="Type text here" oninput="refreshPicture()">
<select id="ChosenFont" onchange="changeFontFamily(true)">
<option value="Amita">Amita</option>
<option value="Averia Serif Libre">Averia Serif Libre</option>
<option value="Victor Mono">Victor Mono</option>
</select>
<div id="slide-container">
<span id="textOnPicture" class="textOnPicture textFitted"></span>
</div>
<script> /*It's textFit from Github, not my own code. I changed here only few settings*/ (function(root, factory) {
"use strict";
// UMD shim
if (typeof define === "function" && define.amd) {
// AMD
define([], factory);
} else if (typeof exports === "object") {
// Node/CommonJS
module.exports = factory();
} else {
// Browser
root.textFit = factory();
}
}(typeof global === "object" ? global : this, function () {
"use strict";
var defaultSettings = {
alignVert: false, // if true, textFit will align vertically using css tables
alignHoriz: true, // if true, textFit will set text-align: center
multiLine: true, // if true, textFit will not set white-space: no-wrap
detectMultiLine: true, // disable to turn off automatic multi-line sensing
minFontSize: 6,
maxFontSize: 10000,
reProcess: true, // if true, textFit will re-process already-fit nodes. Set to 'false' for better performance
widthOnly: false, // if true, textFit will fit text to element width, regardless of text height
alignVertWithFlexbox: true, // if true, textFit will use flexbox for vertical alignment
};
return function textFit(els, options) {
if (!options) options = {};
// Extend options.
var settings = {};
for(var key in defaultSettings){
if(options.hasOwnProperty(key)){
settings[key] = options[key];
} else {
settings[key] = defaultSettings[key];
}
}
// Convert jQuery objects into arrays
if (typeof els.toArray === "function") {
els = els.toArray();
}
// Support passing a single el
var elType = Object.prototype.toString.call(els);
if (elType !== '[object Array]' && elType !== '[object NodeList]' &&
elType !== '[object HTMLCollection]'){
els = [els];
}
// Process each el we've passed.
for(var i = 0; i < els.length; i++){
processItem(els[i], settings);
}
};
/**
* The meat. Given an el, make the text inside it fit its parent.
* @param {DOMElement} el Child el.
* @param {Object} settings Options for fit.
*/
function processItem(el, settings){
if (!isElement(el) || (!settings.reProcess && el.getAttribute('textFitted'))) {
return false;
}
// Set textFitted attribute so we know this was processed.
if(!settings.reProcess){
el.setAttribute('textFitted', 1);
}
var innerSpan, originalHeight, originalHTML, originalWidth;
var low, mid, high;
// Get element data.
originalHTML = el.innerHTML;
originalWidth = innerWidth(el);
originalHeight = innerHeight(el);
// Don't process if we can't find box dimensions
if (!originalWidth || (!settings.widthOnly && !originalHeight)) {
if(!settings.widthOnly)
throw new Error('Set a static height and width on the target element ' + el.outerHTML +
' before using textFit!');
else
throw new Error('Set a static width on the target element ' + el.outerHTML +
' before using textFit!');
}
// Add textFitted span inside this container.
if (originalHTML.indexOf('textFitted') === -1) {
innerSpan = document.createElement('span');
innerSpan.className = 'textFitted';
// Inline block ensure it takes on the size of its contents, even if they are enclosed
// in other tags like <p>
innerSpan.style['display'] = 'inline-block';
innerSpan.innerHTML = originalHTML;
el.innerHTML = '';
el.appendChild(innerSpan);
} else {
// Reprocessing.
innerSpan = el.querySelector('span.textFitted');
// Remove vertical align if we're reprocessing.
if (hasClass(innerSpan, 'textFitAlignVert')){
innerSpan.className = innerSpan.className.replace('textFitAlignVert', '');
innerSpan.style['height'] = '';
el.className.replace('textFitAlignVertFlex', '');
}
}
// Prepare & set alignment
if (settings.alignHoriz) {
el.style['text-align'] = 'center';
innerSpan.style['text-align'] = 'center';
}
// Check if this string is multiple lines
// Not guaranteed to always work if you use wonky line-heights
var multiLine = settings.multiLine;
if (settings.detectMultiLine && !multiLine &&
innerSpan.getBoundingClientRect().height >= parseInt(window.getComputedStyle(innerSpan)['font-size'], 10) * 2){
multiLine = true;
}
// If we're not treating this as a multiline string, don't let it wrap.
if (!multiLine) {
el.style['white-space'] = 'nowrap';
}
low = settings.minFontSize;
high = settings.maxFontSize;
// Binary search for highest best fit
var size = low;
while (low <= high) {
mid = (high + low) >> 1;
innerSpan.style.fontSize = mid + 'px';
var innerSpanBoundingClientRect = innerSpan.getBoundingClientRect();
if (
innerSpanBoundingClientRect.width <= originalWidth
&& (settings.widthOnly || innerSpanBoundingClientRect.height <= originalHeight)
) {
size = mid;
low = mid + 1;
} else {
high = mid - 1;
}
// await injection point
}
// found, updating font if differs:
if( innerSpan.style.fontSize != size + 'px' ) innerSpan.style.fontSize = size + 'px';
// Our height is finalized. If we are aligning vertically, set that up.
if (settings.alignVert) {
addStyleSheet();
var height = innerSpan.scrollHeight;
if (window.getComputedStyle(el)['position'] === "static"){
el.style['position'] = 'relative';
}
if (!hasClass(innerSpan, "textFitAlignVert")){
innerSpan.className = innerSpan.className + " textFitAlignVert";
}
innerSpan.style['height'] = height + "px";
if (settings.alignVertWithFlexbox && !hasClass(el, "textFitAlignVertFlex")) {
el.className = el.className + " textFitAlignVertFlex";
}
}
}
// Calculate height without padding.
function innerHeight(el){
var style = window.getComputedStyle(el, null);
return el.getBoundingClientRect().height -
parseInt(style.getPropertyValue('padding-top'), 10) -
parseInt(style.getPropertyValue('padding-bottom'), 10);
}
// Calculate width without padding.
function innerWidth(el){
var style = window.getComputedStyle(el, null);
return el.getBoundingClientRect().width -
parseInt(style.getPropertyValue('padding-left'), 10) -
parseInt(style.getPropertyValue('padding-right'), 10);
}
//Returns true if it is a DOM element
function isElement(o){
return (
typeof HTMLElement === "object" ? o instanceof HTMLElement : //DOM2
o && typeof o === "object" && o !== null && o.nodeType === 1 && typeof o.nodeName==="string"
);
}
function hasClass(element, cls) {
return (' ' + element.className + ' ').indexOf(' ' + cls + ' ') > -1;
}
// Better than a stylesheet dependency
function addStyleSheet() {
if (document.getElementById("textFitStyleSheet")) return;
var style = [
".textFitAlignVert{",
"position: absolute;",
"top: 0; right: 0; bottom: 0; left: 0;",
"margin: auto;",
"display: flex;",
"justify-content: center;",
"flex-direction: column;",
"}",
".textFitAlignVertFlex{",
"display: flex;",
"}",
".textFitAlignVertFlex .textFitAlignVert{",
"position: static;",
"}",].join("");
var css = document.createElement("style");
css.type = "text/css";
css.id = "textFitStyleSheet";
css.innerHTML = style;
document.body.appendChild(css);
}
}));</script>