[READ-ONLY] Mirror of https://github.com/tynanpurdy/real-font-size. Tiny calculator that tells you the real dimensions of text, not its bounding box tynanpurdy.github.io/real-font-size/
0

Configure Feed

Select the types of activity you want to include in your feed.

real-font-size / index.js
5.9 kB 195 lines
1const fontInput = document.getElementById("fontInput"); 2const fontWeightInput = document.getElementById("fontWeightInput"); 3const typeSizeInput = document.getElementById("typeSizeInput"); 4const typeUnitsInput = document.getElementById("typeUnitsInput"); 5const previewText = document.getElementById("previewText"); 6const diagram = document.getElementById("diagram"); 7const testStringInput = document.getElementById("testStringInput"); 8 9class Font { 10 constructor(name = "Arial", weight = 400, size = 12, units = "pt") { 11 (this.name = name), 12 (this.weight = weight), 13 (this.size = size), 14 (this.units = units); 15 } 16 17 get style() { 18 return `${this.weight} ${this.size}${this.units} ${this.name}`; 19 } 20} 21 22previewText.style.font = new Font().style; 23 24// INITIALIZE 25updateFont(); 26 27// FUNCTIONS 28function unitsCorrectedSize(size, units) { 29 if (units === "pt") { 30 return size * (72.0 / 96.0); 31 } 32 return size; 33} 34 35function getRealFontHeightPx(textMetrics) { 36 return ( 37 textMetrics.actualBoundingBoxAscent + textMetrics.actualBoundingBoxDescent 38 ); 39} 40 41function getFontBoundingHeightPx(textMetrics) { 42 return textMetrics.fontBoundingBoxAscent + textMetrics.fontBoundingBoxDescent; 43} 44 45function clearCanvas(canvas) { 46 const ctx = canvas.getContext("2d"); 47 ctx.clearRect(0, 0, canvas.width, canvas.height); 48 return ctx; 49} 50 51function updateFont() { 52 const newFont = getChosenFont(); 53 const testString = getTestString(); 54 console.log("measure updated"); 55 console.log(newFont); 56 console.log(testString); 57 drawDiagram(newFont, testString); 58 previewText.style.font = newFont.style; 59} 60 61function getChosenFont() { 62 return new Font( 63 fontInput.value, 64 fontWeightInput.value, 65 typeSizeInput.value, 66 typeUnitsInput.value 67 ); 68} 69 70function getTestString() { 71 const testString = testStringInput.value; 72 return testString != "" ? testString : "Apd"; 73} 74 75function drawDiagram(font = new Font(), testString = "Apd", canvas = diagram) { 76 const ctx = clearCanvas(canvas); 77 78 // measure the chosen font 79 ctx.font = font.style; 80 const sampleText = testString; 81 const textMetrics = ctx.measureText(sampleText); 82 83 // display the real height 84 const realHeightPx = getRealFontHeightPx(textMetrics); 85 document.getElementById("realHeight").textContent = `${unitsCorrectedSize( 86 realHeightPx, 87 font.units 88 )} ${font.units}`; 89 console.log(textMetrics); 90 91 // create a fixed-size matching diagram font 92 const diagramFont = new Font(font.name, font.weight, 18, "rem"); 93 ctx.font = diagramFont.style; 94 const diagramTextMetrics = ctx.measureText(sampleText); 95 96 // resize canvas to fit diagram text 97 const sampleTextX = 0; 98 const sampleTextY = diagramTextMetrics.fontBoundingBoxAscent; 99 canvas.width = diagramTextMetrics.width; 100 canvas.height = getFontBoundingHeightPx(diagramTextMetrics); 101 102 // draw bounding-box background 103 ctx.beginPath(); 104 ctx.fillStyle = "#282828"; 105 ctx.fillRect( 106 sampleTextX, 107 0, 108 diagramTextMetrics.width, 109 diagramTextMetrics.fontBoundingBoxAscent + 110 diagramTextMetrics.fontBoundingBoxDescent 111 ); 112 ctx.stroke(); 113 114 // draw diagram text 115 ctx.font = diagramFont.style; 116 ctx.fillStyle = "white"; 117 ctx.fillText(sampleText, sampleTextX, sampleTextY); 118 119 const baselinesAboveAlphabetic = ["actualBoundingBoxAscent"]; 120 const baselinesBelowAlphabetic = ["actualBoundingBoxDescent"]; 121 const baselines = [...baselinesAboveAlphabetic, ...baselinesBelowAlphabetic]; 122 ctx.strokeStyle = "red"; 123 124 baselines.forEach((baseline) => { 125 const y = sampleTextY; 126 ctx.beginPath(); 127 128 const baselineMetricValue = diagramTextMetrics[baseline]; 129 if (baselineMetricValue === undefined) { 130 return; 131 } 132 133 const lineY = baselinesBelowAlphabetic.includes(baseline) 134 ? y + Math.abs(baselineMetricValue) 135 : y - Math.abs(baselineMetricValue); 136 ctx.moveTo(sampleTextX, lineY); 137 ctx.lineTo(sampleTextX + diagramTextMetrics.width, lineY); 138 ctx.stroke(); 139 }); 140} 141 142// EVENT HANDLERS 143typeInputs.addEventListener("change", updateFont); 144 145testStringInput.addEventListener("input", updateFont); 146 147document 148 .getElementById("copyButton") 149 .addEventListener("click", async function () { 150 try { 151 const realHeight = document.getElementById("realHeight").textContent; 152 153 // Use the Clipboard API to copy the text 154 await navigator.clipboard.writeText(realHeight); 155 156 // signify value has been copied via button content 157 let originalText = this.textContent; 158 this.textContent = "✅"; 159 setTimeout( 160 function () { 161 this.textContent = originalText; 162 }.bind(this), 163 1500 164 ); 165 } catch (err) { 166 console.error("Failed to copy: ", err); 167 } 168 }); 169 170document.getElementById("launchFonts").addEventListener("click", () => { 171 if (navigator.userAgent.toUpperCase().indexOf("MAC") >= 0) { 172 window.open("fontbook://"); 173 } else if (navigator.userAgent.toUpperCase().indexOf("WIN") >= 0) { 174 window.open("ms-settings:fonts"); 175 } else if (navigator.userAgent.includes("Linux")) { 176 alert( 177 "I'm a novice programmer, ok? You chose linux and you knew the consequences when you did so. I have no clue how to open your font manager, if you even bothered to install one. Your fonts are in a folder somewhere, or three, I have no idea. Have fun searching, I believe in you." 178 ); 179 } else if (navigator.userAgent.includes("Android")) { 180 alert( 181 "Font management is not available on Android. I don't make the rules. You can yell at Sundar Pichai if you want." 182 ); 183 } else if ( 184 navigator.userAgent.includes("iPhone") || 185 navigator.userAgent.includes("iPad") 186 ) { 187 alert( 188 "Font management is not available on iOS. I don't make the rules. You can yell at Tim Apple if you want." 189 ); 190 } else { 191 alert( 192 "Whatever OS you're running is not easily identified by my simple if statements. Good on you. As for your fonts, I have no clue where they are." 193 ); 194 } 195});