liệt kê mọi phông chữ mà trình duyệt của người dùng có thể hiển thị


105

Có cách nào trong javascript để lấy tên của tất cả các phông chữ (hoặc họ phông chữ) mà trình duyệt có thể hiển thị không? (Tôi muốn cung cấp cho người dùng một danh sách thả xuống với danh sách tất cả các phông chữ có sẵn và cho phép người dùng chọn một phông chữ.) Tôi không muốn phải mã hóa danh sách này trước hoặc gửi nó xuống từ máy chủ. (Theo trực giác, có vẻ như trình duyệt nên biết nó có những phông chữ nào và điều này sẽ được tiếp xúc với javascript bằng cách nào đó.)

Câu trả lời:


38

Phiên bản JavaScript có một chút lỗi. Nó lấy các phông chữ bằng cách lặp lại các phông chữ đã biết và thử nghiệm.

Cách chính xác nhất (mặc dù phải sử dụng một plugin phù hợp) là sử dụng Flash . Tại đây, bạn có thể nhận được danh sách các phông chữ mà không cần phải kiểm tra chúng riêng lẻ bằng cách sử dụng các kích thước.

Bạn sẽ phải quyết định có một danh sách chính xác với chi phí không hoạt động trên một số thiết bị (iDevices, trình duyệt không có plugin Flash, v.v.) hay một danh sách chỉ hỗ trợ tốt hơn qua JavaScript .


30
@Jared Vì nhắc đến Flash? Tôi không nói đó là giải pháp duy nhất, tôi đã đề cập đó là cách phát hiện phông chữ chính xác nhất.
alex

4
@alex Có. Nó có thể gây ấn tượng sai cho các nhà phát triển, đặc biệt là những người mới. Tôi khuyên bạn nên chỉnh sửa câu trả lời của mình để giải thích rõ hơn những ưu và nhược điểm của việc sử dụng Flash, có thể chỉ là "Nó không được khuyến khích, nhưng ..." hoặc đại loại như vậy.
Jared

19
@Jared Tôi có cần viết tất cả các câu trả lời của mình để cung cấp thông tin từ đầu cho người đọc khi họ mới làm quen với nghề này không? Tôi đã giải thích rằng Flash yêu cầu một plugin độc quyền, nhưng tôi cũng đã đề cập rằng đó hiện là cách duy nhất để lấy tất cả các phông chữ có sẵn (phương pháp JavaScript chỉ phát hiện một tập hợp con các phông chữ, có thể đủ tốt cho hầu hết các trường hợp sử dụng). Tôi cũng không hài lòng về việc phải sử dụng Flash, nhưng đó là tất cả những gì chúng tôi có ngay bây giờ cho nhiệm vụ này.
alex

7
@Jared Bạn có thấy đoạn cuối không? Bạn có thể muốn đọc lại nó.
alex

10
@Jared Đoạn đó luôn tồn tại.
alex

73

Có, có! Tôi rất vui vì bạn đã hỏi câu hỏi này vì bây giờ tôi cũng muốn sử dụng nó.

+1 cho câu hỏi và đây là câu trả lời của bạn :)

http://www.lalit.org/lab/javascript-css-font-detect

từ 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;
};

Tóm lược

Làm thế nào nó hoạt động?

Mã này hoạt động trên nguyên tắc đơn giản là mỗi ký tự xuất hiện khác nhau trong các phông chữ khác nhau. Vì vậy, các phông chữ khác nhau sẽ có chiều rộng và chiều cao khác nhau cho cùng một chuỗi ký tự có cùng kích thước phông chữ.


2
Rất quanh co. Điều này thật tuyệt.
đệ quy

4
Cảm ơn bạn, vâng, điều này rất hữu ích khi tôi có một danh sách các phông chữ để kiểm tra những gì được cài đặt, nhưng vấn đề là làm thế nào để tạo một danh sách tên phông chữ ngay từ đầu.
mattsh,

43
Điều này sẽ chỉ cho biết có / không cho dù một phông chữ được cài đặt hay không.
rektide

2
Đầu tiên tôi nghĩ nó rất tuyệt nhưng sau đó tôi đã tìm thấy một số vấn đề. Vấn đề chính là mỗi trình duyệt trả về kết quả khác nhau. Chắc chắn là không đáng tin cậy.
Błażej Klisz

11
Thú vị và hữu ích nhưng không trả lời câu hỏi. Thao tác này không truy xuất tên của các phông chữ có sẵn trong trình duyệt. Đưa ra -1 miễn cưỡng.
BenjaminGolder

10

Có một cách để làm điều này bằng cách sử dụng document.fonts

Giá trị trả về là giao diện FontFaceSet của tài liệu. Giao diện FontFaceSet hữu ích để tải các phông chữ mới, kiểm tra trạng thái của các phông chữ đã tải trước đó, v.v.

  • Các giá trị trả về rất dài với trọng lượng, kiểu dáng, v.v.
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;
}
  • Chỉ trả về họ phông chữ
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)];
}

Tôi đã thử nghiệm nó mà không liên kết bất kỳ phông chữ nào trong HTML, sau đó liên kết phông chữ Roboto, kiểm tra lại và nó được thêm vào kết quả.


đoạn mã này hoạt động hoàn hảo cảm ơn! `` listFonts () {let fonts = document ['fonts']; const it = font.entries (); cho arr = []; let done = false; while (! done) {const font = it.next (); if (! font.done) {arr.push (font.value [0] .family); } else {done = font.done; }} // được chuyển thành set rồi arr để lọc các giá trị lặp lại return [... new Set (arr)]; } `` '
rufreakde

5
<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>

2
@Robert Sköld, vâng, nó dường như chỉ dành cho IE. Nó vẫn hữu ích cho nhiều mục đích, mặc dù khi được sử dụng nghiêm túc, bạn nên phát hiện một số tính năng để những người sử dụng các trình duyệt khác sẽ hiểu; xem ví dụ cs.tut.fi/~jkorpela/listfonts1.html
Jukka K. Korpela

Nó sẽ không hoạt động trong IE11 cho windows phone ?? Có gì khác tôi cần thêm cho windows phone không ???
jats

4

Giải pháp FontFaceSet.check ()

  • Phát hiện tất cả các phông chữ có sẵn là kỹ thuật lấy dấu vân tay của trình duyệt phổ biến, do đó, không có khả năng bất kỳ API JS nào được thêm vào sẽ trực tiếp trả về một danh sách.
  • Hỗ trợ FontFaceSet.check () đủ tốt để được sử dụng nhưng sẽ cần một dự phòng, ví dụ câu trả lời này cho các trình duyệt cũ hơn.
  • Kiểm tra danh sách phông chữ sau đây mất 150ms + vì vậy sẽ chỉ cần chạy theo yêu cầu và kết quả được lưu vào bộ nhớ cache.

Danh sách phông chữ 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',

Danh sách phông chữ 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()]);
})();


cảm ơn đây là những gì tôi cũng đang tìm kiếm cho thiết kế web cuối cùng dọc theo phông chữ hệ thống cục bộ để đạt được nhiều khả năng hiển thị nội dung hoặc phân tích trang theo cách không lấp đầy nhiều cpu
Constantin

3

Trong tìm kiếm này, tôi cũng tìm thấy Font.js , nó thêm một đối tượng Phông chữ giống như Hình ảnh, vì vậy có thể kiểm tra khi nào một phông chữ thực sự đã sẵn sàng để sử dụng. Cũng hoạt động trên phông chữ đã cài đặt / hệ thống. Nhược điểm là IE9 + chỉ do nhu cầu Object.defineProperty(các trình duyệt khác có nó), nhưng nếu bạn đang làm web hiện đại, đây có vẻ là một lựa chọn tốt hơn. (Thật đáng buồn, tôi sẽ phải đi với câu trả lời ở trên, ủng hộ và tiếp tục ngay bây giờ. :))


3

Tôi đã thêm hai phương pháp vào Trình dò ​​tìm của Lalit Patel ở trên:

  • addFont (family, stylesheetUrl, ruleString) -> phát hiện xem có tồn tại phông chữ 'family' hay không, nếu không, thêm một biểu định kiểu sẽ tải phông chữ bằng cách sử dụng stylesheetUrl nếu được cung cấp hoặc theo cách khác là ruleString
  • addFontsArr (arr) -> thêm một mảng phông chữ

Với điều này, bạn có thể làm:

fonts = [ 'Arial', 'Arial Black', { family: 'Lato', stylesheetUrl: 'https://fonts.googleapis.com/css?family=Lato'}, 'Leelawadee UI']
(new FontDetector()).addFontsArr(fonts);

mã:

/**
 * 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));
    }
};

2

Có thể điều này có thể được thực hiện theo một cách hoàn toàn khác, sử dụng một spritesheet với các hình ảnh phông chữ đã biết cho một ký tự cụ thể và so sánh nó với ảnh chụp nhanh của một phần tử canvas có cùng ký tự được vẽ với những gì trình duyệt báo cáo là cùng một phông chữ. Việc so sánh có thể được thực hiện với một cái gì đó giống như giống với.js .

Điều này chậm hơn, nhưng cũng sẽ cho phép chúng tôi phát hiện khi nào trình duyệt đang nói dối.


2

Câu trả lời ngắn gọn là. Không có nhiều thay đổi liên quan đến việc phát hiện phông chữ trong các trình duyệt vào năm 2020 ngoại trừ việc sử dụng Flash bây giờ là một ý tưởng thậm chí còn tệ hơn .

Hiện tại không có hệ thống gốc của trình duyệt để "liệt kê" tất cả các phông chữ có sẵn. Tuy nhiên, các trình duyệt sẽ cho phép bạn kiểm tra xem phông chữ đã được tải / sẵn sàng hay chưa bằng cách sử dụng API FontFaceSet . Nó được hỗ trợ khá tốt trong các trình duyệt hiện đại.

Điều này nhằm mục đích hiển thị nếu một phông chữ web đã được tải xuống hoàn toàn NHƯNG nó cũng sẽ hoạt động với các phông chữ hệ thống. Điểm bắt buộc là bạn phải cung cấp danh sách các phông chữ để kiểm tra.

Vì vậy, kết hợp với một user agent bài kiểm tra (không phải lúc nào cũng chính xác), bạn có thể tạo ra một danh sách các phông chữ hệ thống phổ biến cho từng loại thiết bị. Sau đó, kiểm tra với những phông chữ đó và bất kỳ phông chữ web nào bạn tải.

LƯU Ý: Điều này sẽ KHÔNG cung cấp cho bạn danh sách đầy đủ các phông chữ có sẵn, nhưng bạn có thể kiểm tra các phông chữ thường được cài đặt bởi MS Office hoặc các sản phẩm của Adobe.


0

Gần đây tôi đã nhận thấy rằng nếu tôi đặt giá trị context.font cho canvas HTML5 thành một thứ gì đó không hợp lệ, chẳng hạn như "rác", thì thay đổi sẽ bị canvas bỏ qua. Tôi không biết đây có phải là trình duyệt cụ thể hay không, nhưng nó có vẻ hoạt động theo cách này trên Chrome. Tôi cũng đã thấy các bài đăng khác ( phông chữ canvas HTML 5 bị bỏ qua ) cho biết nó xảy ra trong các trình duyệt khác.

Sau đó người ta có thể viết một chuỗi ra với giá trị mặc định, mà tôi tin là "10px sans serif" ( https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/font ), đặt phông chữ vào một mà bạn đang thử nghiệm và viết lại chuỗi. Nếu nó giống như bản vẽ đầu tiên, thì phông chữ không có sẵn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.