如何在javascript幻灯片中实现无缝显示

问题描述 投票:0回答:1

我用 JavaScript 编写了一个基本的幻灯片。它从 CGI 脚本中下载随机选择的 JPEG,必要时将其缩小,删除之前显示的幻灯片并在页面上显示新幻灯片,每两秒重复一次。

问题是某些 JPEG 非常大(从 3MB 到 20MB)。下载(以及我认为缩放)需要很长时间,有时,当删除上一张幻灯片时,会在下一张幻灯片出现之前花费几秒钟。

我确信这是因为处理的异步性质,但我不知道如何控制它。我希望每张幻灯片都显示至少两秒或足够长的时间,以便下一张幻灯片不会出现任何延迟。

(我在这个演示中使用了占位符图像生成器,所以我不知道它能如何很好地说明延迟问题。)

    function showSlides() {
        const my_img = document.createElement('img');
        fetch('https://picsum.photos/2000/600')
            .then(my_response => my_response.blob())
            .then(my_blob => {
                const my_url = URL.createObjectURL(my_blob);
                my_img.setAttribute('src', my_url);
                my_img.setAttribute('class', 'picture-div-img');
            })
            .catch(my_error => console.error('Error: ', my_error));

        /* NOTE: would like to wait until new slide is completely downloaded
           and rendered offscreen before deleting current slide and displaying
           new one */

        /* Delete current slide */
        const my_parent = document.querySelector('#slide-div');
        while (my_parent.firstChild) {
            my_parent.removeChild(my_parent.firstChild);
        }
        /* Insert new slide */
        my_parent.appendChild(my_img);
        setTimeout(showSlides, 2000); /* Change image every 2 seconds */
    }
    html {
        height: 100%;
        width: 100%;
    }

    body {
        /* prevent body from displacing */
        margin: 0;
        /* body should perfectly superimpose the html */
        height: 100%;
        width: 100%;
    }

    .outer-div {
        display: flex;
        flex-flow: column;
        height: 100%;
        /* Now create left/right margins */
        margin: 0 0.5em;
    }

    .inner-fixed-div {
        margin-top: 0.5em;
    }

    .inner-remaining-div {
        margin-bottom: 1em;
        flex-grow: 1;
        /* hints the contents to not overflow */
        overflow: hidden;
    }

    .picture-div {
        /* force the div to fill the available space */
        width: 100%;
        height: 100%;
    }

    .picture-div-img {
        /* force the image to stay true to its proportions */
        width: 100%;
        height: 100%;
        /* and force it to behave like needed */
        object-fit: scale-down;
        object-position: center;
    }
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">

</head>

<body onload="showSlides();">
  <div class="outer-div">
    <div class="inner-fixed-div">
      <h1>Lorem Ipsum</h1>
    </div>
    <div class="inner-remaining-div">
      <!-- This div will hold the <img> -->
      <div id="slide-div" class="picture-div">
      </div>
    </div> <!-- end of inner-remaining-div -->
  </div> <!-- end of outer-div -->
</body>
</html>

javascript asynchronous fetch-api
1个回答
0
投票

您是否尝试过将插入新幻灯片功能移至 .then 方法中?这将确保它在收到新图像之前不会执行任何操作。

function showSlides() {
    const my_img = document.createElement('img');
    fetch('https://picsum.photos/2000/600')
        .then(my_response => my_response.blob())
        .then(my_blob => {
            const my_url = URL.createObjectURL(my_blob);
            my_img.setAttribute('src', my_url);
            my_img.setAttribute('class', 'picture-div-img');

            const my_parent = document.querySelector('#slide-div');
            while (my_parent.firstChild) {
                my_parent.removeChild(my_parent.firstChild);
            }
            /* Insert new slide */
            my_parent.appendChild(my_img);
            setTimeout(showSlides, 2000); /* Change image every 2 seconds */
        })
        .catch(my_error => console.error('Error: ', my_error));
}
html {
    height: 100%;
    width: 100%;
}

body {
    /* prevent body from displacing */
    margin: 0;
    /* body should perfectly superimpose the html */
    height: 100%;
    width: 100%;
}

.outer-div {
    display: flex;
    flex-flow: column;
    height: 100%;
    /* Now create left/right margins */
    margin: 0 0.5em;
}

.inner-fixed-div {
    margin-top: 0.5em;
}

.inner-remaining-div {
    margin-bottom: 1em;
    flex-grow: 1;
    /* hints the contents to not overflow */
    overflow: hidden;
}

.picture-div {
    /* force the div to fill the available space */
    width: 100%;
    height: 100%;
}

.picture-div-img {
    /* force the image to stay true to its proportions */
    width: 100%;
    height: 100%;
    /* and force it to behave like needed */
    object-fit: scale-down;
    object-position: center;
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">

</head>

<body onload="showSlides();">
  <div class="outer-div">
    <div class="inner-fixed-div">
      <h1>Lorem Ipsum</h1>
    </div>
    <div class="inner-remaining-div">
      <div id="slide-div" class="picture-div">
      </div>
    </div>
  </div>
</body>
</html>

© www.soinside.com 2019 - 2024. All rights reserved.