[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.8 kB 182 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// FUNCTIONS 25function unitsCorrectedSize(size, units) { 26 if (units === "pt") { 27 return size * (72.0 / 96.0); 28 } 29 return size; 30} 31 32function getRealFontHeightPx(textMetrics) { 33 return ( 34 textMetrics.actualBoundingBoxAscent + textMetrics.actualBoundingBoxDescent 35 ); 36} 37 38function getFontBoundingHeightPx(textMetrics) { 39 return textMetrics.fontBoundingBoxAscent + textMetrics.fontBoundingBoxDescent; 40} 41 42function clearCanvas(canvas) { 43 const ctx = canvas.getContext("2d"); 44 ctx.clearRect(0, 0, canvas.width, canvas.height); 45 return ctx; 46} 47 48function drawDiagram(font = new Font(), testString = "Apd", canvas = diagram) { 49 const ctx = clearCanvas(canvas); 50 51 // measure the chosen font 52 ctx.font = font.style; 53 const sampleText = testString; 54 const textMetrics = ctx.measureText(sampleText); 55 56 // display the real height 57 const realHeightPx = getRealFontHeightPx(textMetrics); 58 document.getElementById("realHeight").textContent = `${unitsCorrectedSize( 59 realHeightPx, 60 font.units 61 )} ${font.units}`; 62 console.log(textMetrics); 63 64 // create a fixed-size matching diagram font 65 const diagramFont = new Font(font.name, font.weight, 18, "rem"); 66 ctx.font = diagramFont.style; 67 const diagramTextMetrics = ctx.measureText(sampleText); 68 69 // resize canvas to fit diagram text 70 const sampleTextX = 0; 71 const sampleTextY = diagramTextMetrics.fontBoundingBoxAscent; 72 canvas.width = diagramTextMetrics.width; 73 canvas.height = getFontBoundingHeightPx(diagramTextMetrics); 74 75 // draw bounding-box background 76 ctx.beginPath(); 77 ctx.fillStyle = "#282828"; 78 ctx.fillRect( 79 sampleTextX, 80 0, 81 diagramTextMetrics.width, 82 diagramTextMetrics.fontBoundingBoxAscent + 83 diagramTextMetrics.fontBoundingBoxDescent 84 ); 85 ctx.stroke(); 86 87 // draw diagram text 88 ctx.font = diagramFont.style; 89 ctx.fillStyle = "white"; 90 ctx.fillText(sampleText, sampleTextX, sampleTextY); 91 92 const baselinesAboveAlphabetic = ["actualBoundingBoxAscent"]; 93 const baselinesBelowAlphabetic = ["actualBoundingBoxDescent"]; 94 const baselines = [...baselinesAboveAlphabetic, ...baselinesBelowAlphabetic]; 95 ctx.strokeStyle = "red"; 96 97 baselines.forEach((baseline) => { 98 const y = sampleTextY; 99 ctx.beginPath(); 100 101 const baselineMetricValue = diagramTextMetrics[baseline]; 102 if (baselineMetricValue === undefined) { 103 return; 104 } 105 106 const lineY = baselinesBelowAlphabetic.includes(baseline) 107 ? y + Math.abs(baselineMetricValue) 108 : y - Math.abs(baselineMetricValue); 109 ctx.moveTo(sampleTextX, lineY); 110 ctx.lineTo(sampleTextX + diagramTextMetrics.width, lineY); 111 ctx.stroke(); 112 }); 113} 114drawDiagram(); 115 116// EVENT HANDLERS 117typeInputs.addEventListener("change", () => { 118 newFont = new Font(); 119 newFont.name = fontInput.value; 120 newFont.weight = fontWeightInput.value; 121 newFont.size = typeSizeInput.value; 122 newFont.units = typeUnitsInput.value; 123 124 previewText.style.font = newFont.style; 125 drawDiagram(newFont); 126}); 127 128document 129 .getElementById("copyButton") 130 .addEventListener("click", async function () { 131 try { 132 const realHeight = document.getElementById("realHeight").textContent; 133 134 // Use the Clipboard API to copy the text 135 await navigator.clipboard.writeText(realHeight); 136 137 // signify value has been copied via button content 138 let originalText = this.textContent; 139 this.textContent = "✅"; 140 setTimeout( 141 function () { 142 this.textContent = originalText; 143 }.bind(this), 144 1500 145 ); 146 } catch (err) { 147 console.error("Failed to copy: ", err); 148 } 149 }); 150 151testStringInput.addEventListener("change", () => { 152 const testString = this.value.trim() !== "" ? this.value : "Apd"; 153 drawDiagram(); 154 console.log(`new test string: ${testString}`); 155}); 156 157document.getElementById("launchFonts").addEventListener("click", () => { 158 if (navigator.userAgent.toUpperCase().indexOf("MAC") >= 0) { 159 window.open("fontbook://"); 160 } else if (navigator.userAgent.toUpperCase().indexOf("WIN") >= 0) { 161 window.open("ms-settings:fonts"); 162 } else if (navigator.userAgent.includes("Linux")) { 163 alert( 164 "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." 165 ); 166 } else if (navigator.userAgent.includes("Android")) { 167 alert( 168 "Font management is not available on Android. I don't make the rules. You can yell at Sundar Pichai if you want." 169 ); 170 } else if ( 171 navigator.userAgent.includes("iPhone") || 172 navigator.userAgent.includes("iPad") 173 ) { 174 alert( 175 "Font management is not available on iOS. I don't make the rules. You can yell at Tim Apple if you want." 176 ); 177 } else { 178 alert( 179 "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." 180 ); 181 } 182});