微信小程序图片预加载-组件式写法

969 阅读2分钟

微信小程序图片预加载-组件式写法

微信小程序图片预加载不能用wx.getImageInfo获取图片信息,因为用wx.getImageInfo控制台network走的是xhr类型,xhr加载的图片,不算预加载。 所以image应该走的是png/jpg/gif类型

封装的预加载图片组件preload-images

index.wxml

<view class="container">
    <view wx:for="{{images}}" wx:for-item="image" wx:for-index="index" wx:key="index" class="image-wrapper" hidden="{{image.isHidden}}">
        <image src="{{image.src}}" bindload="onLoad" binderror="onError" data-index="{{index}}" />
    </view>
    <view class="status-text">{{status}}</view>
</view>

index.js

Component({
    properties: {
        images: {
            type: Array,
            value: [],
        },
    },

    data: {
        status: '',
        loadedImagesCount: 0,
        errorImages: [],
    },

    lifetimes: {
        attached() {
            this.initializeHiddenStatus();
        },
    },

    methods: {
        initializeHiddenStatus() {
            if (this.data.images.length === 0) return;

            const newImages = this.data.images.map((url) => ({
                src: url,
                isHidden: true,
            }));

            this.setData({
                images: newImages,
                status: '加载中...',
            });
        },

        updateStatus() {
            if (this.data.loadedImagesCount === this.data.images.length) {
                this.setData({ status: '加载完成' });
                this.triggerEvent('complete', { images: this.data.images, errorImages: this.data.errorImages });
            } else {
                this.setData({ status: `已加载 ${this.data.loadedImagesCount} / ${this.data.images.length}` });
                this.triggerEvent('process', `${parseInt((this.data.loadedImagesCount / this.data.images.length) * 100)}`);
            }
        },

        onLoad(e) {
            const index = e.currentTarget.dataset.index;
            this.data.images[index].isHidden = false;
            this.data.loadedImagesCount += 1;

            this.updateStatus();
            this.triggerEvent('load', e);
        },

        onError(e) {
            const index = e.currentTarget.dataset.index;
            this.data.errorImages.push(this.data.images[index]);

            this.data.loadedImagesCount += 1;
            this.updateStatus();

            this.triggerEvent('error', {
                event: e,
                image: this.data.images[index],
                errorImages: this.data.errorImages,
            });
        },
    },
});

index.wxss

/* components/preload-images/index.wxss */
.preloadContainer {
  display: flex;
  flex-wrap: wrap;
  position: absolute;
  left: -999999rpx;
  opacity: 0;
}

.image-wrapper {
  width: 33.33%; /* 调整图片显示大小和数量 */
  padding: 5px;
}

.image-wrapper image {
  width: 100%;
  height: auto;
}
.status-text {
  width: 100%;
  margin-top: 10px;
  text-align: center;
}

页面使用

test.wxml

<!-- 图片预加载 --> <preload-images wx:if="{{imageUrls.length > 0}}" images="{{imageUrls}}" bind:load="imgLoad" bind:complete="imgComplete" bind:process="imgProcess" bind:error="imgError"></preload-images>

test.js

const imageList = require("../../../utils/imageList.js");
const imagePreloader = require("../../../utils/image_preloader.js");

Page({
  /**
   * 页面的初始数据
   */
  data: {
    imageUrls: [],
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad(options) {
    this.initImgLoading();
   
  },


  //  预加载图片  three 图片文件夹
  initImgLoading() {
    const allImageUrls = imagePreloader.getAllImageUrls(imageList.images["three"]);
    this.setData({
      imageUrls: allImageUrls,
    });
  },

  imgLoad(e) {
    //console.log("加载中", e)
  },

  imgProcess(e) {
      console.log("图片加载进度");
    let { detail } = e;

  },

  imgComplete(e) {
    console.log("图片预加载成功", e);
    
  },

  imgError(e) {
    console.log(e, "==图片加载错误");
  },


});


utils

image_preloader.js

对图片做拼接处理

function preloadImages(imageUrls, onProgress) {
    let loadedCount = 0;
    const totalCount = imageUrls.length;

    return Promise.all(
        imageUrls.map(url =>
            new Promise((resolve, reject) => {
                wx.getImageInfo({
                    src: url,
                    success: () => {
                        loadedCount++;
                        onProgress((loadedCount / totalCount) * 100);
                        resolve(url);
                    },
                    fail: () => {
                        loadedCount++;
                        onProgress((loadedCount / totalCount) * 100);
                        reject(url);
                    },
                });
            })
        )
    );
}

function getAllImageUrls(images) {
    const urls = [];

    for (const key in images) {
        if (Array.isArray(images[key])) {
            urls.push(...images[key]);
        } else {
            urls.push(...getAllImageUrls(images[key]));
        }
    }

    return urls;
}

module.exports = {
    preloadImages: preloadImages,
    getAllImageUrls: getAllImageUrls,
};

imageList.js

配置图片路径

const app = getApp();
const { globalData } = app;
const prefix = globalData.imgCDN;  // 图片的cdn
const version = globalData.mathRom;//图片的版本号,用来清缓存

const imageFilenames = {
  three: {
    loading: ["bg.jpg", "i1.png", "logo.png"],
  },
 
};

function addPrefixToImages(obj, prefix, version) {
  const result = {};

  for (const key in obj) {
    if (Array.isArray(obj[key])) {
      result[key] = obj[key].map((filename) => prefix + key + "/" + filename + "?v=" + version);
    } else {
      result[key] = addPrefixToImages(obj[key], prefix + key + "/", version);
    }
  }

  return result;
}

const images = addPrefixToImages(imageFilenames, prefix, version);

module.exports = {
  images: images,
};