首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >预加载图片,使用图片标签防止闪烁

预加载图片,使用图片标签防止闪烁
EN

Stack Overflow用户
提问于 2021-02-23 02:24:24
回答 1查看 45关注 0票数 0

在我的代码中,我有一个标签图片,我更改了它的内容,以便加载其他图像。但我注意到它在闪烁。这是我的玩具代码。

代码语言:javascript
复制
setTimeout(replaceImage,3000);

function replaceImage(){
let pictureNode = document.getElementById('picture-carousel');

let markup = `
               <source media="(min-width:50em)" srcset="http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/debris2_blue.png">
                
                  <source media="(min-width:25em)" srcset="http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/debris2_brown.png"> 
                  <source  srcset="http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/debris3_blue.png"> 
                  <img src='http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/debris2_blue.png' title='Bla bla' alt='bla bla'>
`

pictureNode.innerHTML = markup;
}
代码语言:javascript
复制
<div>
<picture id='picture-carousel'>
                  <source media="(min-width:50em)" srcset="http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/asteroid_blend.png">
                
                  <source media="(min-width:25em)" srcset="http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/asteroid_blue.png"> 
                  <source  srcset="http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/asteroid_brown.png"> 
                  <img src='http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/asteroid_blend.png' title='Bla bla' alt='bla bla'> <!--  fallback -->
               </picture>
               </div>

我知道为了避免图像闪烁,我可以像这样预加载图像:

代码语言:javascript
复制
function loadImage(){
var img = new Image(),
x=document.getElementById('myImg');
img.onload=function(){
  x.src = img.src;
}

img.src ='http://codeskulptor-demos.commondatastorage.googleapis.com/GalaxyInvaders/back03.jpg'; //  this is the new url img to load';
}
代码语言:javascript
复制
<img src='http://codeskulptor-demos.commondatastorage.googleapis.com/GalaxyInvaders/back02.jpg' id='myImg'>

<button onclick='loadImage();'>Load new Image</button>

当我使用图片标签而不是img标签时,我如何预加载图片?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-02-23 03:27:44

以数据的形式构造<picture>元素。这样,我们就可以构建一个接收数据并逐段构建元素的函数。

执行此操作时,我们可以检查每个单独<source>标记的media值。有了这个值,我们就可以运行window.matchMedia()来确定元素上的媒体查询是否与当前视图匹配。例如,您可以检查min-width: 50em当前是否为真。

有了这些知识,您就可以确定要预加载哪个映像。您只需加载与媒体查询匹配的图像。

检查下面的示例,它完成了上面描述的过程。如果您有任何问题,请联系我们。

代码语言:javascript
复制
const pictureData = [
  {
    tag: 'source',
    attributes: {
      media: '(min-width: 50em)',
      srcset: 'http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/debris2_blue.png'
    }
  },
  {
    tag: 'source',
    attributes: {
      media: '(min-width: 25em)',
      srcset: 'http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/debris2_brown.png'
    }
  },
  {
    tag: 'source',
    attributes: {
      srcset: 'http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/debris3_blue.png'
    }
  },
  {
    tag: 'img',
    attributes: {
      src: 'http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/debris2_blue.png',
      title: 'Bla bla',
      alt: 'bla bla'
    }
  }
];

/**
 * Loads an image and returns a promise.
 * The promise will resolve on the load event of the image.
 */
const preloadImage = url => new Promise((resolve, reject) => {
  const image = new Image();
  image.onload = () => resolve();
  image.onerror = error => reject(error);
  image.src = url;
})

/**
 * Takes in an object of pictureData.
 * It then creates a <picture> element and the children specified in the object.
 * Whenever a tag is source, it will use the media value, if present,
 * to detect if the image is elligable to be loaded. 
 * If so it will preload the image and resolve the promise after it has been loaded.
 */
const buildPicture = async pictureData => {
  const picture = document.createElement('picture');
  let imageToPreload = null;

  // Loop through all the data and start constructing.
  for (const { tag, attributes } of pictureData) {
    const child = document.createElement(tag);
    
    if (imageToPreload === null) {
      // Check source tags for media queries.
      if (tag === 'source') {
        const { media, srcset } = attributes;
        
        // If there is a media query, check it.
        if (!media) {
          const { matches } = window.matchMedia(media);

          // If the query matches, use this as the image.
          if (matches === true) {
            imageToPreload = srcset;
          }

        // No media query found.
        } else {
          imageToPreload = srcset;
        }
      }

      // If no match has been found yet, just load the image.
      if (tag === 'img') {
        const { src } = attributes;
        imageToPreload = src;
      }
    }
    
    // Set all the properties and values of the attributes.
    for (const [ property, value ] of Object.entries(attributes)) {
      child.setAttribute(property, value);
    }

    picture.append(child);
  }

  if (imageToPreload !== null) {
    try {
      await preloadImage(imageToPreload);
    } catch (error) {
      console.error(error);
    }
  }

  return picture;
};

setTimeout(async () => {
  const currentPicture = document.getElementById('picture-carousel');
  const picture = await buildPicture(pictureData);
  currentPicture.replaceWith(picture);
}, 2000);
代码语言:javascript
复制
<picture id='picture-carousel'>
  <source media="(min-width:50em)" srcset="http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/asteroid_blend.png">
  <source media="(min-width:25em)" srcset="http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/asteroid_blue.png">
  <source srcset="http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/asteroid_brown.png">
  <img src='http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/asteroid_blend.png' title='Bla bla' alt='bla bla'>
  <!--  fallback -->
</picture>

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66321319

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档