Détection du support WebP

Comment puis-je détecter la prise en charge de WebP via Javascript? Je voudrais utiliser la détection des fonctionnalités plutôt que la détection du navigateur si possible, mais je ne peux pas trouver un moyen de le faire. Modernizr ( www.modernizr.com ) ne vérifie pas.

46
demandé sur Gant 2011-04-07 01:20:21

12 réponses

Je pense que quelque chose comme ça pourrait fonctionner:

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

Dans Firefox et IE, le gestionnaire" onload "ne sera tout simplement pas appelé du tout si l'image ne peut pas être comprise, et le" onerror " est appelé à la place.

Vous N'avez pas mentionné jQuery, mais comme exemple de gestion de la nature asynchrone de cette vérification, vous pouvez renvoyer un objet jQuery "différé":

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

Alors vous pourriez écrire:

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

Voici un exemple jsfiddle.


Un plus avancé vérificateur: http://jsfiddle.net/JMzj2/29/. celui-ci charge des images à partir d'une URL de données et vérifie s'il se charge avec succès. Étant donné que WebP prend également en charge les images sans perte, vous pouvez vérifier si le navigateur actuel prend en charge simplement WEBP avec perte ou WebP sans perte. (Remarque: cela vérifie implicitement également la prise en charge des URL de données.)

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");
});
41
répondu Pointy 2012-08-18 12:01:20

C'est ma solution - prend environ 6ms et je considère que WebP n'est qu'une fonctionnalité pour un navigateur moderne. Utilise une approche différente en utilisant canvas.toDataUrl () fonction au lieu de l'image comme moyen de détecter la fonctionnalité:

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;
    }
    else {
        // very old browser like IE 8, canvas not supported
        return false;
    }
}
46
répondu Rui Marques 2014-12-01 16:23:28

C'est une vieille question, mais Modernizr prend désormais en charge la détection Webp.

Http://modernizr.com/download/

Recherchez img-webp sous détecte Non-core.

10
répondu Jake Wilson 2014-06-23 22:05:53

WebPJS utilise une détection plus intelligente du support WebP sans aucune image externe requise: http://webpjs.appspot.com/

5
répondu unxed 2011-11-20 07:35:09

Voici le code sans avoir à demander une image (partiellement prise de webpjs.appspot.com)

Jsfiddle

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

function notify(supported) {
  console.log((supported) ? "webP supported!" : "webP not supported.");
}

testWebP(notify);​
3
répondu James Westgate 2012-06-07 10:58:13

J'ai trouvé que la fonctionnalité de support webp détecte nécessite plus de 300 ms lorsque la page est lourde en JavaScript. J'ai donc écrit un script avec des fonctionnalités de mise en cache:

  • cache de script
  • cache localstorage

Il ne détectera qu'une seule fois lorsque l'utilisateur accède pour la première fois à la page.

/**
 * @fileOverview WebP Support Detect.
 * @author ChenCheng<sorrycc@gmail.com>
 */
(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
répondu sorrycc 2013-04-09 09:25:47

Solution Préférée dans HTML5

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

Wiki sur le W3C

3
répondu Andrei Krasutski 2018-02-09 08:28:46

Images WebP avec htaccess

Placez ce qui suit dans votre fichier .htaccess et les images jpg/png seront remplacées par des images WebP si elles se trouvent dans le même dossier.

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

Lire plus ici

1
répondu Andrei Krasutski 2017-10-28 18:11:18

, Il existe un moyen de tester webP soutien instantanément. Il est synchronisé et précis, il n'est donc pas nécessaire d'attendre un rappel pour rendre les images.

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

Cette méthode a considérablement amélioré mon temps de rendu

0
répondu Guy Sopher 2018-04-09 11:20:25

En utilisant la réponse de @Pointy c'est pour 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);
            }
        }
    }
}
0
répondu Serj Sagan 2018-05-09 05:52:36

L'extension WEBP détecte et remplace 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');
  }
})();
0
répondu Limitless isa 2018-07-09 16:46:23

Voici une fonction simple avec Promise basée sur la réponse de Pointy

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
  })
}
0
répondu Liron Navon 2018-08-05 13:27:15