JMAlertBase.js 8.6 KB

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