it-swarm.com.de

Erkennung der WebP-Unterstützung

Wie kann ich die Unterstützung für WebP über Javascript erkennen? Ich würde gerne Feature-Erkennung anstelle von Browser-Erkennung verwenden, aber ich finde keine Möglichkeit, dies zu tun. Modernizr ( www.modernizr.com ) sucht nicht danach.

53
snostorm

Ich denke, so etwas könnte funktionieren:

var hasWebP = false;
(function() {
  var img = new Image();
  img.onload = function() {
    hasWebP = !!(img.height > 0 && img.width > 0);
  };
  img.onerror = function() {
    hasWebP = false;
  };
  img.src = 'http://www.gstatic.com/webp/gallery/1.webp';
})();

In Firefox und IE wird der "onload" -Handler einfach nicht aufgerufen, wenn das Bild nicht verstanden werden kann und stattdessen der "onerror" aufgerufen wird.

Sie haben jQuery nicht erwähnt, aber als Beispiel für den Umgang mit der asynchronen Art dieser Prüfung können Sie ein jQuery-Objekt "Deferred" zurückgeben:

function hasWebP() {
  var rv = $.Deferred();
  var img = new Image();
  img.onload = function() { rv.resolve(); };
  img.onerror = function() { rv.reject(); };
  img.src = 'http://www.gstatic.com/webp/gallery/1.webp';
  return rv.promise();
}

Dann könntest du schreiben:

hasWebP().then(function() {
  // ... code to take advantage of WebP ...
}, function() {
  // ... code to deal with the lack of WebP ...
});

Hier ist ein jsfiddle-Beispiel.


Ein fortgeschrittener Checker: http://jsfiddle.net/JMzj2/29/ . Dieses lädt Bilder von einer Daten-URL und prüft, ob es erfolgreich geladen wurde. Da WebP jetzt auch verlustfreie Bilder unterstützt, können Sie prüfen, ob der aktuelle Browser nur verlustbehaftetes WebP oder auch verlustfreies WebP unterstützt. (Hinweis: Dies prüft implizit auch die Unterstützung für Daten-URLs.)

var hasWebP = (function() {
    // some small (2x1 px) test images for each feature
    var images = {
        basic: "data:image/webp;base64,UklGRjIAAABXRUJQVlA4ICYAAACyAgCdASoCAAEALmk0mk0iIiIiIgBoSygABc6zbAAA/v56QAAAAA==",
        lossless: "data:image/webp;base64,UklGRh4AAABXRUJQVlA4TBEAAAAvAQAAAAfQ//73v/+BiOh/AAA="
    };

    return function(feature) {
        var deferred = $.Deferred();

        $("<img>").on("load", function() {
            // the images should have these dimensions
            if(this.width === 2 && this.height === 1) {
                deferred.resolve();
            } else {
                deferred.reject();
            }
        }).on("error", function() {
            deferred.reject();
        }).attr("src", images[feature || "basic"]);

        return deferred.promise();
    }
})();

var add = function(msg) {
    $("<p>").text(msg).appendTo("#x");
};

hasWebP().then(function() {
    add("Basic WebP available");
}, function() {
    add("Basic WebP *not* available");
});

hasWebP("lossless").then(function() {
    add("Lossless WebP available");
}, function() {
    add("Lossless WebP *not* available");
});
47
Pointy

Dies ist meine Lösung - dauert etwa 6 ms und ich denke, WebP ist nur eine Funktion für einen modernen Browser. Verwendet eine andere Methode mit der Funktion canvas.toDataUrl () anstelle von image, um das Feature zu erkennen:

function canUseWebP() {
    var elem = document.createElement('canvas');

    if (!!(elem.getContext && elem.getContext('2d'))) {
        // was able or not to get WebP representation
        return elem.toDataURL('image/webp').indexOf('data:image/webp') == 0;
    }

    // very old browser like IE 8, canvas not supported
    return false;
}
57
Rui Marques

Dies ist eine alte Frage, aber Modernizr unterstützt jetzt die Webp-Erkennung.

http://modernizr.com/download/

Suchen Sie nach img-webp unter Nichtkern-Erkennungen.

11
Jake Wilson

Bevorzugte Lösung in HTML5

<picture>
  <source srcset="/path/to/image.webp" type="image/webp">
  <img src="/path/to/image.jpg" alt="insert alt text here">
</picture>

Wiki zu W3C

9

Hier ist der Code, ohne ein Bild anfordern zu müssen. Mit qwertys neuer Geige aktualisiert.

http://jsfiddle.net/z6kH9/

function testWebP(callback) {
    var webP = new Image();
    webP.onload = webP.onerror = function () {
        callback(webP.height == 2);
    };
    webP.src = 'data:image/webp;base64,UklGRjoAAABXRUJQVlA4IC4AAACyAgCdASoCAAIALmk0mk0iIiIiIgBoSygABc6WWgAA/veff/0PP8bA//LwYAAA';
};

testWebP(function(support) {
    document.body.innerHTML = support ? 'Yeah man!' : 'Nope';
});
5
James Westgate

WebPJS verwendet eine intelligentere Erkennung der WebP-Unterstützung, ohne dass externe Bilder erforderlich sind: http://webpjs.appspot.com/

5
unxed

Ich habe festgestellt, dass die Funktion zur Erkennung der Webp-Unterstützung 300 + ms benötigt, wenn die Seite JavaScript stark ist. Also schrieb ich ein Skript mit Caching-Funktionen:

  • skript-Cache
  • localstorage cache

Es wird nur einmal erkannt, wenn der Benutzer zum ersten Mal auf die Seite zugreift.

/**
 * @fileOverview WebP Support Detect.
 * @author ChenCheng<[email protected]>
 */
(function() {

  if (this.WebP) return;
  this.WebP = {};

  WebP._cb = function(isSupport, _cb) {
    this.isSupport = function(cb) {
      cb(isSupport);
    };
    _cb(isSupport);
    if (window.chrome || window.opera && window.localStorage) {
      window.localStorage.setItem("webpsupport", isSupport);
    }
  };

  WebP.isSupport = function(cb) {
    if (!cb) return;
    if (!window.chrome && !window.opera) return WebP._cb(false, cb);
    if (window.localStorage && window.localStorage.getItem("webpsupport") !== null) {
      var val = window.localStorage.getItem("webpsupport");
      WebP._cb(val === "true", cb);
      return;
    }
    var img = new Image();
    img.src = "data:image/webp;base64,UklGRjoAAABXRUJQVlA4IC4AAACyAgCdASoCAAIALmk0mk0iIiIiIgBoSygABc6WWgAA/veff/0PP8bA//LwYAAA";
    img.onload = img.onerror = function() {
      WebP._cb(img.width === 2 && img.height === 2, cb);
    };
  };

  WebP.run = function(cb) {
    this.isSupport(function(isSupport) {
      if (isSupport) cb();
    });
  };

})();
3
sorrycc

Hier ist eine Version der Antwort von James Westgate in ES6.

function testWebP() {
    return new Promise(res => {
        const webP = new Image();
        webP.src = 'data:image/webp;base64,UklGRjoAAABXRUJQVlA4IC4AAACyAgCdASoCAAIALmk0mk0iIiIiIgBoSygABc6WWgAA/veff/0PP8bA//LwYAAA';
        webP.onload = webP.onerror = function () {
            res(webP.height === 2);
        };        
    })
};

testWebP().then(hasWebP => console.log(hasWebP));

FF64: falsch

FF65: stimmt

Chrome: wahr

Ich liebe die synchrone Antwort von Rui Marques, aber leider gibt FF65 trotz der Fähigkeit, WebP anzuzeigen, immer false zurück.

2
RoccoB

WebP-Images mit htaccess

Fügen Sie Folgendes in Ihre .htaccess-Datei ein und jpg/png-Bilder werden durch WebP-Bilder ersetzt, wenn sie sich im selben Ordner befinden.

<IfModule mod_rewrite.c>
  RewriteEngine On

  # Check if browser support WebP images
  RewriteCond %{HTTP_ACCEPT} image/webp

  # Check if WebP replacement image exists
  RewriteCond %{DOCUMENT_ROOT}/$1.webp -f

  # Serve WebP image instead
  RewriteRule (.+)\.(jpe?g|png)$ $1.webp [T=image/webp,E=accept:1]
</IfModule>

<IfModule mod_headers.c>
  Header append Vary Accept env=REDIRECT_accept
</IfModule>

<IfModule mod_mime.c>
  AddType image/webp .webp
</IfModule>

Lesen Sie mehr hier

1

hier ist eine einfache Funktion mit Promise basierend auf Pointys Antwort

let webpSupport = undefined // so we won't have to create the image multiple times
const webp1Px = 'data:image/webp;base64,UklGRjoAAABXRUJQVlA4IC4AAACyAgCdASoCAAIALmk0mk0iIiIiIgBoSygABc6WWgAA/veff/0PP8bA//LwYAAA'

function isWebpSupported () {
  if (webpSupport !== undefined) {
    return Promise.resolve(webpSupport)
  }

  return new Promise((resolve, _reject) => {
    const img = new Image()
    img.onload = () => {
      webpSupport = !!(img.height > 0 && img.width > 0);
      resolve(webpSupport)
    }
    img.onerror = () => {
      webpSupport = false
      resolve(webpSupport)
    }
    img.src = webp1Px
  })
}
1
Liron Navon

Es gibt eine Möglichkeit, die webP-Unterstützung zu testen sofort . Die Synchronisierung ist genau und genau, sodass Sie nicht auf einen Rückruf warten müssen, um Bilder zu rendern.

function testWebP = () => {
    const canvas = typeof document === 'object' ? 
    document.createElement('canvas') : {};
    canvas.width = canvas.height = 1;
    return canvas.toDataURL ? canvas.toDataURL('image/webp').indexOf('image/webp') === 5 : false;
}

Diese Methode hat meine Renderzeit erheblich verbessert

1
Guy Sopher

Webp-Erweiterung Erkennen und Ersetzen von JavaScript:

 async function supportsWebp() {
  if (!self.createImageBitmap) return false;

  const webpData = 'data:image/webp;base64,UklGRh4AAABXRUJQVlA4TBEAAAAvAAAAAAfQ//73v/+BiOh/AAA=';
  const blob = await fetch(webpData).then(r => r.blob());
  return createImageBitmap(blob).then(() => true, () => false);
}

(async () => {
  if(await supportsWebp()) {
    console.log('webp does support');
  }
  else {
    $('#banners .item').each(function(){
        var src=$(this).find('img').attr('src');
        src = src.replace(".webp", ".jpg");
        $(this).find('img').attr('src',src);
    });
    console.log('webp does not support');
  }
})();
1
Limitless isa

Mit der Antwort von @ Pointy ist dies für Angular 2+:

import { Injectable } from '@angular/core';
import { Subject }    from 'rxjs/Subject';

@Injectable()
export class ImageService {
    private isWebpEnabledSource = new Subject<boolean>();

    isWebpEnabledAnnounced$ = this.isWebpEnabledSource.asObservable();

    isWebpEnabled() {
        let webpImage = new Image();

        webpImage.src = 'data:image/webp;base64,UklGRjIAAABXRUJQVlA4ICYAAACyAgCdASoCAAEALmk0mk0iIiIiIgBoSygABc6zbAAA/v56QAAAAA==';

        webpImage.onload = () => {
            if (webpImage.width === 2 && webpImage.height === 1) {
                this.isWebpEnabledSource.next(true);
            } else {
                this.isWebpEnabledSource.next(false);
            }
        }
    }
}
1
Serj Sagan

Wir können diese JS verwenden, für welchen Browser die Webp-Erweiterung erkannt wird. Wir können Klasse in HTML-Tag bekommen. Basierend auf dem Unterricht können wir ein Hintergrundbild einstellen.

<html lang="en-US" class="webp webp-alpha webp-animation webp-lossless"></html>

Wenn Browser nicht unterstützt wird

<html lang="en-US" class="no-webp"></html>

JS ist hier.

!function(e,A,n){var o=[],a=[],t={_version:"3.6.0",_config:{classPrefix:"",enableClasses:!0,enableJSClass:!0,usePrefixes:!0},_q:[],on:function(e,A){var n=this;setTimeout(function(){A(n[e])},0)},addTest:function(e,A,n){a.Push({name:e,fn:A,options:n})},addAsyncTest:function(e){a.Push({name:null,fn:e})}},i=function(){};function s(e,A){return typeof e===A}i.prototype=t,i=new i;var l,r,f=A.documentElement,u="svg"===f.nodeName.toLowerCase();function c(e){var A=f.className,n=i._config.classPrefix||"";if(u&&(A=A.baseVal),i._config.enableJSClass){var o=new RegExp("(^|\\s)"+n+"no-js(\\s|$)");A=A.replace(o,"$1"+n+"js$2")}i._config.enableClasses&&(A+=" "+n+e.join(" "+n),u?f.className.baseVal=A:f.className=A)}function p(e,A){if("object"==typeof e)for(var n in e)l(e,n)&&p(n,e[n]);else{var o=(e=e.toLowerCase()).split("."),a=i[o[0]];if(2==o.length&&(a=a[o[1]]),void 0!==a)return i;A="function"==typeof A?A():A,1==o.length?i[o[0]]=A:(!i[o[0]]||i[o[0]]instanceof Boolean||(i[o[0]]=new Boolean(i[o[0]])),i[o[0]][o[1]]=A),c([(A&&0!=A?"":"no-")+o.join("-")]),i._trigger(e,A)}return i}l=s(r={}.hasOwnProperty,"undefined")||s(r.call,"undefined")?function(e,A){return A in e&&s(e.constructor.prototype[A],"undefined")}:function(e,A){return r.call(e,A)},t._l={},t.on=function(e,A){this._l[e]||(this._l[e]=[]),this._l[e].Push(A),i.hasOwnProperty(e)&&setTimeout(function(){i._trigger(e,i[e])},0)},t._trigger=function(e,A){if(this._l[e]){var n=this._l[e];setTimeout(function(){var e;for(e=0;e<n.length;e++)(0,n[e])(A)},0),delete this._l[e]}},i._q.Push(function(){t.addTest=p}),i.addAsyncTest(function(){var e=[{uri:"data:image/webp;base64,UklGRiQAAABXRUJQVlA4IBgAAAAwAQCdASoBAAEAAwA0JaQAA3AA/vuUAAA=",name:"webp"},{uri:"data:image/webp;base64,UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAABBxAR/Q9ERP8DAABWUDggGAAAADABAJ0BKgEAAQADADQlpAADcAD++/1QAA==",name:"webp.alpha"},{uri:"data:image/webp;base64,UklGRlIAAABXRUJQVlA4WAoAAAASAAAAAAAAAAAAQU5JTQYAAAD/////AABBTk1GJgAAAAAAAAAAAAAAAAAAAGQAAABWUDhMDQAAAC8AAAAQBxAREYiI/gcA",name:"webp.animation"},{uri:"data:image/webp;base64,UklGRh4AAABXRUJQVlA4TBEAAAAvAAAAAAfQ//73v/+BiOh/AAA=",name:"webp.lossless"}],A=e.shift();function n(e,A,n){var o=new Image;function a(A){var a=!(!A||"load"!==A.type)&&1==o.width;p(e,"webp"===e&&a?new Boolean(a):a),n&&n(A)}o.onerror=a,o.onload=a,o.src=A}n(A.name,A.uri,function(A){if(A&&"load"===A.type)for(var o=0;o<e.length;o++)n(e[o].name,e[o].uri)})}),function(){var e,A,n,t,l,r;for(var f in a)if(a.hasOwnProperty(f)){if(e=[],(A=a[f]).name&&(e.Push(A.name.toLowerCase()),A.options&&A.options.aliases&&A.options.aliases.length))for(n=0;n<A.options.aliases.length;n++)e.Push(A.options.aliases[n].toLowerCase());for(t=s(A.fn,"function")?A.fn():A.fn,l=0;l<e.length;l++)1===(r=e[l].split(".")).length?i[r[0]]=t:(!i[r[0]]||i[r[0]]instanceof Boolean||(i[r[0]]=new Boolean(i[r[0]])),i[r[0]][r[1]]=t),o.Push((t?"":"no-")+r.join("-"))}}(),c(o),delete t.addTest,delete t.addAsyncTest;for(var d=0;d<i._q.length;d++)i._q[d]();e.Modernizr=i}(window,document);
0

Meine Kurzversion. Ich benutze es, um Browser WebP oder JPG/PNG zu geben.

Google esse das und das alte iPhone (f̶u̶c̶k̶i̶n̶g̶ ̶s̶h̶e̶e̶t̶ -safari) funktioniert auch super!

function checkWebP(callback) {
    var webP = new Image();
    webP.onload = webP.onerror = function () {
        callback(webP.height == 2);
    };
    webP.src = 'data:image/webp;base64,UklGRjoAAABXRUJQVlA4IC4AAACyAgCdASoCAAIALmk0mk0iIiIiIgBoSygABc6WWgAA/veff/0PP8bA//LwYAAA';
};

checkWebP(function(support) {
      if(support) {
          //Do what you whant =)
         console.log('work webp');
      }else{
          //Do what you whant =)
         console.log('not work, use jgp/png')
      }
      
})
0
Alexander Sanik

Da einige alte Browser teilweise Unterstützung für webp haben, ist es besser, genauer zu bestimmen, welche Webp-Funktion Sie verwenden möchten, und diese spezielle Funktion zu erkennen. Hier ist Googles offizielle Empfehlung , wie Sie erkennen eine spezifische webp-funktion:

// check_webp_feature:
//   'feature' can be one of 'lossy', 'lossless', 'alpha' or 'animation'.
//   'callback(feature, result)' will be passed back the detection result (in an asynchronous way!)
function check_webp_feature(feature, callback) {
    var kTestImages = {
        lossy: "UklGRiIAAABXRUJQVlA4IBYAAAAwAQCdASoBAAEADsD+JaQAA3AAAAAA",
        lossless: "UklGRhoAAABXRUJQVlA4TA0AAAAvAAAAEAcQERGIiP4HAA==",
        alpha: "UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAARBxAR/Q9ERP8DAABWUDggGAAAABQBAJ0BKgEAAQAAAP4AAA3AAP7mtQAAAA==",
        animation: "UklGRlIAAABXRUJQVlA4WAoAAAASAAAAAAAAAAAAQU5JTQYAAAD/////AABBTk1GJgAAAAAAAAAAAAAAAAAAAGQAAABWUDhMDQAAAC8AAAAQBxAREYiI/gcA"
    };
    var img = new Image();
    img.onload = function () {
        var result = (img.width > 0) && (img.height > 0);
        callback(feature, result);
    };
    img.onerror = function () {
        callback(feature, false);
    };
    img.src = "data:image/webp;base64," + kTestImages[feature];
}

// example usage
check_webp_feature('lossy', function (feature, isSupported) {
    if (isSupported) {
        // web is supported
    }
});

Beachten Sie, dass das Laden von Bildern nicht blockiert und asynchronous ist. Das bedeutet, dass jeder Code, der von der WebP-Unterstützung abhängig ist, vorzugsweise in die Rückruffunktion eingefügt werden sollte.

Beachten Sie auch, dass andere synchrone Lösungen mit Firefox 65 nicht gut funktionieren 

0
AbdelHady