bir kullanıcının tarayıcısının görüntüleyebileceği her yazı tipini listeleyin


105

Tarayıcının gösterebileceği tüm yazı tiplerinin (veya yazı tipi ailelerinin) adlarını elde etmenin javascript'te bir yolu var mı? (Kullanıcıya mevcut tüm yazı tiplerinin bir listesini içeren bir açılır menü vermek ve kullanıcının bir yazı tipi seçmesine izin vermek istiyorum.) Bu listeyi önceden kodlamak veya sunucudan göndermek zorunda kalmamayı tercih ederim. (Sezgisel olarak, tarayıcının sahip olduğu yazı tiplerini bilmesi ve bunun bir şekilde javascript'e maruz bırakılması gerekiyor gibi görünüyor.)

Yanıtlar:


37

JavaScript sürümü biraz kesintili. Bilinen yazı tiplerini ve testlerini yineleyerek yazı tiplerini alır.

En doğru yol (özel bir eklenti kullanmak zorunda olsa da) Flash kullanmaktır . Burada, boyutları kullanarak ayrı ayrı test etmek zorunda kalmadan yazı tiplerinin listesini alabilirsiniz.

Bazı cihazlarda (iDevices, Flash eklentisi olmayan tarayıcılar vb.) Çalışmama pahasına kesin bir listeye mi yoksa yalnızca JavaScript aracılığıyla daha iyi destek sağlayan kısmi bir listeye mi sahip olacağınıza karar vermeniz gerekecektir .


30
@Jared Flash'tan bahsettiğin için mi? Bunun tek çözüm olduğunu söylemedim, yazı tiplerini tespit etmenin en doğru yolu olduğunu söyledim.
alex

4
@alex Evet. Geliştiricilere, özellikle de yenilerine yanlış izlenim verebilir. Flash kullanmanın artılarını ve eksilerini daha iyi açıklamak için yanıtınızı düzenlemenizi öneririm, belki sadece "Önerilmez, ama ..." veya bunun gibi bir şey.
Jared

19
@Jared Meslekte yeni olma ihtimaline karşı okuyuculara sıfırdan bilgi sağlamak için tüm yanıtlarımı yazmam gerekir mi? Flash'ın uygun bir eklenti gerektirdiğini açıkladım, ancak şu anda mevcut tüm yazı tiplerini almanın tek yolu olduğunu da belirtmiştim (JavaScript yöntemi yalnızca bir yazı tipi alt kümesini algılar, bu muhtemelen çoğu kullanım durumu için yeterince iyidir). Flash kullanmak zorunda kaldığım için de mutlu değilim, ancak bu görev için şu anda sahip olduğumuz tek şey bu.
alex

7
@Jared Son paragrafı görüyor musun? Tekrar okumak isteyebilirsiniz.
alex

10
@Jared O paragraf her zaman vardı.
alex

74

Evet var! Bu soruyu sorduğunuza çok sevindim çünkü şimdi bunu da kullanmak istiyorum.

Soru için +1 ve işte cevabınız :)

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

Http://www.lalit.org/wordpress/wp-content/uploads/2008/05/fontdetect.js?ver=0.3'ten alınan 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');
 */
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;
};

Özet

O nasıl çalışır?

Bu kod, her karakterin farklı yazı tiplerinde farklı görünmesi şeklindeki basit ilkeye göre çalışır. Bu nedenle, farklı yazı tipleri, aynı yazı tipi boyutundaki aynı karakter dizisi için farklı genişlik ve yükseklik alacaktır.


2
Çok aldatıcı. Bu harika.
yinelemeli

4
Teşekkürler, evet bu, neyin yüklü olduğunu test etmek için bir yazı tipi listesine sahip olduğumda kullanışlıdır, ancak sorun ilk etapta bir yazı tipi adları listesinin nasıl oluşturulacağıdır.
mattsh

44
Bu sadece bir yazı tipinin kurulu olup olmadığı için evet / hayır verir.
rektide

2
Önce harika olduğunu düşündüm ama sonra bazı sorunlar buldum. Temel sorun, her tarayıcının farklı sonuçlar vermesidir. Kesinlikle güvenilir değil.
Błażej Klisz

11
İlginç ve kullanışlı ama soruya cevap vermiyor. Bu, tarayıcıda bulunan yazı tiplerinin adlarını almaz. İsteksiz bir -1 vermek.
BenjaminGolder

12

Bunu kullanarak yapmanın bir yolu var document.fonts

Döndürülen değer, belgenin FontFaceSet arabirimidir. FontFaceSet arabirimi, yeni yazı tiplerini yüklemek, önceden yüklenmiş yazı tiplerinin durumunu kontrol etmek vb. İçin kullanışlıdır.

  • Döndürülen değerler ağırlık, stil vb. İle ayrıntılıdır.
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;
}
  • Yalnızca yazı tipi ailesini verir
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)];
}

HTML'de herhangi bir yazı tipi bağlamadan test ettim, ardından Roboto yazı tipini bağladım, tekrar test ettim ve sonuca eklendi.


bu kod parçacığı mükemmel çalıştı, teşekkürler! `` `listFonts () {let fonts = document ['fontlar']; const it = fonts.entries (); let arr = []; let bitti = yanlış; while (! bitti) {const font = it.next (); eğer (! font.done) {arr.push (font.value [0] .family); } else {done = font.done; }} // kümeye dönüştürülür sonra tekrarlanan değerleri filtrelemek için arr return [... new Set (arr)]; } ``
rufreakde

bunu Firefox'ta çalıştırdığımda, yalnızca web yazı tiplerini gösteriyor (FontAwesome gibi)
Tim Davis

6

FontFaceSet.check () çözümü

  • Mevcut tüm yazı tiplerini tespit etmek yaygın bir tarayıcı parmak izi tekniğidir, bu nedenle doğrudan bir liste döndürecek olan herhangi bir JS API'sinin eklenmesi olası değildir.
  • FontFaceSet.check () desteği kullanılacak kadar iyidir, ancak bir geri dönüşe ihtiyaç duyacaktır, örneğin eski tarayıcılar için bu cevap .
  • Aşağıdaki yazı tipi listesinin kontrol edilmesi 150ms + sürer, bu nedenle yalnızca gerektiği şekilde çalıştırılması ve sonucun önbelleğe alınması gerekir.

Windows 10 Yazı Tipi Listesi

'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 / iOS Yazı Tipi Listesi

'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()]);
})();


Teşekkürler, içerik göstermede veya sayfayı çok fazla cpu doldurmayacak şekilde ayrıştırmada daha fazla esneklik kazanmak için yerel sistem yazı tiplerinin yanı sıra nihai web tasarımı için de aradığım şey bu
Constantin

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, evet, sadece IE için görünüyor. Yine de birçok amaç için yararlıdır, ancak ciddi şekilde kullanıldığında, başka tarayıcıları kullanan kişilerin anlayabilmesi için bazı özellik algılamalarına sahip olmanız gerekir; bkz. örn. cs.tut.fi/~jkorpela/listfonts1.html
Jukka K. Korpela

Windows telefonu için IE11'de çalışmayacak ?? Windows telefonu için eklemem gereken başka bir şey var mı ???
jats

4

Lalit Patel'in Dedektörüne yukarıdaki iki yöntem ekledim:

  • addFont (family, stylesheetUrl, ruleString) -> yazı tipinin var olup olmadığını algılar, yoksa yazı tipini, verilmişse stil sayfasıUrl'yi veya başka bir şekilde ruleString'i kullanarak yükleyen bir stil sayfası ekler.
  • addFontsArr (arr) -> bir yazı tipi dizisi ekler

Bununla şunları yapabilirsiniz:

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

3

Bunu araştırmamda, Image'a çok benzer bir Font nesnesi ekleyen Font.js'yi de buldum , böylece bir fontun gerçekten kullanıma hazır olup olmadığını kontrol etmek mümkün. Ayrıca kurulu / sistem yazı tipleri üzerinde de çalışır. Dezavantajı, yalnızca ihtiyaç duyulması nedeniyle IE9 + 'dır Object.defineProperty(diğer tarayıcılarda buna sahiptir), ancak modern web yapıyorsanız, bu daha da iyi bir seçenek gibi görünüyor. (Maalesef yukarıdaki cevaba uymak zorundayım, oy verdim ve şimdilik devam edeceğim. :))


3

Kısa cevap. Flash kullanmanın artık daha da kötü bir fikir olması dışında 2020'de tarayıcılarda yazı tipi algılama ile ilgili pek bir şey değişmedi .

Şu anda mevcut tüm yazı tiplerini "listelemek" için tarayıcı yerel sistemi bulunmamaktadır. Ancak, tarayıcılar FontFaceSet API kullanarak bir fontun yüklü / hazır olup olmadığını kontrol etmenize izin verir . Modern tarayıcılarda oldukça iyi destekleniyor.

Bu, bir web fontunun tamamen indirilip indirilmediğini göstermeyi amaçlamaktadır, ANCAK sistem fontları için de çalışacaktır. İşin püf noktası , kontrol etmek için bir yazı tipi listesi sağlamanız gerektiğidir.

Bu nedenle, bir user agent testle bağlantılı olarak (her zaman doğru değildir), her cihaz türü için ortak sistem yazı tiplerinin bir listesini oluşturabilirsiniz . Ardından bunlara ve yüklediğiniz tüm web yazı tiplerine karşı test edin.

NOT: Bu size mevcut yazı tiplerinin tam listesini VERMEZ, ancak MS Office veya Adobe ürünleri tarafından yaygın olarak yüklenen yazı tiplerini kontrol edebilirsiniz.


2

Belki bu, belirli bir karakter için bilinen yazı tipi görüntülerine sahip bir hareketli yazı sayfası kullanarak ve bunu tarayıcının aynı yazı tipi olarak bildirdikleriyle aynı karakterin çizildiği bir tuval öğesinin anlık görüntüleriyle karşılaştırarak tamamen farklı bir şekilde yapılabilir. Karşılaştırma, benzeri . Js gibi bir şeyle yapılabilir .

Bu daha yavaştır, ancak tarayıcının ne zaman yalan söylediğini tespit etmemize de izin vermelidir.


0

Kısa bir süre önce, bir HTML5 tuval için context.font değerini "önemsiz" gibi geçersiz bir şeye ayarlarsam, değişikliğin tuval tarafından göz ardı edildiğini fark ettim. Bunun tarayıcıya özgü olup olmadığını bilmiyorum, ancak Chrome'da bu şekilde çalışıyor gibi görünüyor. Diğer tarayıcılarda da olduğunu gösteren başka gönderiler de gördüm ( HTML 5 canvas fontu yok sayılıyor ).

Daha sonra "10px sans serif" ( https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/font ) olduğuna inandığım varsayılan değerle bir dize yazabilir , yazı tipini test ettiğinize ve dizeyi yeniden yazın. İlk çizim ile aynıysa, yazı tipi mevcut değildir.


0

Yazı tipi erişim API'si Chrome 87'de mevcuttur:

// Query for all available fonts and log metadata.
const fonts = navigator.fonts.query();
try {
  for await (const metadata of fonts) {
    console.log(`${metadata.family} (${metadata.fullName})`);
  }
} catch (err) {
  console.error(err);
}

// Roboto (Roboto Black)
// Roboto (Roboto Black Italic)
// Roboto (Roboto Bold)

Daha fazla bilgi burada

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.