javascript 网页加载大图像,看起来好像图像没有加载,标题/图像不匹配

slmsl1lt  于 2023-03-11  发布在  Java
关注(0)|答案(1)|浏览(153)

这是一个棘手的问题,可能不容易解决。
问题是,以我们现时的系统来说,这些图片/照片是非常大的,例如每张5 MB或6 MB,而且每隔数天便会由不同的小组上载。即使我们可以要求后端小组有一个系统,稍后将它们转换成缩略图及较小的图片,例如50 KB或150 KB,但这可能仍需数月时间,而且并非我们所能控制。(另一点是,当我们让用户在模态中预览这些照片时,我们可能希望给予他们全尺寸的图像,而不是压缩的图像)。
如果我们使用vanilla JavaScript加载第二张图像,例如在网页上的图像预览模式中,当用户点击“切换”以查看下一张图像(再次切换以查看下一张图像)时,会出现两个问题:
1.标题和图像彼此不匹配
1.用户无法知道图像正在加载,就好像点击后没有React一样
代码为:

document
          .querySelector("#toggle-button")
          .addEventListener("click", () => {
            toggle = !toggle;
            filename = `${toggle ? "beach.jpg" : "mountain.jpg"}?${Date.now()}`;
            elMsg.innerHTML = `<span>Title is ${
              toggle ? "Beach" : "Mountain and Lake"
            }</span>`;
            elImage.src = filename;
          });

你可以试试这里的代码:
https://codesandbox.io/s/silly-haze-4uonqv?file=/index.html

为了使效果更明显,请转到Google Chrome上的DevTool,然后转到网络选项卡,并将“无节流”更改为“慢速3G”速度。

然后您将看到上面提到的问题#1和问题#2。
注意,这里我使用了Date.now()附加到文件名,因此图像URL为:
https://4uonqv.csb.app/beach.jpg?1678392429912
以便使该高速缓存崩溃,这是为了演示的目的以显示这两个问题。
如果我使用React也是一样的,代码如下:

function App() {
  const [toggle, setToggle] = useState(true);

  const imageFilename = `${
    toggle ? "beach.jpg" : "mountain.jpg"
  }?${Date.now()}`;

  return (
    <div className="App">
      <div id="msg">
        <span>toggle is {JSON.stringify(toggle)}</span>
        <span>imageFilename is {imageFilename}</span>
        <span>Title is {toggle ? "Beach" : "Mountain and Lake"}</span>
        <button onClick={() => setToggle((f) => !f)}>Toggle</button>
      </div>
      <img src={imageFilename} alt="a big file" />
    </div>
  );
}

您可以在这里尝试:
https://codesandbox.io/s/floral-resonance-elouv7
图片2(mountain.jpg)大约为1.5MB,如果文件大小为5 MB或6 MB,问题就更严重了。
那么什么是处理这个问题的好方法呢?如果可能的话,我希望不要使用复杂的方法,比如使用微调器,而是使用两步方法,也许首先显示一个空白的图像占位符,然后将src设置为新的占位符...因为对于只显示图像的目的来说,这是一种过度的做法。
如果是Vanilla JavaScript,我想到了一个快速的方法,那就是每次替换整个<img />

elImageContainer.innerHTML = `<img src="${filename}" />`;

你可以试试
https://codesandbox.io/s/objective-bhabha-imdipn
但是我不认为这可以在React中完成,这是项目正在使用的,因为我认为新的虚拟DOM已经创建,并且与以前的虚拟DOM不同,没有办法判断它是否是一个新的<img />元素,就像Vanilla JavaScript的情况一样。
有什么好的解决办法吗?

ecbunoof

ecbunoof1#

根据我上面的评论,我认为(至少)有3种简单的方法可以实现这一点

选项1

和你的后台团队一起工作,得到一些新的,更小的图片。这是非常合理的期望网站的图片被压缩;当然5+ MB对于大多数情况来说太大了。2大的图片会增加响应时间(正如你已经指出的),对于移动的用户来说,也会通过他们的Hive数据计划来花费他们的钱。3这是非常受欢迎的解决方案,会让你的网站的很多事情变得更容易和更好。4如果由于某种原因这是绝对不可能的...

选项2

如上所述,你可以预加载两个图像,但有一个隐藏。然后切换按钮只是切换哪一个是隐藏的。我分叉你的沙盒,使this one to demonstrate the idea
这仍然很简单,解决了视觉问题。但是,它迫使你在页面初始加载时加载两个图像,这会减慢你的加载速度。这对那些从来没有按下“切换”按钮的客户来说尤其糟糕--他们付出了数据和时间成本来加载一个他们甚至从未见过的图像。

选项3

如果您想保持现有的结构/流,可以订阅<img> onload事件,以便在加载新图像后只更新标题/描述。This StackOverflow对此有一些讨论。

相关问题