कैसे पता चलेगा कि कोई फॉन्ट (@ फॉन्ट-फेस) पहले ही लोड हो चुका है?


80

मैं फ़ॉन्ट-विस्मयकारी का उपयोग कर रहा हूं, लेकिन जब फ़ॉन्ट फ़ाइलें लोड नहीं होती हैं, तो आइकन, के साथ दिखाई देते हैं।

इसलिए, मैं चाहता हूं कि ये आइकन display:noneफाइल लोड न होने के दौरान हों।

@font-face {
  font-family: "FontAwesome";
  src: url('../font/fontawesome-webfont.eot');
  src: url('../font/fontawesome-webfont.eot?#iefix') format('eot'), url('../font/fontawesome-webfont.woff') format('woff'), url('../font/fontawesome-webfont.ttf') format('truetype'), url('../font/fontawesome-webfont.svg#FontAwesome') format('svg');
  font-weight: normal;
  font-style: normal;
}

मुझे कैसे पता चलेगा कि इन फ़ाइलों को लोड किया गया है और मैं आखिरकार आइकन दिखाने में सक्षम हूं?

संपादित करें: पेज लोड होने (ऑनलोड) होने पर मैं बात नहीं कर रहा हूं, क्योंकि फॉन्ट को पूरे पेज से पहले लोड किया जा सकता है।


उम्मीद है कि हम जल्द ही देशी फ़ॉन्ट इवेंट्स कर सकते हैं। blog.typekit.com/2013/02/05/more-reliable-font-events
Pacerier


2
यह प्रश्न एक डुप्लिकेट है, और मैंने मूल प्रश्न पर 2015 का अपडेट उत्तर पोस्ट किया है ।
डेन डैस्कलेस्कु

वहाँ एक समाधान है जो smnh.me/web-font-loading-detection-without-timers
Pacerier

जवाबों:


44

अब GitHub पर: https://github.com/patrickmarabeas/jQuery-FontSpy.js

अनिवार्य रूप से विधि दो अलग-अलग फोंट में एक स्ट्रिंग की चौड़ाई की तुलना करके काम करती है। हम कॉमिक सैंस का उपयोग फॉन्ट के खिलाफ परीक्षण के लिए कर रहे हैं, क्योंकि यह वेब सेफ़ फोंट का सबसे अलग है और आपके द्वारा उपयोग किए जा रहे किसी भी कस्टम फॉन्ट के लिए पर्याप्त रूप से अलग है। इसके अतिरिक्त, हम एक बहुत बड़े फ़ॉन्ट-आकार का उपयोग कर रहे हैं ताकि छोटे अंतर भी स्पष्ट हों। जब कॉमिक सैंस स्ट्रिंग की चौड़ाई की गणना की गई है, तो कॉमिक सैंस में वापसी के साथ, फ़ॉन्ट-परिवार को आपके कस्टम फ़ॉन्ट में बदल दिया जाता है। जब जाँच की जाती है, यदि स्ट्रिंग तत्व की चौड़ाई समान है, तो कॉमिक सैंस का फ़ॉलबैक फ़ॉन्ट अभी भी उपयोग में है। यदि नहीं, तो आपका फ़ॉन्ट चालू होना चाहिए।

मैंने फॉन्ट लोड डिटेक्शन की विधि को एक jQuery प्लगइन में डिज़ाइन किया है जो डेवलपर को स्टाइल तत्वों की क्षमता देने के लिए डिज़ाइन किया गया है कि क्या फ़ॉन्ट लोड किया गया है या नहीं। यदि कोई कस्टम फ़ॉन्ट लोड करने में विफल रहता है, तो विफल सुरक्षित टाइमर जोड़ा गया है ताकि उपयोगकर्ता बिना सामग्री के न रह सके। यह सिर्फ खराब प्रयोज्यता है।

मैंने फ़ॉन्ट लोडिंग के दौरान और कक्षाओं को जोड़ने और हटाने के साथ विफल होने पर अधिक नियंत्रण भी जोड़ा है। अब आप फ़ॉन्ट के लिए जो चाहें कर सकते हैं। मैं केवल आपके फ़ॉल बैक फ़ॉन्ट को कस्टम के करीब लाने के लिए फ़ॉन्ट आकार, लाइन रिक्ति, आदि को संशोधित करने की सलाह दूंगा ताकि आपका लेआउट बरकरार रहे, और उपयोगकर्ताओं को एक अपेक्षित अनुभव मिले।

यहाँ एक डेमो है: http://patrickmarabeas.github.io/jQuery-FontSpy.js

निम्न को .js फ़ाइल में फेंक दें और उसे संदर्भ दें।

(function($) {

    $.fontSpy = function( element, conf ) {
        var $element = $(element);
        var defaults = {
            font: $element.css("font-family"),
            onLoad: '',
            onFail: '',
            testFont: 'Comic Sans MS',
            testString: 'QW@HhsXJ',
            delay: 50,
            timeOut: 2500
        };
        var config = $.extend( defaults, conf );
        var tester = document.createElement('span');
            tester.style.position = 'absolute';
            tester.style.top = '-9999px';
            tester.style.left = '-9999px';
            tester.style.visibility = 'hidden';
            tester.style.fontFamily = config.testFont;
            tester.style.fontSize = '250px';
            tester.innerHTML = config.testString;
        document.body.appendChild(tester);
        var fallbackFontWidth = tester.offsetWidth;
        tester.style.fontFamily = config.font + ',' + config.testFont;
        function checkFont() {
            var loadedFontWidth = tester.offsetWidth;
            if (fallbackFontWidth === loadedFontWidth){
                if(config.timeOut < 0) {
                    $element.removeClass(config.onLoad);
                    $element.addClass(config.onFail);
                    console.log('failure');
                }
                else {
                    $element.addClass(config.onLoad);
                    setTimeout(checkFont, config.delay);
                    config.timeOut = config.timeOut - config.delay;
                }
            }
            else {
                $element.removeClass(config.onLoad);
            }
        }
        checkFont();
    };

    $.fn.fontSpy = function(config) {
        return this.each(function() {
            if (undefined == $(this).data('fontSpy')) {
                var plugin = new $.fontSpy(this, config);
                $(this).data('fontSpy', plugin);
            }
        });
    };

})(jQuery);

इसे अपने प्रोजेक्ट पर लागू करें

.bannerTextChecked {
        font-family: "Lobster";
        /* don't specify fallback font here, do this in onFail class */
}

$(document).ready(function() {

    $('.bannerTextChecked').fontSpy({
        onLoad: 'hideMe',
        onFail: 'fontFail anotherClass'
    });

});

उस FOUC को हटाओ!

.hideMe {
    visibility: hidden !important;
}

.fontFail {
    visibility: visible !important;
    /* fall back font */
    /* necessary styling so fallback font doesn't break your layout */
}

संपादित करें: FontAwesome संगतता को हटा दिया गया क्योंकि यह ठीक से काम नहीं करता था और विभिन्न संस्करणों के साथ मुद्दों में भाग गया था। हैकी फिक्स यहां पाया जा सकता है: https://github.com/patrickmarabeas/jQuery-FontFaceSpy.js/issues/1


फ़ॉन्ट की लंबाई की तुलना ... क्या यह WebFont लोडर (अन्य उत्तर देखें) भी कर रहा है?
पचेरियर

1
और किसी भी मामले में, चरित्र की लंबाई की तुलना कई फोंट के लिए काम नहीं करेगी क्योंकि कई "कॉपी" फोंट को समान लंबाई के लिए डिज़ाइन किया गया है । उदाहरण के लिए, एरियल, हेल्वेटिका, और लिबरेशन संस सभी वर्णों के लिए समान वर्ण चौड़ाई है। En.wikipedia.org/wiki/Arial भी देखें । अब तक ऐसा लगता है जैसे कैनवास का उपयोग करने वाले पिक्सेल के लिए पिक्सेल की जाँच करना एकमात्र
मूर्खतापूर्ण

1
मैं फोंट लोड होने से पहले गलत तत्वों के आकार की गणना के साथ iScroll के साथ होने वाली समस्या को ठीक करने के लिए इसका उपयोग करने की आवश्यकता थी। लेकिन मैं jQuery का उपयोग नहीं कर रहा हूं, इसलिए एक वैनिला js संस्करण बनाया है: github.com/keithswright/vanilla-fontspy मेरे लिए काम करता है।
कीथ

@Pacerier - ध्यान दें कि यह केवल आपका चुना हुआ परीक्षण है और आपके चुने हुए लोडिंग फ़ॉन्ट को अलग-अलग लंबाई की आवश्यकता है। इसलिए, जब तक कि कॉमिक सैंस के पास बहुत सारे फोंट नहीं हैं, जिसमें उसके समान चरित्र चौड़ाई है, तब भी इसे ज्यादातर मामलों में काम करना चाहिए।
ब्रायनग्रेज़्ज़ाक

20

Google और Typekit द्वारा विकसित WebFont Loader ( github repo ) आज़माएं ।

यह उदाहरण पहले डिफ़ॉल्ट सेरिफ़ फ़ॉन्ट में पाठ प्रदर्शित करता है; तब फोंट लोड होने के बाद यह निर्दिष्ट फॉन्ट में पाठ प्रदर्शित करता है। (यह कोड अन्य सभी आधुनिक ब्राउज़रों में फ़ायरफ़ॉक्स के डिफ़ॉल्ट व्यवहार को पुन: पेश करता है।)


9

यहाँ दूसरों से समाधान के लिए एक अलग दृष्टिकोण है।

मैं WebGL बनावट बनाने के लिए FontAwesome 4.1.0 का उपयोग कर रहा हूं। इसने मुझे एक छोटे वर्ग का उपयोग करने का विचार दिया जो कि एक वर्ग को प्रस्तुत करने के लिए एक कैनवास का उपयोग करता है, फिर उस कैनवास में एक पिक्सेल को जांचने के लिए जांचें कि क्या यह है:

function waitForFontAwesome( callback ) {
   var retries = 5;

   var checkReady = function() {
      var canvas, context;
      retries -= 1;
      canvas = document.createElement('canvas');
      canvas.width = 20;
      canvas.height = 20;
      context = canvas.getContext('2d');
      context.fillStyle = 'rgba(0,0,0,1.0)';
      context.fillRect( 0, 0, 20, 20 );
      context.font = '16pt FontAwesome';
      context.textAlign = 'center';
      context.fillStyle = 'rgba(255,255,255,1.0)';
      context.fillText( '\uf0c8', 10, 18 );
      var data = context.getImageData( 2, 10, 1, 1 ).data;
      if ( data[0] !== 255 && data[1] !== 255 && data[2] !== 255 ) {
         console.log( "FontAwesome is not yet available, retrying ..." );
         if ( retries > 0 ) {
            setTimeout( checkReady, 200 );
         }
      } else {
         console.log( "FontAwesome is loaded" );
         if ( typeof callback === 'function' ) {
            callback();
         }
      }
   }

   checkReady();
};

जैसा कि यह एक कैनवास का उपयोग करता है, इसके लिए एक काफी आधुनिक ब्राउज़र की आवश्यकता होती है, लेकिन यह IE8 के साथ-साथ पॉलीफ़िल पर भी काम कर सकता है।


मैं उसी समस्या का सामना कर रहा हूं जब कोंवाजेएस में फ़ॉन्ट-भयानक लोड हो रहा है
महदी

4

वास्तव में, यह समझने का एक अच्छा तरीका है कि सभी फॉन्ट डाउनलोड होने या पूरी तरह से लोड होने लगे या नहीं और कुछ त्रुटियों में पड़ जाएं, लेकिन यह केवल एक विशिष्ट फ़ॉन्ट के लिए नहीं है , निम्नलिखित कोड पर ध्यान दें:

document.fonts.onloading = () => {
  // do someting when fonts begin to download
};
document.fonts.onloadingdone = () => {
  // do someting when fonts are loaded completely
};
document.fonts.onloading = () => {
  // do someting when fonts fall into some error
};

और वहाँ भी एक विकल्प है कि रिटर्न Promiseऔर यह .thenसमारोह के साथ संभाल सकता है :

document.fonts.ready
 .then(() => console.log('do someting at the final with each status'))

धन्यवाद। यह पूरी तरह से काम करता है! लेकिन मुझे कहीं-कहीं उस फ़ॉन्ट का उपयोग करके <span> तत्व रखकर फ़ॉन्ट लोडिंग को ट्रिगर करना होगा।
tyt2y3

IE11 में समर्थित नहीं है, जो दुर्भाग्य से अभी भी विंडोज सर्वर के साथ बंडल में आता है
गाइ पैसी

@GuyPassy, ​​मुझे नहीं पता कि IE11 क्या है !!
अमेरलिसिया

4
@AmerllicA काश मैं एक दिन इतना भाग्यशाली हो सकता है
लड़के Passy

3

यहां यह जानने का एक और तरीका है कि क्या @ फॉन्ट-फेस पहले से ही टाइमर का उपयोग किए बिना लोड किया जा चुका है: एक सावधानीपूर्वक तैयार किए गए तत्व का आकार बदलने पर एक तात्कालिक घटना प्राप्त करने के लिए "स्क्रॉल" ईवेंट का उपयोग करें।

मैंने एक ब्लॉग पोस्ट लिखी है कि यह कैसे किया जाता है और जीथब पर पुस्तकालय प्रकाशित किया है ।


0

कुछ ऐसा आजमाएं

$(window).bind("load", function() {
       $('#text').addClass('shown');
});

और फिर करते हैं

#text {visibility: hidden;}
#text.shown {visibility: visible;}

फोंट लोड होने के बाद लोड इवेंट में आग लगनी चाहिए।


$(function(){...})जब पूरे पृष्ठ को लोड किया जाता है तो यह उसी तरह चलता है।
बजे शंकर कैबस

1
ये एक जैसे नहीं हैं। जब डोम (HTML) और पृष्ठ के भीतर संपत्ति (CSS, JS, छवियाँ, फ़्रेम) लोड हो रहे हों तो hayk.mart का उदाहरण चालू हो जाएगा। आपका उदाहरण जब केवल DOM ने लोडिंग समाप्त की है।
२०:२२ को

जिज्ञासु क्यों इस जवाब को नकारा जाता है, एक त्वरित खोज यह सही दृष्टिकोण दिखाती है

-1

यह एक वैकल्पिक दृष्टिकोण है जो कम से कम यह सुनिश्चित करेगा कि फ़ॉन्ट-भयानक लोड किया गया है, कि ओपी के लिए एक पूर्ण समाधान। मूल कोड वर्डप्रेस मंचों में यहां पाया गया है https://wordpress.stackexchange.com/a/165358/40636

यह अज्ञेयवादी है और यह फ़ॉन्ट-भयानक जैसे किसी भी फ़ॉन्ट शैली संसाधन के साथ काम करेगा जहाँ एक फ़ॉन्ट-परिवार की जाँच की जा सकती है। थोड़ा और सोचा के साथ मैं शर्त लगा सकता हूं कि यह बहुत अधिक लागू हो सकता है ...

<link href="//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<script>
    (function($){
        var faSpan = $('<span class="fa" style="display:none"></span>').appendTo('body');
        if (faSpan .css('fontFamily') !== 'FontAwesome' ) {
            // Fallback Link
            $('head').append('<link href="https://stackoverflow.com/css/font-awesome.min.css" rel="stylesheet">');
        }
        faSpan.remove();
    })(jQuery);
</script>

इस मामले में फ़ॉन्ट-बहुत बढ़िया लोड नहीं करता है (या में एक fallback है अगर यह बहुत धीरे-धीरे लोड! ), लेकिन सूचित नहीं करता जब फ़ॉन्ट समाप्त लोड हो रहा है है।
दान डैस्कलेस्क्यू

@DanDascalescu मैंने उत्तर को अधिक स्पष्ट रूप से अपडेट किया है यह इंगित करता है कि यह एक वैकल्पिक दृष्टिकोण है जो केवल यह सुनिश्चित करता है कि फ़ॉन्ट-भयानक लाइब्रेरी भरी हुई है, न कि पूर्ण समाधान। उम्मीद है कि इसे थोड़ा साफ करता है, जैसा कि मैंने पिछले पुनरावृत्ति से कुछ डाउनवोट अर्जित किया है।
उसिल

-3

नीचे दिए गए कोड का उपयोग करें:

<!DOCTYPE HTML>
<html>
    <head>
    </head>

<body>
<canvas id="canvasFont" width="40px" height="40px" style="position: absolute; display: none;"></canvas>

<script>
function IsLoadedFonts()
    {
        var Args = arguments;
        var obj = document.getElementById('canvasFont');
        var ctx = obj.getContext("2d");
        var baseFont = (/chrome/i.test(navigator.userAgent))?'tims new roman':'arial';
         //................
          function getImg(fon)
          { 
            ctx.clearRect(0, 0, (obj).width, (obj).height);
            ctx.fillStyle = 'rgba(0,0,0,1.0)';
            ctx.fillRect( 0, 0, 40, 40 );
            ctx.font = '20px '+ fon;
            ctx.textBaseline = "top";
            ctx.fillStyle = 'rgba(255,255,255,1.0)';
            ctx.fillText( '\u0630', 18, 5 );
            return ctx.getImageData( 0, 0, 40, 40 );
          };
        //..............
          for(var i1=0; i1<Args.length; i1++)
          {
            data1 = getImg(Args[i1]);
            data2 = getImg(baseFont);
            var isLoaded = false;
            //...........
            for (var i=0; i<data1.data.length; i++)
            {
                if(data1.data[i] != data2.data[i])
                    {isLoaded = true; break;}
            }
            //..........
            if(!isLoaded)
                    return false;
         }
         return true;
    };

     setTimeout(function(){alert(IsLoadedFonts('myfont'));},100);
   </script>
   </body>

कई फोंट की जांच कर सकते हैं:

setTimeout(function(){alert(IsLoadedFonts('font1','font2','font3'));},100);

नीचे दिया गया कोड केवल ओपेरा में काम करता है लेकिन आसान है:

if(!document.defaultView.getComputedStyle(document.getElementById('mydiv'))['fontFamily'].match(/myfont/i))
          alert("font do not loaded ");

समान "कैनवास को प्रस्तुत करना" विचार है कि लीफ़्ट ने एक साल पहले पोस्ट किया था
डैन डस्केल्सस्कु
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.