JSZip 是可以建立、讀取、修改 .zip 檔案的 javaScript 工具。在web 應用程式中,免不了需要從web 伺服器取得資源,如果可以將所有的資源都合併到一個.zip 檔案中,這時候只需要做一次請求,這樣既減少了伺服器的壓力,同時也可以加快web應用的呈現速度。
今天就來探討下 JSZip 如何與 #HT 應用結合。先來看看這期Demo 的效果圖:
第一步、需要將應用程式對相關資源打包成.zip 文件,
這是我要壓縮的檔案列表,把回應的資源檔案存放到對應的資料夾下,然後在loadorder 檔案中標示資源載入的順序,loadorder 檔案內容如下:
'js/ht.js', 'js/ht-obj.js', 'js/ht-modeling.js', 'obj/equipment.mtl', 'obj/equipment.obj', 'image/equipment.jpg'
在資源載入順序中,要標示回應資源的相對於.zip 檔案的路徑,這樣方便在讀取.zip 檔案時快速找到相應的資源文件。
第二步驟、在 html 檔案中引入 JSZip 和 JSZipUtils 函式庫,接下來就是請求 .zip 文件,並對 .zip 檔案做解析處理。
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); });
首先透過 JSZipUtils 取得.zip 文件,將取得的文件內容透過new JSZip(data) 方法載入到zip 變數中,透過zip.file(fileName) 讀取loadorder 檔案內容,試用eval 指令動態執行腳本,將文字內容轉換為js 變數order,最後透過遍歷order 變量,將js 資源動態引入頁面。
在.zip 檔案中有包含圖片文件,JSZip 只能取得到圖片檔案的ArrayBuffer 數據,這時需要將ArrayBuffer 轉換為Base64 才能夠為瀏覽器所識別,所以這裡定義了一個轉換函數:_arrayBufferToBase64
function _arrayBufferToBase64( buffer ) { var binary = ''; var bytes = new Uint8Array( buffer ); var len = bytes.byteLength; for (var i = 0; i < len; i++) { binary += String.fromCharCode( bytes[ i ] ); } return window.btoa( binary ); }
這次的案例中,有涉及3D 模型資料與 #HT 3D 拓樸應用的結合,在.zip 檔案中的obj 目錄就是存放3D 模型數據,在檔案讀取中,將3D 模型資料以文字對情勢讀取出來存放到變數中,再將資料傳遞到init 函數中,透過ht .Default.parseObj() 方法將3D 模型資料載入 HT 。
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 模型建立拓樸節點的程式碼。其中那段setImage 的程式碼需要特別注意,為什麼我要大費週張的去判斷image 的檔名呢,那是因為在mtl 3D 模型描述檔中有一個設定貼圖的屬性,該屬性可以指定檔案的絕對路徑,也可以指定檔案的相對路徑,因為採用JSZip 無法將.zip 中的檔案內容寫回本地目錄中,所以只能將貼圖屬性對應的屬性名稱當作 HT 中的image 名稱設定到HT 中,以便HT 模型載入的時候能夠取得得到模型所需的圖片資源。 HT 3D 拓樸的應用可以參考《3D拓樸自動版面之Node.js篇》。
JSZip 在壓縮或解壓縮資料的時候,如果出現速度較慢的情況,可以考慮使用 Web Worker。
#以上是Zip壓縮和解壓技術在HTML5中的應用的程式碼案例(圖)的詳細內容。更多資訊請關注PHP中文網其他相關文章!