如何实现图片预加载和加载进度条

发布时间 2023-09-24 12:55:54作者: 艾码的日常生活

很久没有发文了今天水一篇文章,图片预加载且展示加载的进度条,在现代的Web开发中,优化用户体验至关重要。一种常见的方法是在页面加载时预加载图片,并展示一个加载进度条,让用户了解加载进度。在本文中,我们将深入探讨如何实现这两个关键功能,以提高网站性能和用户满意度,首先谈一下我的思路:

创建一个函数用于new一个image对象,遍历需要预加载的图片数组,设置图片的src属性为传入的 URL,从而触发图片的加载,在每个图片加载成功后,用数组长度计算出百分比更新加载进度并将加载的图片添加到页面上,其中的我有一个我踩的坑需要注意一下

 

/**
 * 图片预加载
 */
export function preloadImage(url) {
    console.log(url)
  return new Promise((resolve, reject) => {
    const img = new Image();
    img.src = url;

    img.onload = () => {
      resolve(img);
    };

    img.onerror = (err) => {
      reject(err);
    };
  });
}

创建了一个 preloadImage 函数,它用于加载给定 URL 的图像。该函数返回一个 Promise,使异步处理图图片加载的成功或失败。

        data() {
            return {
                loadingProgress: 0, // 图片加载进度
            };
        },
        methods: {
            // 预加载
            async preloadImages() {
                const imageUrls = [
                    require('../../static/index/hone-rainbow.png'),
                    require('../../static/index/hone-bg.png'),
//...你的图片
                ];
                const totalImages = imageUrls.length;
                let loadedImages = 0;

                for (const imageUrl of imageUrls) {
                    try {
                        await preloadImage(imageUrl);
                        loadedImages++;
                        this.loadingProgress = (loadedImages / totalImages) * 100; // 更新进度
                    } catch (error) {
                        console.error(error);
                    }
                }
                // 判断是否首次访问,开启新手指引
                this.$nextTick(() => {
                    this.access()
                });
            },
                    },

在 preloadImages 函数中,定义一个数组 imageUrls,其中包含所有需要预加载的 URL。然后,通过遍历这个数组,使用 preloadImage 函数来预加载每个图像。在每个图像加载成功后,更新加载进度并将加载的图像添加到页面上,在页面中我使用了加载进度条来展示加载进度。进度条的百分比由 this.loadingProgress 控制,它在每个图片成功加载后被更新。通过监听 loadingProgress 的变化可以实时更新进度条,还有就是根据需要通过 try-catch 捕获可能的加载错误,在this.$nextTick中进行加载完成后需要进行的操作,确保是在进度条完成后正常运行

    <!-- 预加载页面 -->
    <view v-if="loadingProgress!==100" class="loading-main">
        <view class="loading-line-progress-box">
            <view class="loading-line-progress">
                <u-line-progress width="100" height="20" :percentage="loadingProgress" activeColor="#f9a431">
                    <text class="loading-u-percentage-slot">{{(loadingProgress || 0).toFixed(2)}}%</text>
                    <image v-if="loadingProgress!==0" class="loading-line-progress-logo"
                        src="@/static/index/line-progress-logo.png" mode=""></image>
                </u-line-progress>
            </view>
        </view>
    </view>
    <!-- 主页面 -->
    <view v-else class="content-main">
//加载完成后的页面
    </view>

html的话我这边使用的是uview的进度条组件,这里可以根据自己项目的需要进行调整,当图片加载完毕loadingProgress为一百时进度条页面消失展示主页

接下来记录一下我做这个功能踩的坑

const imageUrls = [
                    '../../static/index/hone-rainbow.png',
                    '../../static/index/hone-bg.png',
                ];

刚开始时我是直接写图片的相对路径,预加载出来的图片当然就是相对路径了,可是图片经过uniapp编译后不仅路径进行了改变,且会添加hash后缀防重名,如此一来之前预加载的图片当进入页面时肯定是用不了的浏览器会重新加载一次图片,这里就有两个方法解决,第一将图片放服务器中进行预加载同时可以减少前端打包的体积,第二种就是就是通过require包裹始终获取图片的真实路径,我这边项目体积并没有很大所以采用了第二种方法始终获取图片的真实路径,webpack构建工具负责将这些引用路径解析为真实的文件路径,因此可以专注于编写相对路径,不必担心最终的部署路径。