library.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606
  1. import md5 from './md5'
  2. /**
  3. * 是否启用cocos的api
  4. */
  5. let enabelCC = true
  6. let _global = typeof window === 'undefined' ? global : window;
  7. let translate = { dx : 0, dy : 0 };
  8. let eventMap = {};
  9. let ccEventMap = {};
  10. let displayMap = {};
  11. /**
  12. * 对外接口
  13. */
  14. module.exports = {
  15. // 基础UI
  16. showLoading,
  17. hideLoading,
  18. showTip,
  19. showSuccessTip,
  20. showErrorTip,
  21. // 网络相关
  22. get,
  23. post,
  24. // 小游戏独特UI
  25. drawImage,
  26. hideImage,
  27. updateImage,
  28. // download,
  29. cc : _global.cc,
  30. wx : _global.wx,
  31. setCanvasTranslate,
  32. getCanvas,
  33. getCanvasCtx,
  34. setDebug,
  35. //本地存储
  36. getStorage,
  37. setStorage,
  38. //签名构造
  39. encodePwd
  40. }
  41. Object.defineProperty(module.exports, "host", {
  42. get: function() {
  43. if (this.debug) {
  44. return 'https://test-xyxbox.duowan.com/'
  45. } else {
  46. return 'https://xyxbox.duowan.com/'
  47. }
  48. }
  49. });
  50. function setDebug(debug) {
  51. module.exports.debug = debug
  52. }
  53. function getCanvas() {
  54. return _global.canvas || cc.game.canvas
  55. }
  56. function getCanvasCtx() {
  57. let gameCanvas = getCanvas()
  58. return gameCanvas.getContext('2d')
  59. }
  60. /**
  61. * 设置canvas的原点
  62. * @param {int} dx The distance to translate in X
  63. * @param {int} dy The distance to translate in Y
  64. */
  65. function setCanvasTranslate(dx, dy) {
  66. translate.dx = dx;
  67. translate.dy = dy;
  68. }
  69. function drawImage(name, src, x, y, callback, options) {
  70. // 图片地址补齐http
  71. if (src.indexOf('http') !== 0) {
  72. src += 'http:'
  73. }
  74. // 微信里面只能用https的图片
  75. if (_global.wx) {
  76. src = src.replace(/http\:\/\//, 'https://')
  77. }
  78. if (enabelCC && _global.cc) {
  79. download(src, function(texture2D) {
  80. let pNode = options['pNode']
  81. let node = pNode.getChildByName(name)
  82. let sp = null
  83. let btn = null
  84. // 判断是否加过这个node了
  85. if (!node) {
  86. node = new cc.Node(name)
  87. node.zIndex = options['zIndex'] || 66666
  88. sp = node.addComponent(cc.Sprite)
  89. btn = node.addComponent(cc.Button)
  90. // node.x = x
  91. // node.y = y
  92. var widget = node.addComponent(cc.Widget)
  93. widget.isAlignTop = true
  94. widget.isAlignLeft = true
  95. widget.left = x
  96. widget.top = y
  97. node.parent = pNode
  98. } else {
  99. sp = node.getComponent(cc.Sprite)
  100. btn = node.getComponent(cc.Button)
  101. if (ccEventMap[name]) {
  102. btn.node.off(cc.Node.EventType.TOUCH_START, ccEventMap[name])
  103. delete ccEventMap[name]
  104. }
  105. }
  106. // 如果是多张图的情况
  107. if (options['num'] && options['num'] > 1) {
  108. options['texture2D'] = texture2D;
  109. displayMap[name] = [sp, x, y, options]
  110. if (!sp.spriteFrame) {
  111. updateImage();
  112. }
  113. } else {
  114. sp.spriteFrame = new cc.SpriteFrame(texture2D);
  115. }
  116. if (callback) {
  117. ccEventMap[name] = callback
  118. btn.node.on(cc.Node.EventType.TOUCH_START, callback)
  119. }
  120. });
  121. } else {
  122. let ctx = getCanvasCtx()
  123. if (!ctx) {
  124. console.log('目前不支持WebGL引擎渲染')
  125. return
  126. }
  127. let image = _global.wx ? wx.createImage() : new Image;
  128. image.onload = function () {
  129. displayMap[name] = [image, x, y, options]
  130. // updateImage()
  131. // 绑定事件
  132. if (callback) {
  133. _bindEvent(name, 'touchstart', image, x, y, options, callback)
  134. }
  135. }
  136. image.src = src
  137. }
  138. }
  139. let i = 0;
  140. function updateImage() {
  141. let ctx = null;
  142. for (var name in displayMap) {
  143. let value = displayMap[name]
  144. let image = value[0]
  145. let options = value[3]
  146. let texture2D = options.texture2D;
  147. let orginSize = texture2D || image;
  148. let info = null;
  149. if (options && options['num'] && options['num'] > 1) {
  150. let cur = options['cur'] || 0;
  151. let curFrame = options['curFrame'] || 0;
  152. let num = options['num']
  153. let interval = options['interval']
  154. if (++curFrame == interval) {
  155. curFrame = 0;
  156. cur = (cur + 1) % num;
  157. }
  158. let rows = options['rows'] || 1
  159. let cols = options['cols'] || 1
  160. let cur_rows = parseInt(cur / cols);
  161. let cur_cols = cur - cur_rows * cols;
  162. let img_width = orginSize.width / cols
  163. let img_height = orginSize.height / rows
  164. info = [img_width * cur_cols, img_height * cur_rows, img_width, img_height]
  165. // 设置显示列表
  166. displayMap[name][3]['curFrame'] = curFrame;
  167. displayMap[name][3]['cur'] = cur;
  168. } else {
  169. info = [value[1], value[2], orginSize.width, orginSize.height]
  170. }
  171. if (texture2D) {
  172. let sf = new cc.SpriteFrame(texture2D)
  173. sf.setRect(new cc.Rect(info[0], info[1], info[2], info[3]))
  174. image.spriteFrame = sf
  175. } else {
  176. let x = value[1] - translate.dx
  177. let y = value[2] - translate.dy
  178. ctx = ctx || getCanvasCtx();
  179. ctx.drawImage(image, info[0], info[1], info[2], info[3], x, y, info[2], info[3])
  180. }
  181. }
  182. }
  183. function hideImage(name, pNode = null) {
  184. _unbindEvent(name);
  185. if (displayMap[name]) {
  186. delete displayMap[name]
  187. }
  188. if (pNode) {
  189. let child = pNode.getChildByName(name)
  190. if (child) {
  191. child.removeFromParent(true)
  192. }
  193. }
  194. }
  195. function _unbindEvent(name) {
  196. eventMap[name] = eventMap[name] || {}
  197. for (let eventType in eventMap[name]) {
  198. _unbindOneEvent(name, eventType)
  199. }
  200. }
  201. function _unbindOneEvent(name, eventType) {
  202. eventMap[name] = eventMap[name] || {}
  203. if (eventMap[name][eventType]) {
  204. getCanvas().removeEventListener(eventType, eventMap[name][eventType])
  205. delete eventMap[name][eventType]
  206. }
  207. }
  208. // jquery offset原生实现
  209. function _offset(target) {
  210. var top = 0,
  211. left = 0
  212. while(target.offsetParent) {
  213. top += target.offsetTop
  214. left += target.offsetLeft
  215. target = target.offsetParent
  216. }
  217. return {
  218. top: top,
  219. left: left,
  220. }
  221. }
  222. function _bindEvent(name, eventType, image, x, y, options, callback) {
  223. eventMap[name] = eventMap[name] || {}
  224. if (eventMap[name][eventType]) {
  225. _unbindOneEvent(name, eventType);
  226. }
  227. eventMap[name][eventType] = function(event) {
  228.    var _x, _y;
  229. var touches = event.touches;
  230. if (touches) {
  231. var canvas = getCanvas();
  232. let offset = _offset(canvas);
  233. _x = touches[0].clientX - offset.left,
  234. _y = touches[0].clientY - offset.top;
  235. } else if (event.layerX || event.layerX == 0) {
  236.    _x = event.layerX;
  237.    _y = event.layerY;
  238.    } else if (event.offsetX || event.offsetX == 0) { // Opera
  239.   _x = event.offsetX;
  240.   _y = event.offsetY;
  241.    }
  242. _checkRange(_x, _y, options)
  243. };
  244. function _checkRange(_x, _y, options) {
  245. let radio = _global.wx ? 0.67 : 1.5;
  246. let rows = options['rows'] || 1
  247. let cols = options['cols'] || 1
  248. let flag = _x > x && _x < x + image.width * radio / cols
  249. flag &= _y > y && _y < y + image.height * radio / rows
  250. if (flag && !self.isHide) {
  251. callback && callback();
  252. }
  253. }
  254. getCanvas().addEventListener(eventType, eventMap[name][eventType]);
  255. }
  256. function download(src, callback) {
  257. if (enabelCC && _global.cc) {
  258. cc.loader.load(src, function (err, tex) {
  259. if (err) {
  260. cc.error(err);
  261. } else {
  262. callback(tex);
  263. }
  264. });
  265. }
  266. else {
  267. wx.downloadFile({
  268. url: src,
  269. header: {},
  270. filePath: '',
  271. success: function (ret) {
  272. callback(ret.tempFilePath);
  273. }
  274. })
  275. }
  276. }
  277. // -------------- 通用UI ----------------
  278. let loadingTimeoutHandler = 0
  279. function showLoading(title, timeout, cancelable) {
  280. let option = { title }
  281. if (!cancelable) {
  282. option['mask'] = true
  283. }
  284. if (_global.wx) {
  285. wx.showLoading(option)
  286. } else {
  287. console.log(`showLoading, title:${title}, timeout:${timeout}, cancelable:${cancelable}`)
  288. }
  289. // 超时时间为15s
  290. timeout = timeout || 15000;
  291. loadingTimeoutHandler = setTimeout(function(){
  292. hideLoading()
  293. showTip("加载超时,请稍后再试")
  294. }, timeout);
  295. }
  296. function hideLoading() {
  297. loadingTimeoutHandler && clearTimeout(loadingTimeoutHandler);
  298. loadingTimeoutHandler = 0;
  299. if (_global.wx) {
  300. wx.hideLoading()
  301. } else {
  302. console.log(`hideLoading`)
  303. }
  304. }
  305. function showSuccessTip(title, timeout) {
  306. showTip(title, timeout, {
  307. 'icon' : 'success'
  308. });
  309. }
  310. function showErrorTip(title, timeout) {
  311. showTip(title, timeout, {
  312. 'icon' : 'loading'
  313. });
  314. }
  315. function showTip(title, timeout, option) {
  316. option = option || {}
  317. option['title'] = title
  318. option['duration'] = timeout || 3000
  319. if (_global.wx) {
  320. wx.showToast(option)
  321. } else {
  322. console.log(`showTip:${title}, ${timeout}`)
  323. }
  324. }
  325. // -------------- 网络相关接口 ------------
  326. function _get(url, data, callback) {
  327. if (_global.wx) {
  328. wx.request({
  329. method:'GET',
  330. url: url,
  331. data: data,
  332. dataType: 'text',
  333. success: function(ret) {
  334. callback(ret.data)
  335. }
  336. });
  337. } else {
  338. let query = _buildData(data);
  339. if (url.indexOf('?') >= 0) {
  340. url += '&' + query;
  341. } else {
  342. url += '?' + query;
  343. }
  344. var xhr = new XMLHttpRequest();
  345. xhr.onreadystatechange = function () {
  346. if (xhr.readyState == 4 && (xhr.status >= 200 && xhr.status < 400)) {
  347. var text = xhr.responseText;
  348. callback(text);
  349. }
  350. };
  351. xhr.open("GET", url, true);
  352. xhr.send();
  353. }
  354. }
  355. function _post(url, data, callback) {
  356. if (_global.wx) {
  357. wx.request({
  358. method:'POST',
  359. url: url,
  360. data: data,
  361. dataType: 'text',
  362. header: {
  363. //设置参数内容类型为x-www-form-urlencoded
  364. 'content-type':'application/x-www-form-urlencoded',
  365. },
  366. success: function(ret) {
  367. callback(ret.data)
  368. }
  369. });
  370. } else {
  371. var xhr = new XMLHttpRequest();
  372. xhr.onreadystatechange = function () {
  373. if (xhr.readyState == 4 && (xhr.status >= 200 && xhr.status < 400)) {
  374. var text = xhr.responseText;
  375. callback(text);
  376. }
  377. };
  378. xhr.open("POST", url, true);
  379. xhr.send(_buildData(data));
  380. }
  381. }
  382. function _buildData(data) {
  383. let query = '';
  384. for (let key in data) {
  385. query += key + '=' + data[key] + '&';
  386. }
  387. if (query) {
  388. query = query.substr(0, query.length - 1);
  389. }
  390. return query;
  391. }
  392. function get(url, data, callback, option) {
  393. option = option || {};
  394. // 支持post(url, callback)的写法;
  395. if (typeof data === 'function') {
  396. option = callback || {};
  397. callback = data;
  398. data = {};
  399. }
  400. option['loading'] && showLoading();
  401. _get(url, data, function(text) {
  402. option['loading'] && hideLoading();
  403. if (option['type'] === 'text' && typeof text == 'string') {
  404. callback && callback(text);
  405. } else {
  406. var objResult = _getAjaxResult(text);
  407. callback && callback(objResult);
  408. }
  409. });
  410. }
  411. /**
  412. * option object {'cache', 'loading', 'onTimeout'}
  413. * cache为true、every、once
  414. */
  415. function post(url, data, callback, option) {
  416. option = option || {};
  417. // 支持postCross(url, callback)的写法;
  418. if ( typeof data == 'function') {
  419. option = callback || {};
  420. callback = data;
  421. data = {};
  422. }
  423. data['_from'] = 'ajax';
  424. //获取cache的key
  425. if (option['cache'] && window.localStorage) {
  426. var cacheKey = 'ajaxCache-' + url + '?' + $.param(data);
  427. //如果有cache则不出现loading
  428. var isCached = _loadAjaxCache(cacheKey, callback);
  429. if (isCached) {
  430. option['loading'] = false;
  431. if (option['cache'] == "must") {
  432. return;
  433. }
  434. }
  435. }
  436. if (option['loading']) {
  437. showLoading();
  438. }
  439. _post(url, data, function (text) {
  440. option['loading'] && hideLoading();
  441. if (option['type'] === 'text') {
  442. callback(text);
  443. } else {
  444. var objResult = _getAjaxResult(text);
  445. if (objResult['result'] && option['cache']) {
  446. var cache = getStorage(cacheKey);
  447. if (cache && cache == text) {
  448. // 网络返回跟缓存一致
  449. return;
  450. } else {
  451. setStorage(cacheKey, xhr.responseText);
  452. }
  453. }
  454. _handleResult(callback, objResult);
  455. }
  456. });
  457. }
  458. function _getAjaxResult(text) {
  459. var objResult = {};
  460. var objError = {
  461. result : 0,
  462. msg : "系统繁忙,请稍后再试!"
  463. };
  464. try {
  465. objResult = JSON.parse(text);
  466. if (typeof objResult !== 'object' || objResult === null) {
  467. objResult = objError;
  468. }
  469. } catch (ex) {
  470. //非json的处理
  471. objResult = objError;
  472. }
  473. return objResult;
  474. }
  475. function _loadAjaxCache(cacheKey, callback) {
  476. var cache = getStorage(cacheKey);
  477. if (cache) {
  478. var objResult = JSON.parse(cache);
  479. objResult._fromCache = true;
  480. _handleResult(callback, objResult);
  481. return true;
  482. } else {
  483. return false;
  484. }
  485. }
  486. function _handleResult(callback, objResult) {
  487. //session_id失效,重新验证登录
  488. if(!objResult.result && objResult.code === -5) {
  489. openLogin();
  490. } else {
  491. callback && callback(objResult);
  492. }
  493. }
  494. function getStorage(key) {
  495. if(_global.wx) {
  496. return wx.getStorageSync(key)
  497. }else {
  498. let str = localStorage.getItem(key)
  499. let data
  500. try{
  501. data = JSON.parse(str)
  502. } catch(e) {
  503. data = str
  504. }
  505. return data
  506. }
  507. }
  508. function setStorage(key,value) {
  509. if(_global.wx) {
  510. wx.setStorage({
  511. key,
  512. data: value
  513. });
  514. }else {
  515. let str
  516. try {
  517. str = JSON.stringify(value)
  518. } catch (error) {
  519. str = value
  520. }
  521. localStorage.setItem(key,str)
  522. }
  523. }
  524. function encodePwd(random, pwd) {
  525. var k1 = md5.sha1(random);
  526. var k2 = md5.sha1(k1);
  527. var v = md5.xor(md5.xor(pwd, k2), k1);
  528. return md5.base64encode(v);
  529. }