список всех шрифтов, которые может отображать браузер пользователя
есть ли способ в javascript получить имена всех шрифтов (или семейств шрифтов), которые браузер может показать? (Я хочу дать пользователю выпадающий список со списком всех доступных шрифтов и разрешить пользователю выбрать шрифт.) Я бы предпочел не нужно жестко кодировать этот список заранее или отправить его с сервера. (Интуитивно кажется, что браузер должен знать, какие шрифты у него есть, и это должно быть как-то связано с javascript.)
6 ответов:
версия JavaScript немного шелушится. Он получает шрифты, повторяя известные шрифты и тестирование.
самый точный способ (хотя и должен использовать плагин propriety) - это использовать Flash. Здесь вы можете получить список шрифтов, не проверяя их по отдельности с помощью размеров.
вы будете иметь, чтобы решить, будет ли иметь точный список за счет не работает на некоторых устройствах ( iOS-устройств, браузеров без Flash-плагина, и т. д.), или частичный список с лучшей поддержкой только через JavaScript.
Да есть! Я так рад, что вы задали этот вопрос, потому что теперь я хочу использовать это тоже.
+1 для вопроса, и вот ваш ответ:)
http://www.lalit.org/lab/javascript-css-font-detect
код от 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; };
резюме
Как это работает?
этот код работает по простому принципу, что каждый символ появляется по-разному в разных шрифтах. Так что разные шрифты будут принимать разные ширина и высота для одной и той же строки символов одинакового размера шрифта.
<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>
в моем поиске для этого, я также нашел шрифт.js, который добавляет объект шрифта, похожий на изображение, поэтому можно проверить, когда шрифт действительно готов к использованию. Также работает на установленных / системных шрифтов. Недостатком является IE9+ только из-за необходимости
Object.defineProperty
(другие браузеры имеют его), но если вы делаете современный веб, это кажется еще лучшим вариантом. (Я, к сожалению,должен буду пойти с ответом выше, поддержанным и переходящим сейчас. :))
возможно, это можно было бы сделать совершенно по-другому, используя спрайт-лист с известными изображениями шрифтов для определенного символа и сравнивая его со снимками элемента canvas, на котором один и тот же символ нарисован с тем, что браузер сообщает как один и тот же шрифт. Сравнение может быть сделано с чем-то вроде напоминают.js.
Это медленнее, но также должно позволить нам обнаружить, когда браузер лежит.
я добавил два метода к детектору Лалита Пателя выше:
- addFont (family, stylesheetUrl, ruleString) - > определяет, существует ли шрифт "family", если не добавляет таблицу стилей, загружая шрифт с помощью либо stylesheetUrl, если задано, либо иначе ruleString
- addFontsArr (arr) - > добавляет массив шрифтов
С этим можно сделать:
fonts = [ 'Arial', 'Arial Black', { family: 'Lato', stylesheetUrl: 'https://fonts.googleapis.com/css?family=Lato'}, 'Leelawadee UI'] (new FontDetector()).addFontsArr(fonts);
код:
/** * 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)); } };