SwipeGesture.cs 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. using System;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. namespace FairyGUI
  5. {
  6. /// <summary>
  7. /// 滑动手势。你可以通过onBegin+onMove+onEnd关心整个滑动过程,也可以只使用onAction关注最后的滑动结果。滑动结果包括方向和加速度,可以从position和velocity获得。
  8. /// 注意onAction仅当滑动超过一定距离(actionDistance)时才触发。
  9. /// </summary>
  10. public class SwipeGesture : EventDispatcher
  11. {
  12. /// <summary>
  13. ///
  14. /// </summary>
  15. public GObject host { get; private set; }
  16. /// <summary>
  17. /// 当手指开始扫动时派发该事件。
  18. /// </summary>
  19. public EventListener onBegin { get; private set; }
  20. /// <summary>
  21. /// 手指离开屏幕时派发该事件。
  22. /// </summary>
  23. public EventListener onEnd { get; private set; }
  24. /// <summary>
  25. /// 手指在滑动时派发该事件。
  26. /// </summary>
  27. public EventListener onMove { get; private set; }
  28. /// <summary>
  29. /// 当手指从按下到离开经过的距离大于actionDistance时派发该事件。
  30. /// </summary>
  31. public EventListener onAction { get; private set; }
  32. /// <summary>
  33. /// 手指离开时的加速度
  34. /// </summary>
  35. public Vector2 velocity;
  36. /// <summary>
  37. /// 你可以在onBegin事件中设置这个值,那个后续将根据手指移动的距离修改这个值。如果不设置,那position初始为(0,0),反映手指扫过的距离。
  38. /// </summary>
  39. public Vector2 position;
  40. /// <summary>
  41. /// 移动的变化值
  42. /// </summary>
  43. public Vector2 delta;
  44. /// <summary>
  45. /// The min distance to fire onAction event
  46. /// 派发onAction事件的最小距离。如果手指扫过的距离少于此值,onAction不会触发(但onEnd仍然会派发)
  47. /// </summary>
  48. public int actionDistance;
  49. /// <summary>
  50. /// 是否把变化量强制为整数。默认true。
  51. /// </summary>
  52. public bool snapping;
  53. Vector2 _startPoint;
  54. Vector2 _lastPoint;
  55. float _time;
  56. bool _started;
  57. bool _touchBegan;
  58. public static int ACTION_DISTANCE = 200;
  59. public SwipeGesture(GObject host)
  60. {
  61. this.host = host;
  62. actionDistance = ACTION_DISTANCE;
  63. snapping = true;
  64. Enable(true);
  65. onBegin = new EventListener(this, "onSwipeBegin");
  66. onEnd = new EventListener(this, "onSwipeEnd");
  67. onMove = new EventListener(this, "onSwipeMove");
  68. onAction = new EventListener(this, "onnSwipeAction");
  69. }
  70. public void Dispose()
  71. {
  72. Enable(false);
  73. host = null;
  74. }
  75. public void Enable(bool value)
  76. {
  77. if (value)
  78. {
  79. if (host == GRoot.inst)
  80. {
  81. Stage.inst.onTouchBegin.Add(__touchBegin);
  82. Stage.inst.onTouchMove.Add(__touchMove);
  83. Stage.inst.onTouchEnd.Add(__touchEnd);
  84. }
  85. else
  86. {
  87. host.onTouchBegin.Add(__touchBegin);
  88. host.onTouchMove.Add(__touchMove);
  89. host.onTouchEnd.Add(__touchEnd);
  90. }
  91. }
  92. else
  93. {
  94. _started = false;
  95. _touchBegan = false;
  96. if (host == GRoot.inst)
  97. {
  98. Stage.inst.onTouchBegin.Remove(__touchBegin);
  99. Stage.inst.onTouchMove.Remove(__touchMove);
  100. Stage.inst.onTouchEnd.Remove(__touchEnd);
  101. }
  102. else
  103. {
  104. host.onTouchBegin.Remove(__touchBegin);
  105. host.onTouchMove.Remove(__touchMove);
  106. host.onTouchEnd.Remove(__touchEnd);
  107. }
  108. }
  109. }
  110. void __touchBegin(EventContext context)
  111. {
  112. if (Stage.inst.touchCount > 1)
  113. {
  114. _touchBegan = false;
  115. if (_started)
  116. {
  117. _started = false;
  118. onEnd.Call(context.inputEvent);
  119. }
  120. return;
  121. }
  122. InputEvent evt = context.inputEvent;
  123. _startPoint = _lastPoint = host.GlobalToLocal(new Vector2(evt.x, evt.y));
  124. _lastPoint = _startPoint;
  125. _time = Time.unscaledTime;
  126. _started = false;
  127. velocity = Vector2.zero;
  128. position = Vector2.zero;
  129. _touchBegan = true;
  130. context.CaptureTouch();
  131. }
  132. void __touchMove(EventContext context)
  133. {
  134. if (!_touchBegan || Stage.inst.touchCount > 1)
  135. return;
  136. InputEvent evt = context.inputEvent;
  137. Vector2 pt = host.GlobalToLocal(new Vector2(evt.x, evt.y));
  138. delta = pt - _lastPoint;
  139. if (snapping)
  140. {
  141. delta.x = Mathf.Round(delta.x);
  142. delta.y = Mathf.Round(delta.y);
  143. if (delta.x == 0 && delta.y == 0)
  144. return;
  145. }
  146. float deltaTime = Time.unscaledDeltaTime;
  147. float elapsed = (Time.unscaledTime - _time) * 60 - 1;
  148. if (elapsed > 1) //速度衰减
  149. velocity = velocity * Mathf.Pow(0.833f, elapsed);
  150. velocity = Vector3.Lerp(velocity, delta / deltaTime, deltaTime * 10);
  151. _time = Time.unscaledTime;
  152. position += delta;
  153. _lastPoint = pt;
  154. if (!_started)
  155. { //灵敏度检查,为了和点击区分
  156. int sensitivity;
  157. if (Stage.touchScreen)
  158. sensitivity = UIConfig.touchDragSensitivity;
  159. else
  160. sensitivity = 5;
  161. if (Mathf.Abs(delta.x) < sensitivity && Mathf.Abs(delta.y) < sensitivity)
  162. return;
  163. _started = true;
  164. onBegin.Call(evt);
  165. }
  166. onMove.Call(evt);
  167. }
  168. void __touchEnd(EventContext context)
  169. {
  170. _touchBegan = false;
  171. if (!_started)
  172. return;
  173. _started = false;
  174. InputEvent evt = context.inputEvent;
  175. Vector2 pt = host.GlobalToLocal(new Vector2(evt.x, evt.y));
  176. delta = pt - _lastPoint;
  177. if (snapping)
  178. {
  179. delta.x = Mathf.Round(delta.x);
  180. delta.y = Mathf.Round(delta.y);
  181. }
  182. position += delta;
  183. //更新速度
  184. float elapsed = (Time.unscaledTime - _time) * 60 - 1;
  185. if (elapsed > 1)
  186. velocity = velocity * Mathf.Pow(0.833f, elapsed);
  187. if (snapping)
  188. {
  189. velocity.x = Mathf.Round(velocity.x);
  190. velocity.y = Mathf.Round(velocity.y);
  191. }
  192. onEnd.Call(evt);
  193. pt -= _startPoint;
  194. if (Mathf.Abs(pt.x) > actionDistance || Mathf.Abs(pt.y) > actionDistance)
  195. onAction.Call(evt);
  196. }
  197. }
  198. }