import md5 from './md5' /** * 是否启用cocos的api */ let enabelCC = true let _global = typeof window === 'undefined' ? global : window; let translate = { dx : 0, dy : 0 }; let eventMap = {}; let ccEventMap = {}; let displayMap = {}; /** * 对外接口 */ module.exports = { // 基础UI showLoading, hideLoading, showTip, showSuccessTip, showErrorTip, // 网络相关 get, post, // 小游戏独特UI drawImage, hideImage, updateImage, // download, cc : _global.cc, wx : _global.wx, setCanvasTranslate, getCanvas, getCanvasCtx, setDebug, //本地存储 getStorage, setStorage, //签名构造 encodePwd } Object.defineProperty(module.exports, "host", { get: function() { if (this.debug) { return 'https://test-xyxbox.duowan.com/' } else { return 'https://xyxbox.duowan.com/' } } }); function setDebug(debug) { module.exports.debug = debug } function getCanvas() { return _global.canvas || cc.game.canvas } function getCanvasCtx() { let gameCanvas = getCanvas() return gameCanvas.getContext('2d') } /** * 设置canvas的原点 * @param {int} dx The distance to translate in X * @param {int} dy The distance to translate in Y */ function setCanvasTranslate(dx, dy) { translate.dx = dx; translate.dy = dy; } function drawImage(name, src, x, y, callback, options) { // 图片地址补齐http if (src.indexOf('http') !== 0) { src += 'http:' } // 微信里面只能用https的图片 if (_global.wx) { src = src.replace(/http\:\/\//, 'https://') } if (enabelCC && _global.cc) { download(src, function(texture2D) { let pNode = options['pNode'] let node = pNode.getChildByName(name) let sp = null let btn = null // 判断是否加过这个node了 if (!node) { node = new cc.Node(name) node.zIndex = options['zIndex'] || 66666 sp = node.addComponent(cc.Sprite) btn = node.addComponent(cc.Button) // node.x = x // node.y = y var widget = node.addComponent(cc.Widget) widget.isAlignTop = true widget.isAlignLeft = true widget.left = x widget.top = y node.parent = pNode } else { sp = node.getComponent(cc.Sprite) btn = node.getComponent(cc.Button) if (ccEventMap[name]) { btn.node.off(cc.Node.EventType.TOUCH_START, ccEventMap[name]) delete ccEventMap[name] } } // 如果是多张图的情况 if (options['num'] && options['num'] > 1) { options['texture2D'] = texture2D; displayMap[name] = [sp, x, y, options] if (!sp.spriteFrame) { updateImage(); } } else { sp.spriteFrame = new cc.SpriteFrame(texture2D); } if (callback) { ccEventMap[name] = callback btn.node.on(cc.Node.EventType.TOUCH_START, callback) } }); } else { let ctx = getCanvasCtx() if (!ctx) { console.log('目前不支持WebGL引擎渲染') return } let image = _global.wx ? wx.createImage() : new Image; image.onload = function () { displayMap[name] = [image, x, y, options] // updateImage() // 绑定事件 if (callback) { _bindEvent(name, 'touchstart', image, x, y, options, callback) } } image.src = src } } let i = 0; function updateImage() { let ctx = null; for (var name in displayMap) { let value = displayMap[name] let image = value[0] let options = value[3] let texture2D = options.texture2D; let orginSize = texture2D || image; let info = null; if (options && options['num'] && options['num'] > 1) { let cur = options['cur'] || 0; let curFrame = options['curFrame'] || 0; let num = options['num'] let interval = options['interval'] if (++curFrame == interval) { curFrame = 0; cur = (cur + 1) % num; } let rows = options['rows'] || 1 let cols = options['cols'] || 1 let cur_rows = parseInt(cur / cols); let cur_cols = cur - cur_rows * cols; let img_width = orginSize.width / cols let img_height = orginSize.height / rows info = [img_width * cur_cols, img_height * cur_rows, img_width, img_height] // 设置显示列表 displayMap[name][3]['curFrame'] = curFrame; displayMap[name][3]['cur'] = cur; } else { info = [value[1], value[2], orginSize.width, orginSize.height] } if (texture2D) { let sf = new cc.SpriteFrame(texture2D) sf.setRect(new cc.Rect(info[0], info[1], info[2], info[3])) image.spriteFrame = sf } else { let x = value[1] - translate.dx let y = value[2] - translate.dy ctx = ctx || getCanvasCtx(); ctx.drawImage(image, info[0], info[1], info[2], info[3], x, y, info[2], info[3]) } } } function hideImage(name, pNode = null) { _unbindEvent(name); if (displayMap[name]) { delete displayMap[name] } if (pNode) { let child = pNode.getChildByName(name) if (child) { child.removeFromParent(true) } } } function _unbindEvent(name) { eventMap[name] = eventMap[name] || {} for (let eventType in eventMap[name]) { _unbindOneEvent(name, eventType) } } function _unbindOneEvent(name, eventType) { eventMap[name] = eventMap[name] || {} if (eventMap[name][eventType]) { getCanvas().removeEventListener(eventType, eventMap[name][eventType]) delete eventMap[name][eventType] } } // jquery offset原生实现 function _offset(target) { var top = 0, left = 0 while(target.offsetParent) { top += target.offsetTop left += target.offsetLeft target = target.offsetParent } return { top: top, left: left, } } function _bindEvent(name, eventType, image, x, y, options, callback) { eventMap[name] = eventMap[name] || {} if (eventMap[name][eventType]) { _unbindOneEvent(name, eventType); } eventMap[name][eventType] = function(event) {    var _x, _y; var touches = event.touches; if (touches) { var canvas = getCanvas(); let offset = _offset(canvas); _x = touches[0].clientX - offset.left, _y = touches[0].clientY - offset.top; } else if (event.layerX || event.layerX == 0) {    _x = event.layerX;    _y = event.layerY;    } else if (event.offsetX || event.offsetX == 0) { // Opera   _x = event.offsetX;   _y = event.offsetY;    } _checkRange(_x, _y, options) }; function _checkRange(_x, _y, options) { let radio = _global.wx ? 0.67 : 1.5; let rows = options['rows'] || 1 let cols = options['cols'] || 1 let flag = _x > x && _x < x + image.width * radio / cols flag &= _y > y && _y < y + image.height * radio / rows if (flag && !self.isHide) { callback && callback(); } } getCanvas().addEventListener(eventType, eventMap[name][eventType]); } function download(src, callback) { if (enabelCC && _global.cc) { cc.loader.load(src, function (err, tex) { if (err) { cc.error(err); } else { callback(tex); } }); } else { wx.downloadFile({ url: src, header: {}, filePath: '', success: function (ret) { callback(ret.tempFilePath); } }) } } // -------------- 通用UI ---------------- let loadingTimeoutHandler = 0 function showLoading(title, timeout, cancelable) { let option = { title } if (!cancelable) { option['mask'] = true } if (_global.wx) { wx.showLoading(option) } else { console.log(`showLoading, title:${title}, timeout:${timeout}, cancelable:${cancelable}`) } // 超时时间为15s timeout = timeout || 15000; loadingTimeoutHandler = setTimeout(function(){ hideLoading() showTip("加载超时,请稍后再试") }, timeout); } function hideLoading() { loadingTimeoutHandler && clearTimeout(loadingTimeoutHandler); loadingTimeoutHandler = 0; if (_global.wx) { wx.hideLoading() } else { console.log(`hideLoading`) } } function showSuccessTip(title, timeout) { showTip(title, timeout, { 'icon' : 'success' }); } function showErrorTip(title, timeout) { showTip(title, timeout, { 'icon' : 'loading' }); } function showTip(title, timeout, option) { option = option || {} option['title'] = title option['duration'] = timeout || 3000 if (_global.wx) { wx.showToast(option) } else { console.log(`showTip:${title}, ${timeout}`) } } // -------------- 网络相关接口 ------------ function _get(url, data, callback) { if (_global.wx) { wx.request({ method:'GET', url: url, data: data, dataType: 'text', success: function(ret) { callback(ret.data) } }); } else { let query = _buildData(data); if (url.indexOf('?') >= 0) { url += '&' + query; } else { url += '?' + query; } var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function () { if (xhr.readyState == 4 && (xhr.status >= 200 && xhr.status < 400)) { var text = xhr.responseText; callback(text); } }; xhr.open("GET", url, true); xhr.send(); } } function _post(url, data, callback) { if (_global.wx) { wx.request({ method:'POST', url: url, data: data, dataType: 'text', header: { //设置参数内容类型为x-www-form-urlencoded 'content-type':'application/x-www-form-urlencoded', }, success: function(ret) { callback(ret.data) } }); } else { var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function () { if (xhr.readyState == 4 && (xhr.status >= 200 && xhr.status < 400)) { var text = xhr.responseText; callback(text); } }; xhr.open("POST", url, true); xhr.send(_buildData(data)); } } function _buildData(data) { let query = ''; for (let key in data) { query += key + '=' + data[key] + '&'; } if (query) { query = query.substr(0, query.length - 1); } return query; } function get(url, data, callback, option) { option = option || {}; // 支持post(url, callback)的写法; if (typeof data === 'function') { option = callback || {}; callback = data; data = {}; } option['loading'] && showLoading(); _get(url, data, function(text) { option['loading'] && hideLoading(); if (option['type'] === 'text' && typeof text == 'string') { callback && callback(text); } else { var objResult = _getAjaxResult(text); callback && callback(objResult); } }); } /** * option object {'cache', 'loading', 'onTimeout'} * cache为true、every、once */ function post(url, data, callback, option) { option = option || {}; // 支持postCross(url, callback)的写法; if ( typeof data == 'function') { option = callback || {}; callback = data; data = {}; } data['_from'] = 'ajax'; //获取cache的key if (option['cache'] && window.localStorage) { var cacheKey = 'ajaxCache-' + url + '?' + $.param(data); //如果有cache则不出现loading var isCached = _loadAjaxCache(cacheKey, callback); if (isCached) { option['loading'] = false; if (option['cache'] == "must") { return; } } } if (option['loading']) { showLoading(); } _post(url, data, function (text) { option['loading'] && hideLoading(); if (option['type'] === 'text') { callback(text); } else { var objResult = _getAjaxResult(text); if (objResult['result'] && option['cache']) { var cache = getStorage(cacheKey); if (cache && cache == text) { // 网络返回跟缓存一致 return; } else { setStorage(cacheKey, xhr.responseText); } } _handleResult(callback, objResult); } }); } function _getAjaxResult(text) { var objResult = {}; var objError = { result : 0, msg : "系统繁忙,请稍后再试!" }; try { objResult = JSON.parse(text); if (typeof objResult !== 'object' || objResult === null) { objResult = objError; } } catch (ex) { //非json的处理 objResult = objError; } return objResult; } function _loadAjaxCache(cacheKey, callback) { var cache = getStorage(cacheKey); if (cache) { var objResult = JSON.parse(cache); objResult._fromCache = true; _handleResult(callback, objResult); return true; } else { return false; } } function _handleResult(callback, objResult) { //session_id失效,重新验证登录 if(!objResult.result && objResult.code === -5) { openLogin(); } else { callback && callback(objResult); } } function getStorage(key) { if(_global.wx) { return wx.getStorageSync(key) }else { let str = localStorage.getItem(key) let data try{ data = JSON.parse(str) } catch(e) { data = str } return data } } function setStorage(key,value) { if(_global.wx) { wx.setStorage({ key, data: value }); }else { let str try { str = JSON.stringify(value) } catch (error) { str = value } localStorage.setItem(key,str) } } function encodePwd(random, pwd) { var k1 = md5.sha1(random); var k2 = md5.sha1(k1); var v = md5.xor(md5.xor(pwd, k2), k1); return md5.base64encode(v); }