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 模型載入的時候能夠獲取得到模型所需要的圖片資源。
原創文章,作者:投稿專員,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/215641.html