更改<img/>上显示的图像的有效方法?

时间:2019-04-04 21:28:27

标签: javascript html html5 image

在javascript中,我引用了DOM <img>元素。我需要在JavaScript中更改<img>显示的图像。

到目前为止,我已经通过将image.src属性更改为新图像的URL进行了尝试。这行得通,但是仍然存在一个问题:我需要每秒更改图像多次,并且更改src属性会导致浏览器对图像(已经缓存)进行新的GET请求,由于将有数百个同时进行的客户端,因此对Web服务器造成了压力。

我当前(低效)的解决方案是这样完成的:

let image = document.querySelector("img");

setInterval(function(){
    image.src = getNextImageURL();//this causes a GET request
}, 10);

function getNextImageURL() {
   /*...implementation...*/
}
<img>

我正在寻找一种更有效的更改图像的方法,该方法不会引起任何不必要的HTTP请求。

2 个答案:

答案 0 :(得分:3)

我认为您需要以其他方式进行编码...

如果要减少请求,则应将所有图像组合在一张Sprite Sheet中。 许多游戏内动画都使用了这个技巧。 但是您需要将 1 2 3 4 5 6 7 8 0 R 2654 R 1536 510 2590 2777 1677 1 1676 2824 3079 1677 R 3090 R 1709 2 2651 R 1677 1409 1664 2252 1710 1536 3 1676 1677 2085 R 1710 2916 3140 1963 标记更改为另一个标记,例如<img/>

这里的想法是我们只有一个图像,我们只是根据需要更改视口

用于精灵表的样本

enter image description here

<div></div>
let element = document.querySelector("div");
let i = 1
setInterval(function(){
    element.style.backgroundPosition= getNextImagePostion(i++);//this will change the posion
}, 100);

function getNextImagePostion(nextPos) {
   /*...implementation...*/

   // this just for try
   //  6 is the number of images in sheet
   // 20 is the height for one segment in sheet
   var posX = 100*(nextPos%6);

  // first is position on x and latter is position on y
   return "-"+posX+"px 0px ";
}
.image {
    width: 100px; /*  width of single image*/
    height: 100px; /*height of single image*/
    background-image: url(https://picsum.photos/500/100?image=8) /*path to your sprite sheet*/
}

答案 1 :(得分:2)

如果Sprite-sheet想法不起作用(例如,因为您的图片很大),请使用canvas

您只需要预加载所有图像,将它们存储在数组中,然后在画布上一个接一个地绘制它们即可:

const urls = new Array(35).fill(0).map((v, i) =>
  'https://picsum.photos/500/500?image=' + i
 );
// load all the images
const loadImg = Promise.all(
  urls.map(url => 
    new Promise((res, rej) => {
      // each url will have its own <img>
      const img = new Image();
      img.onload = e => res(img);
      img.onerror = rej;
      img.src = url;
    })
  )
);
// when they're all loaded
loadImg.then(imgs => {
  // prepare the canvas
  const canvas = document.getElementById('canvas');
  // set its size
  canvas.width = canvas.height = 500;
  // get the drawing context
  const ctx = canvas.getContext('2d');

  let i = 0;
  // start the animation
  anim();

  function anim() {
    // do it again at next screen refresh (~16ms on a 60Hz monitor)
    requestAnimationFrame(anim);
    // increment our index
    i = (i + 1) % imgs.length;
    // draw the required image
    ctx.drawImage(imgs[i], 0, 0);
  }
})
.catch(console.error);
<canvas id="canvas"></canvas>

如果您希望时间控制:

const urls = new Array(35).fill(0).map((v, i) =>
  'https://picsum.photos/500/500?image=' + i
 );
// load all the images
const loadImg = Promise.all(
  urls.map(url => 
    new Promise((res, rej) => {
      // each url will have its own <img>
      const img = new Image();
      img.onload = e => res(img);
      img.onerror = rej;
      img.src = url;
    })
  )
);
// when they're all loaded
loadImg.then(imgs => {
  // prepare the canvas
  const canvas = document.getElementById('canvas');
  // set its size
  canvas.width = canvas.height = 500;
  // get the drawing context
  const ctx = canvas.getContext('2d');

  const duration = 100; // the number of ms each image should last
  let i = 0;
  let lastTime = performance.now();

  // start the animation
  requestAnimationFrame(anim);

  // rAF passes a timestamp
  function anim(time) {
    // do it again at next screen refresh (~16ms on a 60Hz monitor)
    requestAnimationFrame(anim);

    const timeDiff = time - lastTime;
    if(timeDiff < duration) { // duration has not yet elapsed
      return;
    }
    // update lastTime
    lastTime = time - (timeDiff - duration);
    // increment our index
    i = (i + 1) % (imgs.length);
    // draw the required image
    ctx.drawImage(imgs[i], 0, 0);
  }
})
.catch(console.error);
<canvas id="canvas"></canvas>