UITween.ts 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. import { TweenEasing } from "./TweenEasing";
  2. const { ccclass, property, executeInEditMode, playOnFocus } = cc._decorator;
  3. /**
  4. * 缓动数据
  5. * @author 薛鸿潇
  6. */
  7. @ccclass("PropsData")
  8. export class PropsData {
  9. @property({ displayName: "坐标" })
  10. public position: cc.Vec2 = cc.Vec2.ZERO;
  11. @property({ displayName: "旋转" })
  12. public angle: number = 0;
  13. @property({ displayName: "缩放" })
  14. public scale: number = 1;
  15. @property({displayName: "显示隐藏", tooltip: '打勾是显示'})
  16. public active: boolean = true;
  17. }
  18. /**
  19. * 缓动数据
  20. * @author 薛鸿潇
  21. */
  22. @ccclass("TweenData")
  23. export class TweenData {
  24. @property({ displayName: "属性数据", type: PropsData })
  25. public propsData: PropsData = new PropsData();
  26. @property({ displayName: "持续时间", tooltip: '单位:秒' })
  27. public duration: number = 0.3;
  28. @property({ displayName: "延迟时间", tooltip: '单位:秒' })
  29. public delay: number = 0;
  30. @property({ displayName: "是否为差值" })
  31. public isOffset: boolean = false;
  32. @property({ displayName: '完成回调', tooltip: "缓动完成时触发", type: cc.Component.EventHandler })
  33. public onComplete: cc.Component.EventHandler[] = [];
  34. @property({ displayName: '开始回调', tooltip: "缓动启动时触发", type: cc.Component.EventHandler })
  35. public onStart: cc.Component.EventHandler[] = [];
  36. @property({ displayName: '过程回调', tooltip: "缓动更新时触发", type: cc.Component.EventHandler })
  37. public onUpdate: cc.Component.EventHandler[] = [];
  38. }
  39. /**
  40. * 缓动组件,目前只支持节点的三个基础属性
  41. * @author 薛鸿潇
  42. */
  43. @ccclass
  44. @executeInEditMode()
  45. @playOnFocus()
  46. export class UITween extends cc.Component {
  47. @property({ displayName: "节点初始属性", type: PropsData })
  48. public fromData: PropsData = new PropsData();
  49. @property({ displayName: "节点目标属性", type: TweenData })
  50. public targetData: TweenData[] = [];
  51. @property({ displayName: '缓动节点', tooltip: "要播放缓动动画的目标,不填则是当前节点", type: cc.Node })
  52. public target: cc.Node = null;
  53. @property({ displayName: "缓动效果", type: cc.Enum(TweenEasing) })
  54. public tweenEasing: TweenEasing = TweenEasing.sineInOut;
  55. @property({ displayName: '执行次数', tooltip: "为0则一直重复执行" })
  56. public repeat: number = 1;
  57. @property({ displayName: "单次完成回调", tooltip: '单次缓动序列执行完毕时触发', type: cc.Component.EventHandler })
  58. public onOneRepeatComplete: cc.Component.EventHandler = new cc.Component.EventHandler();
  59. @property({ displayName: "自动播放" })
  60. public playOnLoad: boolean = true;
  61. @property({displayName:'是否设置起始位置为屏幕旁边按屏幕加节点尺寸的一半'})
  62. public isSetSuitStartPos: boolean = false;
  63. private _edit_play: boolean = false;
  64. @property({ displayName: "编辑器预览" })
  65. get edit_play(): boolean {
  66. if (this._edit_play && !this.edit_playing) {
  67. this.edit_playing = true;
  68. this.play();
  69. }
  70. return this._edit_play;
  71. }
  72. set edit_play(v: boolean) {
  73. this._edit_play = v;
  74. if (this.target && v) {
  75. cc.Tween.stopAllByTarget(this.target);
  76. }
  77. if (!v) this.edit_playing = false;
  78. }
  79. private resetProperty: boolean = false;
  80. @property({displayName: '重置基础属性'})
  81. get reset_property():boolean{
  82. if(this.resetProperty)
  83. {
  84. this.fromData.position = cc.v2(this.node.position.x, this.node.position.y);
  85. this.fromData.angle = this.node.angle;
  86. this.fromData.scale = this.node.scale;
  87. for(let i = 0; i != this.targetData.length; ++i)
  88. {
  89. let target = this.targetData[i];
  90. target.propsData.position = cc.v2(this.node.position.x, this.node.position.y);
  91. target.propsData.angle = this.node.angle;
  92. target.propsData.scale = this.node.scale;
  93. }
  94. this.resetProperty = false;
  95. }
  96. return this.resetProperty;
  97. }
  98. set reset_property(v){
  99. this.resetProperty = v;
  100. }
  101. /** 编辑器是否正在播放 */
  102. private edit_playing = false;
  103. public start() {
  104. !this.target && (this.target = this.node);
  105. this.target = this.target || this.node;
  106. this.currentRepeat = this.repeat;
  107. if (CC_EDITOR) {
  108. this._edit_play && this.play();
  109. } else {
  110. this.playOnLoad && this.play();
  111. }
  112. }
  113. private t: cc.Tween<any>;
  114. /** 剩余播放次数 */
  115. private currentRepeat: number;
  116. public play() {
  117. if (CC_EDITOR && !this.edit_playing) return;
  118. if (this.repeat == 0) {
  119. this.t = cc.tween(this.target);
  120. this.readyPlay();
  121. this.t = this.t.call(this.play.bind(this));
  122. this.t.start();
  123. }
  124. else if (this.currentRepeat) {
  125. this.t = cc.tween(this.target);
  126. this.readyPlay();
  127. this.t = this.t.call(this.play.bind(this));
  128. this.currentRepeat--;
  129. this.t.start();
  130. }
  131. else {
  132. this.t = null;
  133. this.currentRepeat = this.repeat;
  134. this.edit_play = false;
  135. }
  136. }
  137. public readyPlay() {
  138. let self = this;
  139. if (this.fromData) {
  140. if(this.isSetSuitStartPos)
  141. {
  142. if(this.fromData.position.x >0)
  143. {
  144. this.fromData.position.x = cc.winSize.width / 2 + this.target.getContentSize().width/2;
  145. }else{
  146. this.fromData.position.x = -cc.winSize.width / 2 - this.target.getContentSize().width/2;
  147. }
  148. }
  149. this.node.setPosition(this.fromData.position.clone());
  150. this.node.scale = this.fromData.scale;
  151. this.node.angle = this.fromData.angle;
  152. this.node.active = this.fromData.active;
  153. }
  154. if (this.targetData.length) {
  155. for (let i = 0; i < this.targetData.length; i++) {
  156. const targetData = this.targetData[i];
  157. if (targetData.delay != 0) {
  158. this.t = this.t.delay(targetData.delay);
  159. }
  160. if(targetData.propsData.active)
  161. {
  162. this.t = this.t.call(()=>{
  163. this.node.active = true;
  164. });
  165. }else{
  166. this.t = this.t.call(()=>{
  167. this.node.active = false;
  168. });
  169. }
  170. let toData = {
  171. position: targetData.propsData.position,
  172. scale: targetData.propsData.scale,
  173. angle: targetData.propsData.angle,
  174. }
  175. if (targetData.isOffset) {
  176. toData.position = this.node.getPosition().add(targetData.propsData.position);
  177. toData.scale = this.node.scale + targetData.propsData.scale;
  178. toData.angle = this.node.angle + targetData.propsData.angle;
  179. }
  180. this.t = this.t.to(
  181. targetData.duration,
  182. toData,
  183. {
  184. easing: TweenEasing[this.tweenEasing] as any,
  185. onComplete: (target: cc.Node) => {
  186. console.log("----------tweenComplete");
  187. if(targetData.onComplete && targetData.onComplete.length > 0)
  188. {
  189. for(let i = 0; i != targetData.onComplete.length; ++i)
  190. {
  191. targetData.onComplete[i].emit([target]);
  192. }
  193. }
  194. //targetData.onComplete && targetData.onComplete.emit([target]);
  195. // this.edit_playing = false;
  196. // this._edit_play = false;
  197. },
  198. onStart: (target: cc.Node) => {
  199. console.log("----------tweenStart");
  200. //targetData.onStart && targetData.onStart.emit([target])
  201. if(targetData.onStart && targetData.onStart.length > 0)
  202. {
  203. for(let i = 0; i != targetData.onStart.length; ++i)
  204. {
  205. targetData.onStart[i].emit([target]);
  206. }
  207. }
  208. },
  209. onUpdate: (target: cc.Node, ratio: number) => {
  210. //targetData.onUpdate && targetData.onUpdate.emit([target, ratio])
  211. if(targetData.onUpdate && targetData.onUpdate.length > 0)
  212. {
  213. for(let i = 0; i != targetData.onUpdate.length; ++i)
  214. {
  215. targetData.onUpdate[i].emit([target]);
  216. }
  217. }
  218. }
  219. }
  220. );
  221. }
  222. }
  223. if (this.onOneRepeatComplete) {
  224. this.t = this.t.call(() => {
  225. self.onOneRepeatComplete.emit([this, this.t])
  226. });
  227. }
  228. }
  229. }