library.js 14 KB

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