Czy w javascript jest sposób na uzyskanie nazw wszystkich czcionek (lub rodzin czcionek), które może wyświetlić przeglądarka? (Chcę udostępnić użytkownikowi listę rozwijaną z listą wszystkich dostępnych czcionek i pozwolić użytkownikowi wybrać czcionkę.) Wolałbym nie musieć zakodować tej listy na stałe z wyprzedzeniem ani wysyłać jej z serwera. (Intuicyjnie wydaje się, że przeglądarka powinna wiedzieć, jakie ma czcionki i powinno to jakoś zostać ujawnione w javascript).
źródło
Tak jest! Tak się cieszę, że zadałeś to pytanie, ponieważ teraz chcę też tego użyć.
+1 na pytanie, a oto Twoja odpowiedź :)
http://www.lalit.org/lab/javascript-css-font-detect
Kod z http://www.lalit.org/wordpress/wp-content/uploads/2008/05/fontdetect.js?ver=0.3
/** * JavaScript code to detect available availability of a * particular font in a browser using JavaScript and CSS. * * Author : Lalit Patel * Website: http://www.lalit.org/lab/javascript-css-font-detect/ * License: Apache Software License 2.0 * http://www.apache.org/licenses/LICENSE-2.0 * Version: 0.15 (21 Sep 2009) * Changed comparision font to default from sans-default-default, * as in FF3.0 font of child element didn't fallback * to parent element if the font is missing. * Version: 0.2 (04 Mar 2012) * Comparing font against all the 3 generic font families ie, * 'monospace', 'sans-serif' and 'sans'. If it doesn't match all 3 * then that font is 100% not available in the system * Version: 0.3 (24 Mar 2012) * Replaced sans with serif in the list of baseFonts */ /** * Usage: d = new Detector(); * d.detect('font name'); */ var Detector = function() { // a font will be compared against all the three default fonts. // and if it doesn't match all 3 then that font is not available. var baseFonts = ['monospace', 'sans-serif', 'serif']; //we use m or w because these two characters take up the maximum width. // And we use a LLi so that the same matching fonts can get separated var testString = "mmmmmmmmmmlli"; //we test using 72px font size, we may use any size. I guess larger the better. var testSize = '72px'; var h = document.getElementsByTagName("body")[0]; // create a SPAN in the document to get the width of the text we use to test var s = document.createElement("span"); s.style.fontSize = testSize; s.innerHTML = testString; var defaultWidth = {}; var defaultHeight = {}; for (var index in baseFonts) { //get the default width for the three base fonts s.style.fontFamily = baseFonts[index]; h.appendChild(s); defaultWidth[baseFonts[index]] = s.offsetWidth; //width for the default font defaultHeight[baseFonts[index]] = s.offsetHeight; //height for the defualt font h.removeChild(s); } function detect(font) { var detected = false; for (var index in baseFonts) { s.style.fontFamily = font + ',' + baseFonts[index]; // name of the font along with the base font for fallback. h.appendChild(s); var matched = (s.offsetWidth != defaultWidth[baseFonts[index]] || s.offsetHeight != defaultHeight[baseFonts[index]]); h.removeChild(s); detected = detected || matched; } return detected; } this.detect = detect; };
Podsumowanie
źródło
Można to zrobić za pomocą
document.fonts
Zwracana wartość to interfejs FontFaceSet dokumentu. Interfejs FontFaceSet jest przydatny do ładowania nowych czcionek, sprawdzania stanu wcześniej załadowanych czcionek itp.
function listFonts() { let { fonts } = document; const it = fonts.entries(); let arr = []; let done = false; while (!done) { const font = it.next(); if (!font.done) { arr.push(font.value[0]); } else { done = font.done; } } return arr; }
function listFonts() { let { fonts } = document; const it = fonts.entries(); let arr = []; let done = false; while (!done) { const font = it.next(); if (!font.done) { arr.push(font.value[0].family); } else { done = font.done; } } // converted to set then arr to filter repetitive values return [...new Set(arr)]; }
Przetestowałem to bez łączenia żadnych czcionek w HTML, następnie podłączyłem czcionkę Roboto, przetestowałem ponownie i został dodany do wyniku.
źródło
Rozwiązanie FontFaceSet.check ()
Lista czcionek systemu Windows 10
'Arial', 'Arial Black', 'Bahnschrift', 'Calibri', 'Cambria', 'Cambria Math', 'Candara', 'Comic Sans MS', 'Consolas', 'Constantia', 'Corbel', 'Courier New', 'Ebrima', 'Franklin Gothic Medium', 'Gabriola', 'Gadugi', 'Georgia', 'HoloLens MDL2 Assets', 'Impact', 'Ink Free', 'Javanese Text', 'Leelawadee UI', 'Lucida Console', 'Lucida Sans Unicode', 'Malgun Gothic', 'Marlett', 'Microsoft Himalaya', 'Microsoft JhengHei', 'Microsoft New Tai Lue', 'Microsoft PhagsPa', 'Microsoft Sans Serif', 'Microsoft Tai Le', 'Microsoft YaHei', 'Microsoft Yi Baiti', 'MingLiU-ExtB', 'Mongolian Baiti', 'MS Gothic', 'MV Boli', 'Myanmar Text', 'Nirmala UI', 'Palatino Linotype', 'Segoe MDL2 Assets', 'Segoe Print', 'Segoe Script', 'Segoe UI', 'Segoe UI Historic', 'Segoe UI Emoji', 'Segoe UI Symbol', 'SimSun', 'Sitka', 'Sylfaen', 'Symbol', 'Tahoma', 'Times New Roman', 'Trebuchet MS', 'Verdana', 'Webdings', 'Wingdings', 'Yu Gothic',
Lista czcionek macOS / iOS
'American Typewriter', 'Andale Mono', 'Arial', 'Arial Black', 'Arial Narrow', 'Arial Rounded MT Bold', 'Arial Unicode MS', 'Avenir', 'Avenir Next', 'Avenir Next Condensed', 'Baskerville', 'Big Caslon', 'Bodoni 72', 'Bodoni 72 Oldstyle', 'Bodoni 72 Smallcaps', 'Bradley Hand', 'Brush Script MT', 'Chalkboard', 'Chalkboard SE', 'Chalkduster', 'Charter', 'Cochin', 'Comic Sans MS', 'Copperplate', 'Courier', 'Courier New', 'Didot', 'DIN Alternate', 'DIN Condensed', 'Futura', 'Geneva', 'Georgia', 'Gill Sans', 'Helvetica', 'Helvetica Neue', 'Herculanum', 'Hoefler Text', 'Impact', 'Lucida Grande', 'Luminari', 'Marker Felt', 'Menlo', 'Microsoft Sans Serif', 'Monaco', 'Noteworthy', 'Optima', 'Palatino', 'Papyrus', 'Phosphate', 'Rockwell', 'Savoye LET', 'SignPainter', 'Skia', 'Snell Roundhand', 'Tahoma', 'Times', 'Times New Roman', 'Trattatello', 'Trebuchet MS', 'Verdana', 'Zapfino',
FontFaceSet.check ()
const fontCheck = new Set([ // Windows 10 'Arial', 'Arial Black', 'Bahnschrift', 'Calibri', 'Cambria', 'Cambria Math', 'Candara', 'Comic Sans MS', 'Consolas', 'Constantia', 'Corbel', 'Courier New', 'Ebrima', 'Franklin Gothic Medium', 'Gabriola', 'Gadugi', 'Georgia', 'HoloLens MDL2 Assets', 'Impact', 'Ink Free', 'Javanese Text', 'Leelawadee UI', 'Lucida Console', 'Lucida Sans Unicode', 'Malgun Gothic', 'Marlett', 'Microsoft Himalaya', 'Microsoft JhengHei', 'Microsoft New Tai Lue', 'Microsoft PhagsPa', 'Microsoft Sans Serif', 'Microsoft Tai Le', 'Microsoft YaHei', 'Microsoft Yi Baiti', 'MingLiU-ExtB', 'Mongolian Baiti', 'MS Gothic', 'MV Boli', 'Myanmar Text', 'Nirmala UI', 'Palatino Linotype', 'Segoe MDL2 Assets', 'Segoe Print', 'Segoe Script', 'Segoe UI', 'Segoe UI Historic', 'Segoe UI Emoji', 'Segoe UI Symbol', 'SimSun', 'Sitka', 'Sylfaen', 'Symbol', 'Tahoma', 'Times New Roman', 'Trebuchet MS', 'Verdana', 'Webdings', 'Wingdings', 'Yu Gothic', // macOS 'American Typewriter', 'Andale Mono', 'Arial', 'Arial Black', 'Arial Narrow', 'Arial Rounded MT Bold', 'Arial Unicode MS', 'Avenir', 'Avenir Next', 'Avenir Next Condensed', 'Baskerville', 'Big Caslon', 'Bodoni 72', 'Bodoni 72 Oldstyle', 'Bodoni 72 Smallcaps', 'Bradley Hand', 'Brush Script MT', 'Chalkboard', 'Chalkboard SE', 'Chalkduster', 'Charter', 'Cochin', 'Comic Sans MS', 'Copperplate', 'Courier', 'Courier New', 'Didot', 'DIN Alternate', 'DIN Condensed', 'Futura', 'Geneva', 'Georgia', 'Gill Sans', 'Helvetica', 'Helvetica Neue', 'Herculanum', 'Hoefler Text', 'Impact', 'Lucida Grande', 'Luminari', 'Marker Felt', 'Menlo', 'Microsoft Sans Serif', 'Monaco', 'Noteworthy', 'Optima', 'Palatino', 'Papyrus', 'Phosphate', 'Rockwell', 'Savoye LET', 'SignPainter', 'Skia', 'Snell Roundhand', 'Tahoma', 'Times', 'Times New Roman', 'Trattatello', 'Trebuchet MS', 'Verdana', 'Zapfino', ].sort()); (async() => { await document.fonts.ready; const fontAvailable = new Set(); for (const font of fontCheck.values()) { if (document.fonts.check(`12px "${font}"`)) { fontAvailable.add(font); } } console.log('Available Fonts:', [...fontAvailable.values()]); })();
źródło
<SCRIPT> function getFonts() { var nFontLen = dlgHelper.fonts.count; var rgFonts = new Array(); for ( var i = 1; i < nFontLen + 1; i++ ) rgFonts[i] = dlgHelper.fonts(i); rgFonts.sort(); for ( var j = 0; j < nFontLen; j++ ) document.write( rgFonts[j] + "<BR>" ); } </SCRIPT> <BODY onload="getFonts()"> <OBJECT id=dlgHelper CLASSID="clsid:3050f819-98b5-11cf-bb82-00aa00bdce0b" width="0px" height="0px"> </OBJECT>
źródło
Dodałem dwie metody do detektora Lalit Patel powyżej:
Dzięki temu możesz:
fonts = [ 'Arial', 'Arial Black', { family: 'Lato', stylesheetUrl: 'https://fonts.googleapis.com/css?family=Lato'}, 'Leelawadee UI'] (new FontDetector()).addFontsArr(fonts);
kod:
/** * JavaScript code to detect available availability of a * particular font in a browser using JavaScript and CSS. * * Author : Lalit Patel * Website: http://www.lalit.org/lab/javascript-css-font-detect/ * License: Apache Software License 2.0 * http://www.apache.org/licenses/LICENSE-2.0 * Version: 0.15 (21 Sep 2009) * Changed comparision font to default from sans-default-default, * as in FF3.0 font of child element didn't fallback * to parent element if the font is missing. * Version: 0.2 (04 Mar 2012) * Comparing font against all the 3 generic font families ie, * 'monospace', 'sans-serif' and 'sans'. If it doesn't match all 3 * then that font is 100% not available in the system * Version: 0.3 (24 Mar 2012) * Replaced sans with serif in the list of baseFonts */ /** * Usage: d = new Detector(); * d.detect('font name'); */ function FontDetector() { this.detect = detect; this.addFont = addFont; this.addFontsArr = addFontsArr; // a font will be compared against all the three default fonts. // and if it doesn't match all 3 then that font is not available. var baseFonts = ['monospace', 'sans-serif', 'serif']; //we use m or w because these two characters take up the maximum width. // And we use a LLi so that the same matching fonts can get separated var testString = "mmmmmmmmmmlli"; //we test using 72px font size, we may use any size. I guess larger the better. var testSize = '72px'; var h = document.getElementsByTagName("body")[0]; // create a SPAN in the document to get the width of the text we use to test var s = document.createElement("span"); s.style.fontSize = testSize; s.innerHTML = testString; var defaultWidth = {}; var defaultHeight = {}; for (var index in baseFonts) { //get the default width for the three base fonts s.style.fontFamily = baseFonts[index]; h.appendChild(s); defaultWidth[baseFonts[index]] = s.offsetWidth; //width for the default font defaultHeight[baseFonts[index]] = s.offsetHeight; //height for the defualt font h.removeChild(s); } function detect(font) { var detected = false; for (var index in baseFonts) { s.style.fontFamily = font + ',' + baseFonts[index]; // name of the font along with the base font for fallback. h.appendChild(s); var matched = (s.offsetWidth != defaultWidth[baseFonts[index]] || s.offsetHeight != defaultHeight[baseFonts[index]]); h.removeChild(s); detected = detected || matched; } return detected; } function addFont(family, stylesheetUrl, ruleString) { if (detect(family)) { //console.log('using internal font '+family); return true; } if (stylesheetUrl) { console.log('added stylesheet '+stylesheetUrl); var head = document.head, link = document.createElement('link'); link.type = 'text/css'; link.rel = 'stylesheet'; link.href = stylesheetUrl; head.appendChild(link); return true; } if (ruleString) { console.log('adding font rule:'+rule); var newStyle = document.createElement('style'); newStyle.appendChild(document.createTextNode(rule)); document.head.appendChild(newStyle); return true; } console.log('could not add font '+family); } function addFontsArr(arr) { arr.forEach(a => typeof a==='string' ? addFont(a) : addFont(a.family, a.stylesheetUrl, a.ruleString)); } };
źródło
Szukając tego, znalazłem również Font.js , który dodaje obiekt Font podobnie jak Image, dzięki czemu można sprawdzić, kiedy czcionka jest rzeczywiście gotowa do użycia. Działa również na czcionkach zainstalowanych / systemowych. Wadą jest IE9 + tylko ze względu na potrzebę
Object.defineProperty
(inne przeglądarki go mają), ale jeśli robisz nowoczesną sieć, wydaje się to jeszcze lepszą opcją. (Niestety, będę musiał odpowiedzieć na powyższe pytanie, przegłosowałem i na razie idę dalej. :))źródło
Krótka odpowiedź brzmi. Niewiele się zmieniło w zakresie wykrywania czcionek w przeglądarkach w 2020 roku, poza tym, że używanie Flasha jest teraz jeszcze gorszym pomysłem .
Obecnie nie ma natywnego systemu przeglądarki, który mógłby „wyświetlić” wszystkie dostępne czcionki. Jednak przeglądarki umożliwiają sprawdzenie, czy czcionka jest załadowana / gotowa za pomocą interfejsu API FontFaceSet . Jest całkiem dobrze obsługiwany w nowoczesnych przeglądarkach.
Ma to na celu pokazanie, czy czcionka internetowa została całkowicie pobrana, ALE będzie działać również w przypadku czcionek systemowych. Problem polega na tym, że musisz podać listę czcionek do sprawdzenia.
Zatem w połączeniu z
user agent
testem (nie zawsze dokładnym) można stworzyć listę typowych czcionek systemowych dla każdego typu urządzenia. Następnie przetestuj te i wszystkie ładowane czcionki internetowe.UWAGA: NIE da ci to pełnej listy dostępnych czcionek, ale możesz sprawdzić czcionki powszechnie instalowane przez produkty MS Office lub Adobe.
źródło
Może można by to zrobić w zupełnie inny sposób, używając arkusza sprites ze znanymi obrazami czcionek dla określonej postaci i porównując to z migawkami elementu płótna, na którym ten sam znak jest rysowany za pomocą tego, co przeglądarka zgłasza jako tę samą czcionkę. Porównanie można wykonać za pomocą czegoś takiego jak resemble.js .
Jest to wolniejsze, ale powinno również pozwolić nam wykryć, kiedy przeglądarka kłamie.
źródło
Niedawno zauważyłem, że jeśli ustawię wartość context.font dla płótna HTML5 na coś nieprawidłowego, na przykład „śmieci”, zmiana zostanie zignorowana przez płótno. Nie wiem, czy to jest specyficzne dla przeglądarki, ale wydaje się, że działa w ten sposób w Chrome. Widziałem również inne posty ( ignorowanie czcionki płótna HTML 5 ), które wskazują, że dzieje się to w innych przeglądarkach.
Następnie można napisać ciąg znaków z wartością domyślną, którą uważam za „10px sans serif” ( https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/font ), ustawić czcionkę do tego, który testujesz, i ponownie napisz ciąg. Jeśli jest taki sam jak pierwszy rysunek, czcionka nie jest dostępna.
źródło