library.js 15 KB

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