UNPKG

prophetk-3d-viewer

Version:

A Three.js r128 based GLB/GLTF model viewer for WeChat Mini Program and Web.

132 lines (114 loc) • 4.03 kB
class WebPlatformAdapter { constructor(options = {}) { this.window = options.window || (typeof window !== 'undefined' ? window : null); this.document = options.document || (typeof document !== 'undefined' ? document : null); this._fileCache = new Map(); } getWindowInfo() { const win = this.window || {}; return { pixelRatio: win.devicePixelRatio || 1, windowWidth: win.innerWidth || 300, windowHeight: win.innerHeight || 150, }; } getPixelRatio() { return this.getWindowInfo().pixelRatio; } getContext(canvas, type) { return canvas.getContext(type); } requestAnimationFrame(canvas, callback) { const raf = this.window && this.window.requestAnimationFrame; return raf ? raf.call(this.window, callback) : setTimeout(callback, 16); } cancelAnimationFrame(canvas, id) { const caf = this.window && this.window.cancelAnimationFrame; if (caf) caf.call(this.window, id); else clearTimeout(id); } createImage() { const img = new Image(); img.crossOrigin = 'anonymous'; return img; } createCanvas(width, height) { const canvas = this.document.createElement('canvas'); canvas.width = width; canvas.height = height; return canvas; } requestJson(url) { return fetch(url, { cache: 'no-store', headers: { 'Cache-Control': 'no-cache', Pragma: 'no-cache', }, }).then((res) => { if (!res.ok) throw new Error('Request failed: ' + res.status); return res.json(); }); } fetchFile(sourceUrl, options = {}) { const shouldCache = options.shouldCache !== false; const url = options.url || sourceUrl; const cacheKey = options.cacheKey || sourceUrl; if (shouldCache && this._fileCache.has(cacheKey)) { const entry = this._fileCache.get(cacheKey); if (!entry.objectUrl) entry.objectUrl = URL.createObjectURL(entry.blob); return Promise.resolve(entry.objectUrl); } return fetch(url, { cache: shouldCache ? 'default' : 'no-store' }) .then((res) => { if (!res.ok) throw new Error('Download failed: ' + res.status); return res.blob(); }) .then((blob) => { const objectUrl = URL.createObjectURL(blob); if (shouldCache) { const old = this._fileCache.get(cacheKey); if (old) URL.revokeObjectURL(old.objectUrl); this._fileCache.set(cacheKey, { objectUrl, blob }); } return objectUrl; }); } fetchArrayBuffer(sourceUrl, options = {}) { const shouldCache = options.shouldCache !== false; const url = options.url || sourceUrl; const cacheKey = options.cacheKey || sourceUrl; if (shouldCache && this._fileCache.has(cacheKey)) { return this._fileCache.get(cacheKey).blob.arrayBuffer(); } return fetch(url, { cache: shouldCache ? 'default' : 'no-store' }) .then((res) => { if (!res.ok) throw new Error('Download failed: ' + res.status); return res.blob(); }) .then((blob) => { if (shouldCache) this._fileCache.set(cacheKey, { objectUrl: '', blob }); return blob.arrayBuffer(); }); } readFileBase64(objectUrl) { const entry = Array.from(this._fileCache.values()).find((item) => item.objectUrl === objectUrl); if (!entry) return Promise.reject(new Error('file is not cached as blob')); return new Promise((resolve, reject) => { const reader = new FileReader(); reader.onload = () => { const result = String(reader.result || ''); resolve(result.split(',')[1] || ''); }; reader.onerror = reject; reader.readAsDataURL(entry.blob); }); } dispose() { this._fileCache.forEach((entry) => { if (entry.objectUrl) URL.revokeObjectURL(entry.objectUrl); }); this._fileCache.clear(); } } module.exports = WebPlatformAdapter;