日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

offscreenCanvas+worker+IndexedDB实现无感大量图片缓存

發布時間:2023/11/18 windows 47 coder
生活随笔 收集整理的這篇文章主要介紹了 offscreenCanvas+worker+IndexedDB实现无感大量图片缓存 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一個有必要實現的需求

因為項目中需要使用canvasTexture(一個threejs3d引擎中的材質類型),繪制大量的圖片,每次使用都會請求大量的oss圖片資源,雖然重復請求會有磁盤緩存但畢竟這個磁盤緩存時效過短,

這里需要了解一下知識才能正常閱讀。

Transferable objects https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Transferable_objects

Web Worker https://developer.mozilla.org/zh-CN/docs/Web/API/Web_Workers_API

OffScreenCanvas https://developer.mozilla.org/zh-CN/docs/Web/API/OffscreenCanvas

需要注意項目所處瀏覽器環境是否支持其中的某些Api



  • 因為有了將有了將圖片緩存到本地的需求,那么大量的資源緩存必然是使用indexedDB了

  • 其次為了方便存儲和使用就需要將圖片專為Blob對象。我們如果在程序中批量的將 canvasTexture 輸出為圖片并專為Blob對象并存到本地的話,會因為大量長時間的占用主線程造成頁面渲染幀時隔過長,造成卡頓影響用戶體驗,

  • 那么我們就需要將canvasTexture輸出圖片和轉為Blob對象這個耗時的過程放到worker中進行

  • 而如果要在worker中進行操作我們需要用到OffScreenCanvas來進行圖片的繪制輸出和轉為Blob對象

  • 雖然worker可以傳遞OffScreenCanvas對象但是無法傳遞它的渲染空間Context所以我們只能在主線程中把canvasTexture中的畫面輸出為ArrayBuffer然后傳遞給worker中新創建的OffScreenCanvas然后通過OffScreenCanvas重新繪制并輸出為Blob對象返回給主線程進行存儲(ArrayBuffer,和 Blob都是可轉移對象Transferable object 所以我們不需要擔心它們的通信效率)自此這個流程就算完成了

這段代碼是對普通圖片進行緩存操作

    //此段以及下一段代碼中都使用了localforage(一個封裝了web端多個本地存儲策略的npm包)這個Api作為存儲策略
    setImageLocalCache(image, key) {
        const cacheKey = key
        const ofsCanvas = new OffscreenCanvas(image.width, image.height);
        let context = ofsCanvas.getContext('2d')
        context.drawImage(image, 0, 0, image.width, image.height)
        const imageData = context.getImageData(0, 0, ofsCanvas.width, ofsCanvas.height);
        const dataArray = imageData.data; //Unit8ClampedArray 
        const arrayBuffer = dataArray.buffer; // ArrayBuffer
        const worker = new Worker('worker/makeBlobCache.js')

        worker.postMessage({
            arrayBuffer,
            width: image.width,
            height: image.height
        }, [arrayBuffer])

        context.clearRect(0, 0, ofsCanvas.width, ofsCanvas.height)
        context = null

        worker.onmessage = (e) => {
            localforage.setItem(cacheKey, e.data).then(() => {
                URL.revokeObjectURL(URL.createObjectURL(e.data)) // 存儲結束后釋放Blob對象
            })
            worker.terminate(); //釋放worker線程
        }
    }

這段代碼是使用緩存的資源操作

    let blob = localforage.getItem(cacheKey)
    if(blob) {
      const image = new Image()
      image.src = URL.createObjectURL(blob)
      blob = null
      image.onerror = (e) => {
        console.log(e)
      }
      image.onload = () => {
        console.log('執行到這里圖片就加載完成了')
        URL.revokeObjectURL(url)
      }
    }

這段代碼是上述兩段代碼中的worker文件代碼

self.onmessage = (e) => {
    const arrayBuffer = e.data.arrayBuffer;
    const width = e.data.width;
    const height = e.data.height;
    const uint8View = new Uint8ClampedArray(arrayBuffer);

    const imageData = new ImageData(uint8View, width, height); 
    const offscreen = new OffscreenCanvas(width, height)
    let ctx = offscreen.getContext('2d')

    ctx.putImageData(imageData, 0, 0)
    offscreen.convertToBlob({
        type: 'image/png',
        quality: 1
    }).then(blob => {
        ctx.clearRect(0, 0, offscreen.width, offscreen.height);
        ctx = null;
        self.postMessage(blob)
    })

};

總結

以上是生活随笔為你收集整理的offscreenCanvas+worker+IndexedDB实现无感大量图片缓存的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。