【原創(chuàng)博文蟋座,轉(zhuǎn)載請(qǐng)注明出處褐澎!】
項(xiàng)目開(kāi)發(fā)中加載遠(yuǎn)程服務(wù)器圖片資源是基本需求之一籽孙。游戲中在線加載一張圖片(比如玩家頭像)烈评,想保存在本地,并為這張圖片生成一個(gè)唯一ID或MD5犯建,下次啟動(dòng)的時(shí)候讲冠,就可以從本地讀取數(shù)據(jù)生成對(duì)應(yīng)的精靈。在使用Cocos Creator開(kāi)發(fā)游戲時(shí)胎挎,官方很友好地為我們提供了加載遠(yuǎn)程資源的API(如下)沟启,這幾個(gè)API的好處在于根據(jù)URL從服務(wù)器加載圖片后,本地也會(huì)有一份圖片的存儲(chǔ)犹菇,下次加載的時(shí)候德迹,如果URL相同,則直接從本地加載揭芍。詳情見(jiàn)官方 加載遠(yuǎn)程資源和設(shè)備資源
// 遠(yuǎn)程 url 帶圖片后綴名
var remoteUrl = "http://unknown.org/someres.png";
cc.loader.load(remoteUrl, function (err, texture) {
// Use texture to create sprite frame
});
// 遠(yuǎn)程 url 不帶圖片后綴名胳搞,此時(shí)必須指定遠(yuǎn)程圖片文件的類型
remoteUrl = "http://unknown.org/emoji?id=124982374";
cc.loader.load({url: remoteUrl, type: 'png'}, function () {
// Use texture to create sprite frame
});
// 用絕對(duì)路徑加載設(shè)備存儲(chǔ)內(nèi)的資源,比如相冊(cè)
var absolutePath = "/dara/data/some/path/to/image.png"
cc.loader.load(absolutePath, function () {
// Use texture to create sprite frame
});
本來(lái)認(rèn)為官方自帶本地緩存的加載遠(yuǎn)程圖片API已經(jīng)很完美了称杨。但是最近自己在使用時(shí)肌毅,發(fā)現(xiàn)服務(wù)器返回的圖片URL并不如官方API限定的那樣有后綴(.png or .jpg), 【"http://mapi1.93leju.net/home/userLogo.resource?userId=8201709288446120&mt="】,并且后臺(tái)開(kāi)發(fā)人員說(shuō)圖片格式不唯一姑原,可能是png或jpg格式的(其實(shí)后臺(tái)幫忙轉(zhuǎn)成統(tǒng)一的格式也挺容易的嘛悬而,但是他們lazy)。所以在無(wú)法確定URL對(duì)應(yīng)的圖片格式時(shí)锭汛,官方的API也就無(wú)法滿足實(shí)際需求笨奠,這種情況下我們得自己想辦法去實(shí)現(xiàn)。
小插曲:
發(fā)現(xiàn)這個(gè)問(wèn)題后唤殴,首先我在論壇搜了一下關(guān)鍵詞般婆,找到一個(gè)兩年前方案,但是無(wú)法直接運(yùn)行起來(lái)朵逝,于是我在論壇里發(fā)了個(gè)帖子蔚袍,并希望近期遇到類似問(wèn)題的開(kāi)發(fā)者給個(gè)方案。然而意料地得到如下回復(fù)配名,讓人很無(wú)語(yǔ)啤咽。不知道留言這個(gè)人心理是否有問(wèn)題晋辆,但肯定不健康。從事技術(shù)開(kāi)發(fā)闰蚕,每個(gè)人在不同階段都會(huì)遇到各種問(wèn)題栈拖,或容易或簡(jiǎn)單连舍。即便你技術(shù)再牛没陡,也不應(yīng)該歧視別人,正所謂“每一位牛逼的人都曾經(jīng)歷過(guò)一段傻逼的歲月”索赏。
所以在我解決了這個(gè)問(wèn)題之后盼玄,我將它在博客中記錄下來(lái),并希望可以幫助到其他小伙伴潜腻。所謂“贈(zèng)人玫瑰埃儿,手留余香”(The fragrance always stays in the hand that gives the rose to others),相信好人一生平安融涣。
耐心分析源碼童番,并參考論壇上唯一一個(gè)兩年前的大神方案,改進(jìn)并優(yōu)化之后威鹿,終于可以完美運(yùn)行在當(dāng)前環(huán)境中(Creator版本1.9.1)剃斧。接下來(lái)我將分享出經(jīng)過(guò)我封裝之后的圖片下載器文件 ImageLoader.js。
使用方法:
cc.vv = {};
cc.vv.imageLoader = require("ImageLoader");
cc.vv.imageLoader.imageLoadTool(imageURL,function(spriteFrame){
this.headSprite.spriteFrame = spriteFrame;
}.bind(this));
注:imageURL就是遠(yuǎn)程服務(wù)器的圖片地址忽你。
/*
* @Author: Damo
* @Date: 2018-06-08 09:56:20
* @Last Modified by: Damo
* @Last Modified time: 2018-06-10 13:29:52
*/
cc.Class({
extends: cc.Component,
statics : {
loadImage : function (url,callback){
cc.loader.load(url,function (err,tex) {
var spriteFrame = new cc.SpriteFrame(tex, cc.Rect(0, 0, tex.width, tex.height));
callback(spriteFrame);
});
},
imageLoadTool(url, callback){
var dirpath = jsb.fileUtils.getWritablePath() + 'customHeadImage/';
console.log("dirpath ->",dirpath);
var md5Sign = require("signMd5").md5Sign;
let md5URL = md5Sign(url);
var filepath = dirpath + md5URL + '.jpg';
console.log("filepath ->",filepath);
function loadEnd(){
cc.loader.load(filepath, function(err, tex){
if( err ){
cc.error(err);
}else{
var spriteFrame = new cc.SpriteFrame(tex);
if( spriteFrame ){
spriteFrame.retain();
callback(spriteFrame);
}
}
});
}
if( jsb.fileUtils.isFileExist(filepath) ){
cc.log('Remote is find' + filepath);
loadEnd();
return;
}
var saveFile = function(data){
if( typeof data !== 'undefined' ){
if( !jsb.fileUtils.isDirectoryExist(dirpath) ){
jsb.fileUtils.createDirectory(dirpath);
}else{
console.log("路徑exist");
}
// new Uint8Array(data) writeDataToFile writeStringToFile
if( jsb.fileUtils.writeDataToFile( new Uint8Array(data) , filepath) ){
cc.log('Remote write file succeed.');
loadEnd();
}else{
cc.log('Remote write file failed.');
}
}else{
cc.log('Remote download file failed.');
}
};
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
cc.log("xhr.readyState " +xhr.readyState);
cc.log("xhr.status " +xhr.status);
if (xhr.readyState === 4 ) {
if(xhr.status === 200){
//responseType一定要在外面設(shè)置
// xhr.responseType = 'arraybuffer';
saveFile(xhr.response);
}else{
saveFile(null);
}
}
}.bind(this);
//responseType一定要在外面設(shè)置
xhr.responseType = 'arraybuffer';
xhr.open("GET", url, true);
xhr.send();
},
},
});
上面在設(shè)置圖片存儲(chǔ)路徑的時(shí)候這樣提到:
var md5Sign = require("signMd5").md5Sign;
let md5URL = md5Sign(url);
var filepath = dirpath + md5URL + '.jpg';
其中“ var md5Sign = require("signMd5").md5Sign;”也只是引入一個(gè)md5加密的腳本幼东,意即給一串長(zhǎng)的URL地址轉(zhuǎn)為固定長(zhǎng)短字符,這個(gè)MD5腳本我就不上傳了科雳,GitHub上面很多根蟹。伙伴們?cè)跍y(cè)試的時(shí)候糟秘,上面這三行代碼可以簡(jiǎn)寫(xiě)成:
var filepath = dirpath + url + '.jpg';
也就是直接使用url简逮。