简体   繁体   English

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

[英]Efficient method of changing the image displayed on an <img>?

In javascript, I have a reference to a DOM <img> element. 在javascript中,我有一个DOM <img>元素的引用。 I need to change the image displayed by the <img> from within the javascript. 我需要在javascript中更改<img>显示的图像。

So far, I have tried this by changing the image.src attribute to the URL of the new image. 到目前为止,我已经通过将image.src属性更改为新图像的URL来尝试此操作。 This worked, but there is still a problem: I need the image to be changed many times per second, and changing the src attribute causes the browser to do a new GET request for the image (which is already cached), which puts strain on the web server since there will be hundreds of simultanious clients. 这有效,但仍然存在一个问题:我需要每秒更改图像多次,并且更改src属性会导致浏览器对图像(已经缓存)执行新的GET请求,这会给应变带来压力Web服务器,因为将有数百个同时发生的客户端。

My current (inefficient) solution is done like this: 我目前的(低效)解决方案是这样完成的:

 let image = document.querySelector("img"); setInterval(function(){ image.src = getNextImageURL();//this causes a GET request }, 10); function getNextImageURL() { /*...implementation...*/ } 
 <img> 

I am looking for a more efficient way of changing the image, that does not cause any unnecessary HTTP requests. 我正在寻找一种更有效的方式来更改图像,这不会导致任何不必要的HTTP请求。

I think you need to code in a different way... 我想你需要以不同的方式编码......

if you want to reduce requests you should combine all image in one sprite Sheet. 如果你想减少请求,你应该将所有图像组合在一个精灵表中。 this trick is used so many in-game animations. 这个技巧在游戏中使用了很多动画。 But you will need to change <img/> tag to another tag like <div></div> 但是您需要将<img/>标记更改为另一个标记,例如<div></div>

the idea here is that we have one image and we just change the viewport for what we want 这里的想法是我们有一个图像,我们只是改变我们想要的视口

sample For sprite sheet 样本用于精灵表

在此输入图像描述

 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*/ } 
 <div class="image"> </div> 

If the sprite-sheet idea doesn't work (eg because you have big images), then use a canvas . 如果精灵表的想法不起作用(例如,因为你有大图像),那么使用画布

You just need to preload all your images, store them in an Array and then draw them one after the other on your 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> 

And if you wish time control: 如果你希望时间控制:

 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> 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM