JSZip 是一款可以創(chuàng )建、讀取、修改 .zip 文件的 javaScript 工具。在 web 應用中,免不了需要從 web 服務(wù)器中獲取資源,如果可以將所有的資源都合并到一個(gè) .zip 文件中,這時(shí)候只需要做一次請求,這樣既減少了服務(wù)器的壓力,同時(shí)也可以加快 web 應用的呈現速度。
今天就來(lái)探討下 JSZip 如何與 HT 拓撲應用結合。先來(lái)看看這期 Demo 的效果圖:
第一步、需要將應用對相關(guān)資源打包成 .zip 文件,
這是我要壓縮的文件列表,把響應的資源文件存放到對應的文件夾下,然后在 loadorder 文件中標明資源加載的順序,loadorder 文件內容如下:
在資源加載順序中,要標明響應資源的相對于 .zip 文件的路徑,這樣方便在讀取 .zip 文件時(shí)快速找到相應的資源文件。
第二步、在 html 文件中引入 JSZip 和 JSZipUtils 庫,接下來(lái)就是請求 .zip 文件,并對 .zip 文件做解析處理。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | JSZipUtils.getBinaryContent('res/ImportObj.zip', function(err, data) { if(err) { throw err; // or handle err } var zip = new JSZip(data); var loadorderStr = zip.file('loadorder').asText(), order; eval('order = [' + loadorderStr + ']'); var len = order.length, image = {}, mtlStr = '', objStr = ''; for(var i = 0; i < len; i++) { var fileName = order[i]; if(fileName.indexOf('js/') >= 0) { var js = document.createElement('script'); js.innerHTML = zip.file(fileName).asText(); document.getElementsByTagName('head')[0].appendChild(js); } else if(fileName.indexOf('image/') >= 0) { var buffer = zip.file(fileName).asArrayBuffer(), str = _arrayBufferToBase64(buffer), pIndex = fileName.indexOf('.'), type = fileName.substr(pIndex + 1), re = 'data:image/' + type + ';base64,'; image[fileName] = re + str; } else if(fileName.indexOf('obj/') >= 0) { var str = zip.file(fileName).asText(); if(fileName.indexOf('.mtl') > 0) { mtlStr = str; } else if(fileName.indexOf('.obj') > 0) { objStr = str; } } } init(objStr, mtlStr, image);}); |
首先通過(guò) JSZipUtils 獲取 .zip 文件,將獲取到的文件內容通過(guò) new JSZip(data) 方法加載到 zip 變量中,通過(guò) zip.file(fileName) 讀取 loadorder 文件內容,試用 eval 命令動(dòng)態(tài)執行腳本,將文本內容轉換為 js 變量 order,最后通過(guò)遍歷 order 變量,將 js 資源動(dòng)態(tài)引入到頁(yè)面中。
在 .zip 文件中有包含圖片文件,JSZip 只能獲取到圖片文件的 ArrayBuffer 數據,這時(shí)需要將 ArrayBuffer 轉換為 Base64 才能夠為瀏覽器所識別,所以這里定義了一個(gè)轉換函數:_arrayBufferToBase64
這次的案例中,有涉及到 3D 模型數據與 HT 3D 拓撲應用的結合,在 .zip 文件中的 obj 目錄就是存放 3D 模型數據,在文件讀取中,將 3D 模型數據以文本對形勢讀取出來(lái)存放到變量中,再將數據傳遞到 init 函數中,通過(guò) ht.Default.parseObj() 方法將 3D 模型數據加載到 HT 中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | function init(objStr, mtlStr, image) { dataModel = new ht.DataModel(); g3d = new ht.graph3d.Graph3dView(dataModel); view = g3d.getView(); view.className = 'main'; document.body.appendChild(view); window.addEventListener('resize', function (e) { g3d.invalidate(); }, false); g3d.setEye([0, 500, 1000]); g3d.setCenter([0, 200, 0]); g3d.setGridVisible(true); g3d.setGridColor('#74AADA'); var param = { shape3d: 'E1', center: true, cube: true }; var modelMap = ht.Default.parseObj(objStr, mtlStr, param); for(var model in modelMap) { var map = modelMap[model], i = map.image, index = i.lastIndexOf('/'), fileName = i.substr(index + 1), rawS3 = map.rawS3; for(var imgName in image) { if(imgName.indexOf(fileName) >= 0) { ht.Default.setImage(i, 256, 256, image[imgName]); } } } var node = new ht.Node(); node.s({ 'shape3d': 'E1', 'wf.visible': 'selected', 'wf.width': 3, 'wf.color': '#F7F691' }); node.s3(param.rawS3); node.p3(0, param.rawS3[1]/2, 0); dataModel.add(node);} |
上述是生成 3D 拓撲、3D 模型引入和引用 3D 模型創(chuàng )建拓撲節點(diǎn)的代碼。其中那段 setImage 的代碼需要特別注意,為什么我要大費周張的去判斷 image 的文件名呢,那是因為在 mtl 3D 模型描述文件中有一個(gè)設置貼圖的屬性,該屬性可以指定文件的絕對路徑,也可以指定文件的相對路徑,因為采用 JSZip 無(wú)法將 .zip 中的文件內容寫(xiě)回到本地目錄中,所以只能將貼圖屬性對應的屬性名稱(chēng)作為 HT 中的 image 名稱(chēng)設置到 HT 中,以便 HT 模型加載的時(shí)候能夠獲取得到模型所需要的圖片資源。HT 3D 拓撲的應用可以參考《3D拓撲自動(dòng)布局之Node.js篇》。
JSZip 在壓縮或解壓數據的時(shí)候,如果出現速度較慢的情況,可以考慮使用 Web Worker,Web Worker的具體應用可以參考《3D拓撲自動(dòng)布局之Web Workers篇》。
聯(lián)系客服