UNPKG

prophetk-3d-viewer

Version:

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

167 lines (147 loc) • 4.65 kB
function appendNoCacheParam(url) { const sep = url.indexOf('?') === -1 ? '?' : '&'; return url + sep + '_t=' + Date.now(); } function sanitizeCacheKey(key) { return key.replace(/[^a-zA-Z0-9_]/g, '_'); } class WechatPlatformAdapter { constructor(options = {}) { this.wx = options.wx || (typeof wx !== 'undefined' ? wx : null); this.canvas = options.canvas || null; if (!this.wx) throw new Error('WechatPlatformAdapter requires wx'); } getWindowInfo() { return this.wx.getWindowInfo(); } getPixelRatio() { const info = this.getWindowInfo(); return info.pixelRatio || 1; } getContext(canvas, type) { return canvas.getContext(type); } requestAnimationFrame(canvas, callback) { return canvas.requestAnimationFrame(callback); } cancelAnimationFrame(canvas, id) { canvas.cancelAnimationFrame(id); } createImage(canvas) { return canvas.createImage(); } createCanvas(width, height) { if (!this.wx.createOffscreenCanvas) { throw new Error('wx.createOffscreenCanvas is required for three.js UI textures'); } const canvas = this.wx.createOffscreenCanvas({ type: '2d', width, height }); canvas.width = width; canvas.height = height; return canvas; } requestJson(url) { return new Promise((resolve, reject) => { this.wx.request({ url, dataType: 'json', header: { 'Cache-Control': 'no-cache', Pragma: 'no-cache', }, success: (res) => { try { resolve(typeof res.data === 'string' ? JSON.parse(res.data) : res.data); } catch (e) { reject(e); } }, fail: reject, }); }); } fetchFile(sourceUrl, options = {}) { const url = options.url || sourceUrl; // Packaged paths are relative to the Mini Program root, not this JS file. // Local files bypass downloading and the remote-file cache. if (!/^https?:\/\//i.test(url)) { return Promise.resolve(url.split(/[?#]/)[0].replace(/^\.\//, '')); } const shouldCache = options.shouldCache !== false; const cacheKey = options.cacheKey || sourceUrl; return new Promise((resolve, reject) => { const cached = shouldCache ? this._getCachedPath(cacheKey) : ''; if (cached) return resolve(cached); this.wx.downloadFile({ url: shouldCache ? url : appendNoCacheParam(url), header: shouldCache ? undefined : { 'Cache-Control': 'no-cache', Pragma: 'no-cache', }, success: (res) => { if (res.statusCode !== 200) { reject(new Error('Download failed: ' + res.statusCode)); return; } if (!shouldCache) { resolve(res.tempFilePath); return; } const fs = this.wx.getFileSystemManager(); const ext = sourceUrl.split('?')[0].split('.').pop(); const dest = this.wx.env.USER_DATA_PATH + '/' + sanitizeCacheKey(cacheKey) + '.' + ext; try { fs.copyFileSync(res.tempFilePath, dest); this.wx.setStorageSync(cacheKey, dest); resolve(dest); } catch (e) { resolve(res.tempFilePath); } }, fail: reject, }); }); } fetchArrayBuffer(sourceUrl, options = {}) { return this.fetchFile(sourceUrl, options).then((filePath) => { return new Promise((resolve, reject) => { this.wx.getFileSystemManager().readFile({ filePath, success: (res) => resolve(res.data), fail: reject, }); }); }); } readFileBase64(filePath) { return new Promise((resolve, reject) => { this.wx.getFileSystemManager().readFile({ filePath, encoding: 'base64', success: (res) => resolve(res.data), fail: reject, }); }); } readTextFile(filePath) { return new Promise((resolve, reject) => { this.wx.getFileSystemManager().readFile({ filePath, encoding: 'utf8', success: (res) => resolve(res.data), fail: reject, }); }); } _getCachedPath(cacheKey) { let cached = ''; try { cached = this.wx.getStorageSync(cacheKey); } catch (e) {} if (!cached) return ''; try { this.wx.getFileSystemManager().accessSync(cached); return cached; } catch (e) { return ''; } } } module.exports = WechatPlatformAdapter;