JMAlertBase.js 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. /**
  2. * 弹框
  3. */
  4. cc.Class({
  5. extends: cc.Component,
  6. properties: {
  7. id: {
  8. default: JMC.ALERT_ID.DEFAULT,
  9. type: JMC.ALERT_ID,
  10. tooltip: '弹框 Id'
  11. },
  12. enableOutside: {
  13. default: false,
  14. tooltip: '是否响应:点击遮挡关闭弹框'
  15. },
  16. enableBack: {
  17. default: false,
  18. tooltip: '是否响应:点击返回键关闭弹框'
  19. },
  20. isBlockOutside: {
  21. default: true,
  22. tooltip: '是否阻挡:点击穿透\n注意:遮挡时,请添加 Button 组件来响应 blockOnClicked'
  23. },
  24. autoPlayAnim: {
  25. default: false,
  26. tooltip: '是否自动播放弹出/关闭动画(在 onLoad 播放)'
  27. },
  28. isShowing: {
  29. default: false,
  30. visible: false
  31. },
  32. isHiding: {
  33. default: false,
  34. visible: false
  35. },
  36. enableAction: {
  37. visible: false,
  38. get () {
  39. return (!this.isShowing && !this.isHiding);
  40. }
  41. },
  42. alertZIndex: {
  43. default: 0,
  44. tooltip: '弹框弹出的层次,越大值越在顶层。0是默认值,值>=100时,popAllAlert接口将不处理它'
  45. },
  46. rootNode: {
  47. default: undefined,
  48. type: cc.Node,
  49. tooltip: '播放弹出/关闭动画中缩放的节点。如果为空则无弹出/关闭动画'
  50. }
  51. },
  52. /**
  53. * 生命周期。子类需要调用this._super()
  54. *
  55. * @author Pyden
  56. * @date 2019-03-25
  57. */
  58. onLoad () {
  59. // 穿透的特殊处理
  60. if (!this.isBlockOutside) {
  61. // 注意:_hitTest方法,需要调用this.node.on才会执行到
  62. this.node._hitTest = (point, listener) => {
  63. this.blockOnClicked();
  64. return false;
  65. };
  66. }
  67. this.isShowing = false;
  68. this.isHiding = false;
  69. if (!CC_EDITOR) {
  70. if (this.autoPlayAnim) {
  71. this.playShowAnim();
  72. }
  73. }
  74. },
  75. /**
  76. * 生命周期。子类需要调用this._super()
  77. *
  78. * @author Pyden
  79. * @date 2019-03-25
  80. */
  81. onEnable () {
  82. this.node.on(cc.Node.EventType.TOUCH_START, this._onTouchStart, this);
  83. },
  84. /**
  85. * 生命周期。子类需要调用this._super()
  86. *
  87. * @author Pyden
  88. * @date 2019-03-25
  89. */
  90. onDisable () {
  91. this.node.off(cc.Node.EventType.TOUCH_START, this._onTouchStart, this);
  92. },
  93. /**
  94. * 生命周期。子类需要调用this._super()
  95. *
  96. * @author Pyden
  97. * @date 2019-07-22
  98. */
  99. onDestroy () {
  100. },
  101. /**
  102. * AlertCtrl.showAlert 方法统一调用刷新弹框的方法
  103. *
  104. * @author Pyden
  105. * @date 2019-04-23
  106. * @param {Object} viewData
  107. * @param {Function} cb
  108. */
  109. reloadData (viewData, cb) {
  110. this.cb = cb;
  111. },
  112. /**
  113. * 回调消息
  114. *
  115. * @author Pyden
  116. * @date 2019-04-26
  117. * @param {String} eventKey 事件Key
  118. * @param {Any} eventData 附加信息
  119. */
  120. alertCallback (eventKey, eventData) {
  121. if (this.cb) {
  122. // 因为cb如果出错会导致游戏闪屏,所以加上try catch
  123. try {
  124. this.cb(this, eventKey, eventData);
  125. } catch (error) {
  126. G.LogUtils.error('alert call back error:', error);
  127. }
  128. } else {
  129. this.alertDefaultCallback(eventKey, eventData);
  130. }
  131. },
  132. /**
  133. * 弹框默认事件的处理
  134. *
  135. * @author Pyden
  136. * @date 2019-04-26
  137. * @param {String} eventKey 事件Key
  138. * @param {Any} eventData 附加信息
  139. */
  140. alertDefaultCallback (eventKey, eventData) {
  141. switch (eventKey) {
  142. case 'error': {
  143. // 出错了,继续停留在弹框
  144. break;
  145. }
  146. case 'willShow': {
  147. // 弹框将要展示
  148. break;
  149. }
  150. case 'hideDone': {
  151. // 弹框隐藏完毕
  152. break;
  153. }
  154. default: {
  155. // 关闭
  156. this.close();
  157. break;
  158. }
  159. }
  160. },
  161. /**
  162. * 点击遮挡
  163. *
  164. * @author Pyden
  165. * @date 2019-03-25
  166. */
  167. blockOnClicked () {
  168. G.LogUtils.log('blockOnClicked');
  169. if (!this.enableOutside) {
  170. G.LogUtils.log('!this.enableOutside');
  171. return;
  172. }
  173. this.closeOnClicked();
  174. },
  175. /**
  176. * 点击返回键
  177. *
  178. * @author Pyden
  179. * @date 2019-03-25
  180. */
  181. backKeyOnClicked () {
  182. if (!this.enableBack) {
  183. return;
  184. }
  185. this.closeOnClicked();
  186. },
  187. /**
  188. * 点击关闭。包括3种:点击关闭按钮、点击遮挡、点击返回键
  189. *
  190. * @author Pyden
  191. * @date 2019-03-25
  192. */
  193. closeOnClicked () {
  194. if (!this.enableAction) {
  195. return;
  196. }
  197. // G.AudioMgr.playEffect('res_audio/mp3/sound/click', false);
  198. this.alertCallback('clickedClose');
  199. },
  200. /**
  201. * 关闭弹框
  202. *
  203. * @author Pyden
  204. * @date 2019-03-25
  205. */
  206. close () {
  207. this.playHideAnim(() => {
  208. // 播放隐藏动画完毕向cb发送一个hideDone消息
  209. this.alertCallback('hideDone');
  210. let event = new cc.Event.EventCustom('e_alert_pop', true);
  211. event.setUserData(this);
  212. this.node.dispatchEvent(event);
  213. });
  214. },
  215. /**
  216. * 播放弹出动画:淡入
  217. * 注意:弹出过程中,不响应交互
  218. *
  219. * @author Pyden
  220. * @date 2019-03-28
  221. * @param {function} cb 弹出后的回调
  222. */
  223. playShowAnim (cb) {
  224. if (!this.rootNode) {
  225. if (cb) {
  226. cb(this);
  227. }
  228. return;
  229. }
  230. if (this.isShowing) {
  231. return;
  232. }
  233. this.isShowing = true;
  234. this.isHiding = false;
  235. let animTime = 0.2;
  236. this.rootNode.scale = 0.1;
  237. cc.tween(this.rootNode)
  238. .stop()
  239. .to(animTime - 0.1, {scale: 1.06})
  240. .to(0.07, {scale: 0.98})
  241. .to(0.03, {scale: 1})
  242. .start();
  243. this.node.opacity = 255 * 0.2;
  244. cc.tween(this.node)
  245. .stop()
  246. .to(animTime, {opacity: 255})
  247. .call(() => {
  248. this.isShowing = false;
  249. if (cb) {
  250. cb(this);
  251. }
  252. })
  253. .start();
  254. },
  255. /**
  256. * 播放关闭动画:淡出
  257. * 注意:弹出过程中,不响应交互
  258. *
  259. * @author Pyden
  260. * @date 2019-03-28
  261. * @param {function} cb 关闭后的回调
  262. */
  263. playHideAnim (cb) {
  264. if (!this.rootNode) {
  265. if (cb) {
  266. cb(this);
  267. }
  268. return;
  269. }
  270. if (this.isHiding) {
  271. return;
  272. }
  273. this.isShowing = false;
  274. this.isHiding = true;
  275. let animTime = 0.1;
  276. cc.tween(this.rootNode)
  277. .stop()
  278. .to(animTime, {scale: 0})
  279. .start();
  280. cc.tween(this.node)
  281. .stop()
  282. .to(animTime, {opacity: 0})
  283. .call(() => {
  284. this.isHiding = false;
  285. if (cb) {
  286. cb(this);
  287. }
  288. })
  289. .start();
  290. },
  291. /**
  292. * 通用的按钮点击回调
  293. * 根据customEventData去cb
  294. *
  295. * @author libo
  296. * @date 2019-04-12
  297. * @param {Object} event
  298. * @param {String} customEventData
  299. */
  300. emitCustomEventData (event, customEventData) {
  301. if (!customEventData) {
  302. G.LogUtils.error('[emitCustomEventData] customEventData不能是空');
  303. return;
  304. }
  305. this.alertCallback(customEventData);
  306. },
  307. // ---------------- 私有方法分割线 ----------------
  308. /**
  309. * 开始触摸
  310. *
  311. * @author Pyden
  312. * @date 2019-03-25
  313. * @param {*} event
  314. */
  315. _onTouchStart (event) {
  316. if (this.isBlockOutside) {
  317. // 遮挡时,请添加 Button 组件来响应 blockOnClicked
  318. event.stopPropagation();
  319. }
  320. }
  321. });