【问题标题】:how to detect that avif is supported or not in reactjs?如何检测在 reactjs 中是否支持 avif?
【发布时间】:2021-12-23 20:09:15
【问题描述】:

我正在尝试通过将图像格式化为 avif 来优化图像。但是有些浏览器不支持avif。

所以我创建了一个这样的实用函数

  function isAvifSupported() {
    let returnValue;
    const avif = new Image();
    avif.src =
      "data:image/avif;base64,AAAAIGZ0eXBhdmlmAAAAAGF2aWZtaWYxbWlhZk1BMUIAAADybWV0YQAAAAAAAAAoaGRscgAAAAAAAAAAcGljdAAAAAAAAAAAAAAAAGxpYmF2aWYAAAAADnBpdG0AAAAAAAEAAAAeaWxvYwAAAABEAAABAAEAAAABAAABGgAAAB0AAAAoaWluZgAAAAAAAQAAABppbmZlAgAAAAABAABhdjAxQ29sb3IAAAAAamlwcnAAAABLaXBjbwAAABRpc3BlAAAAAAAAAAIAAAACAAAAEHBpeGkAAAAAAwgICAAAAAxhdjFDgQ0MAAAAABNjb2xybmNseAACAAIAAYAAAAAXaXBtYQAAAAAAAAABAAEEAQKDBAAAACVtZGF0EgAKCBgANogQEAwgMg8f8D///8WfhwB8+ErK42A=";
    avif.onload = function () {
        returnValue = true
    };
    return returnValue;
  }

但是当我尝试调用这个函数时,它总是返回未定义。但是当我使用avif站点中提供的功能时。它工作正常。下面是它的代码

function AddClass(class) { document.documentElement.classList.add(class) };
var avif = new Image();
avif.src = "data:image/avif;base64,AAAAIGZ0eXBhdmlmAAAAAGF2aWZtaWYxbWlhZk1BMUIAAADybWV0YQAAAAAAAAAoaGRscgAAAAAAAAAAcGljdAAAAAAAAAAAAAAAAGxpYmF2aWYAAAAADnBpdG0AAAAAAAEAAAAeaWxvYwAAAABEAAABAAEAAAABAAABGgAAAB0AAAAoaWluZgAAAAAAAQAAABppbmZlAgAAAAABAABhdjAxQ29sb3IAAAAAamlwcnAAAABLaXBjbwAAABRpc3BlAAAAAAAAAAIAAAACAAAAEHBpeGkAAAAAAwgICAAAAAxhdjFDgQ0MAAAAABNjb2xybmNseAACAAIAAYAAAAAXaXBtYQAAAAAAAAABAAEEAQKDBAAAACVtZGF0EgAKCBgANogQEAwgMg8f8D///8WfhwB8+ErK42A=";
avif.onload = function () { AddClass("avif") };
avif.onerror = function () {
  var webp = new Image();
  webp.src = "data:image/webp;base64,UklGRhoAAABXRUJQVlA4TA0AAAAvAAAAEAcQERGIiP4HAA==";
  webp.onload = function () { AddClass("webp") }
}

但是上面定义的函数在dom的顶层添加了css。它必须返回 true 或 false,而不是添加类。这样我就可以轻松处理了。


let updatedImageUrl = isAvifSupported() ? `${imageUrl}?fm=avif` ? imageUrl

但我不知道,如何解决这个问题。请推荐一个解决方案。

【问题讨论】:

    标签: reactjs contentful avif


    【解决方案1】:

    以下功能可以正常工作。这是@Stefan Judis 的扩展答案版本。我根据我的项目修改了这个

    import React, { useEffect, useState } from "react";
    import "./styles.css";
    
    const url =
      "https://images.ctfassets.net/{space_id}/1WJFyl9C8q18KI6OQG7mPu/{unique_name}/name.jpg";
    
    const ImageFormat = () => {
      const [imageFormat, setImageFormat] = useState("");
    
      function addImageProcess(src) {
        return new Promise((resolve, reject) => {
          let img = new Image();
          img.onload = () => resolve("avif");
          img.onerror = () => {
            const webp = new Image();
            webp.src =
              "data:image/webp;base64,UklGRhoAAABXRUJQVlA4TA0AAAAvAAAAEAcQERGIiP4HAA==";
            webp.onload = async () => {
              resolve("webp");
            };
    
            webp.onerror = () => {
              reject("");
            };
          };
          img.src = src;
        });
      }
    
      useEffect(() => {
        async function logImageFormat(imageUrl) {
          let imageFormatValue = await addImageProcess(imageUrl);
          setImageFormat(`${url}?fm=${imageFormatValue}&w=3500`);
        }
    
        logImageFormat(
          "data:image/avif;base64,AAAAIGZ0eXBhdmlmAAAAAGF2aWZtaWYxbWlhZk1BMUIAAADybWV0YQAAAAAAAAAoaGRscgAAAAAAAAAAcGljdAAAAAAAAAAAAAAAAGxpYmF2aWYAAAAADnBpdG0AAAAAAAEAAAAeaWxvYwAAAABEAAABAAEAAAABAAABGgAAAB0AAAAoaWluZgAAAAAAAQAAABppbmZlAgAAAAABAABhdjAxQ29sb3IAAAAAamlwcnAAAABLaXBjbwAAABRpc3BlAAAAAAAAAAIAAAACAAAAEHBpeGkAAAAAAwgICAAAAAxhdjFDgQ0MAAAAABNjb2xybmNseAACAAIAAYAAAAAXaXBtYQAAAAAAAAABAAEEAQKDBAAAACVtZGF0EgAKCBgANogQEAwgMg8f8D///8WfhwB8+ErK42A="
        );
      }, []);
    
      return (
        <>
          <div className="App">{imageFormat}</div>
        </>
      );
    };
    
    export default ImageFormat;
    
    

    【讨论】:

      【解决方案2】:

      您的 sn-p 的主要问题是您没有考虑异步调用。

      onload 将在函数返回后被调用。要解决此问题,您必须提供回调并实现如下示例所示的 Promise。

      function isAvifSupported() {
        return new Promise(resolve => {
            var image = new Image();
        
            image.onload = image.onerror = function() {
              resolve(image.width === 2);
            };
        
            image.src = "data:image/avif;base64,AAAAIGZ0eXBhdmlmAAAAAGF2aWZtaWYxbWlhZk1BMUIAAADybWV0YQAAAAAAAAAoaGRscgAAAAAAAAAAcGljdAAAAAAAAAAAAAAAAGxpYmF2aWYAAAAADnBpdG0AAAAAAAEAAAAeaWxvYwAAAABEAAABAAEAAAABAAABGgAAAB0AAAAoaWluZgAAAAAAAQAAABppbmZlAgAAAAABAABhdjAxQ29sb3IAAAAAamlwcnAAAABLaXBjbwAAABRpc3BlAAAAAAAAAAIAAAACAAAAEHBpeGkAAAAAAwgICAAAAAxhdjFDgQ0MAAAAABNjb2xybmNseAACAAIAAYAAAAAXaXBtYQAAAAAAAAABAAEEAQKDBAAAACVtZGF0EgAKCBgANogQEAwgMg8f8D///8WfhwB8+ErK42A=";
          });
      }
      
      isAvifSupported().then(console.log);
      

      作为灵感,我调整了the standard modernizrsn-p 以适合您的用例并使用了您的虚拟图像。

      请记住,由于您必须使用异步调用,因此功能检测也必须是异步的。

      isAvifSupported().then(
        isSupported => {
          const updatedImageUrl = isSupported ?
            `${imageUrl}?fm=avif` :
            imageUrl;
        }
      );
      

      根据您的项目,您可能需要重构一些东西来实现承诺(或回调)解决方案,但不幸的是,无法同步检查 avif 支持。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-06-10
        • 2019-12-27
        • 2018-05-01
        相关资源
        最近更新 更多