UI_Control_ScrollFlow.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544
  1. using System;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using UnityEngine.EventSystems;
  5. using UnityEngine.UI;
  6. /// <summary>
  7. ///
  8. /// </summary>
  9. public class UI_Control_ScrollFlow : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
  10. {
  11. /// <summary>
  12. ///
  13. /// </summary>
  14. public RectTransform Rect;
  15. /// <summary>
  16. ///
  17. /// </summary>
  18. public List<UI_Control_ScrollFlow_Item> ItemList = new List<UI_Control_ScrollFlow_Item>();
  19. /// <summary>
  20. /// 卡牌的像素宽度
  21. /// </summary>
  22. public float itemWidth = 500;
  23. /// <summary>
  24. /// 最大缩放
  25. /// </summary>
  26. public float MaxScale = 1.0f;
  27. /// <summary>
  28. /// 开始坐标值
  29. /// </summary>
  30. private float startValue = 0.5f;
  31. /// <summary>
  32. ///
  33. /// </summary>
  34. private int defaultItemIndex = 0;
  35. /// <summary>
  36. /// 卡牌之间的间隔坐标
  37. /// </summary>
  38. private float spaceValue = 0.2f;
  39. /// <summary>
  40. /// 移动速度曲线
  41. /// </summary>
  42. public AnimationCurve SpeedCurve;
  43. /// <summary>
  44. /// 坐标曲线
  45. /// </summary>
  46. public AnimationCurve PositionCurve;
  47. /// <summary>
  48. /// 缩放幅度大小曲线
  49. /// </summary>
  50. public AnimationCurve ScaleCurve;
  51. /// <summary>
  52. /// 拖拽时候的,托主幅度量
  53. /// </summary>
  54. private float dragV = 0;
  55. /// <summary>
  56. /// 拖拽时候的,计算值
  57. /// </summary>
  58. private Vector2 start_point, add_vect;
  59. /// <summary>
  60. /// 移动结束事件
  61. /// </summary>
  62. public event CallBack<UI_Control_ScrollFlow_Item> MoveEnd;
  63. /// <summary>
  64. /// 更改当前卡牌的状态
  65. /// </summary>
  66. public event CallBack<bool, UI_Control_ScrollFlow_Item> EventRefreshCardState;
  67. /// <summary>
  68. /// 是否开启动画
  69. /// </summary>
  70. public bool _anim = false;
  71. /// <summary>
  72. /// 移动的量
  73. /// </summary>
  74. private float AddV = 0;
  75. /// <summary>
  76. /// 移动方向
  77. /// </summary>
  78. private float Vk = 0;
  79. /// <summary>
  80. ///
  81. /// </summary>
  82. private float Vtotal = 0;
  83. /// <summary>
  84. /// 动画速度 * 单位时间* 移动方向,计算出来的移动值
  85. /// </summary>
  86. private float CurrentV = 0;
  87. /// <summary>
  88. ///
  89. /// </summary>
  90. private float VT = 0;
  91. /// <summary>
  92. ///
  93. /// </summary>
  94. private float _v1 = 0, _v2 = 0;
  95. /// <summary>
  96. /// 动画速度
  97. /// </summary>
  98. public float _anim_speed = 1f;
  99. /// <summary>
  100. ///
  101. /// </summary>
  102. public UI_Control_ScrollFlow_Item Current;
  103. /// <summary>
  104. /// 初始化组件
  105. /// </summary>
  106. public void InitComponments()
  107. {
  108. Rect = this.transform.GetComponent<RectTransform>();
  109. MaxScale = 1.0f;
  110. itemWidth = 500;
  111. //PositionCurve = AnimationCurve.EaseInOut(0, 0, 1.0f, 1.0f);
  112. float[] tixxx = new float[] {-0.22f, -0.02f, 0.18f, 0.5f, 0.82f, 1.02f, 1.22f, 1.42f, 1.62f, 1.82f, 2.02f, 2.22f, 2.42f, 2.62f, 2.82f, 3.02f, 3.22f, 3.42f, 3.62f, 3.82f, 4.02f, 4.22f, 4.42f, 4.62f, 4.82f };
  113. Keyframe[] ks = new Keyframe[3];
  114. ks[0] = new Keyframe(0, 0.95f);
  115. ks[1] = new Keyframe(0.5f, 1.0f);
  116. ks[2] = new Keyframe(1.0f, 0.95f);
  117. ScaleCurve = new AnimationCurve(ks);
  118. Keyframe[] spks = new Keyframe[5];
  119. spks[0] = new Keyframe(-1.0f, 2.0f);
  120. spks[1] = new Keyframe(-0.5f, 1.5f);
  121. spks[2] = new Keyframe(0, 0.5f);
  122. spks[3] = new Keyframe(0.5f, 1.5f);
  123. spks[4] = new Keyframe(1.0f, 2.0f);
  124. SpeedCurve = new AnimationCurve(spks);
  125. Keyframe[] posArr = new Keyframe[tixxx.Length];
  126. int index = 0;
  127. for (int i = -3; i <= 21; i++)
  128. {
  129. posArr[index] = new Keyframe(startValue + i * spaceValue, tixxx[index]);
  130. index++;
  131. }
  132. PositionCurve = new AnimationCurve(posArr);
  133. }
  134. /// <summary>
  135. /// 接手到通知,某个子对象的选中状态发生改变了
  136. /// </summary>
  137. public void OnReceiveUpdateState(bool isSelected, UI_Control_ScrollFlow_Item item)
  138. {
  139. if (EventRefreshCardState != null)
  140. {
  141. EventRefreshCardState(isSelected, item);
  142. }
  143. }
  144. /// <summary>
  145. ///
  146. /// </summary>
  147. public void Refresh(bool resetPosition = false)
  148. {
  149. if (Rect.childCount > 0)
  150. {
  151. int count = 0;
  152. for (int i = 0; i < Rect.childCount; i++)
  153. {
  154. Transform tran = Rect.GetChild(i);
  155. if (ItemsOld.Contains(tran))
  156. {
  157. continue;
  158. }
  159. if (!tran.gameObject.activeSelf)
  160. {
  161. continue;
  162. }
  163. count++;
  164. }
  165. //// Debug.LogError("countcountcount:::" + count);
  166. if (count > 5)
  167. {
  168. defaultItemIndex = 5;
  169. }
  170. else
  171. {
  172. defaultItemIndex = count - 1;
  173. }
  174. }
  175. //// Debug.LogError("defaultItemIndex::::" + defaultItemIndex);
  176. int rIndex = 0;
  177. for (int i = 0; i < Rect.childCount; i++)
  178. {
  179. Transform tran = Rect.GetChild(i);
  180. if (ItemsOld.Contains(tran))
  181. {
  182. continue;
  183. }
  184. if (!tran.gameObject.activeSelf)
  185. {
  186. continue;
  187. }
  188. UI_Control_ScrollFlow_Item item = tran.GetComponent<UI_Control_ScrollFlow_Item>();
  189. if (item != null)
  190. {
  191. item.Init(this, ItemList.Count);
  192. ItemList.Add(item);
  193. //item.Drag(startValue - (ItemList.Count - 1) * spaceValue);
  194. float dv = startValue + (rIndex - defaultItemIndex) * spaceValue;
  195. item.Drag(dv);
  196. //// Debug.LogError("CurrentItem::::" + dv);
  197. if (Mathf.Abs(dv - startValue) < 0.05f)
  198. {
  199. Current = item;
  200. //// Debug.LogError("CurrentItem::::" + item.gameObject.name);
  201. }
  202. rIndex++;
  203. }
  204. }
  205. //if (MoveEnd != null)
  206. //{
  207. // MoveEnd(Current);
  208. //}
  209. for (int i = 0; i < ItemList.Count; i++)
  210. {
  211. ItemList[i].Refresh();
  212. }
  213. ItemsOld.Clear();
  214. }
  215. /// <summary>
  216. ///
  217. /// </summary>
  218. public List<Transform> ItemsOld;
  219. /// <summary>
  220. ///
  221. /// </summary>
  222. public void Clear()
  223. {
  224. ItemsOld = new List<Transform>();
  225. for (int i = 0; i < ItemList.Count; i++)
  226. {
  227. ItemsOld.Add(ItemList[i].transform);
  228. Destroy(ItemList[i].gameObject);
  229. }
  230. ItemList.Clear();
  231. }
  232. /// <summary>
  233. ///
  234. /// </summary>
  235. /// <param name="eventData"></param>
  236. public void OnBeginDrag(PointerEventData eventData)
  237. {
  238. start_point = eventData.position;
  239. add_vect = Vector3.zero;
  240. _anim = false;
  241. }
  242. /// <summary>
  243. ///
  244. /// </summary>
  245. /// <param name="eventData"></param>
  246. public void OnDrag(PointerEventData eventData)
  247. {
  248. //判断此时 是不是已经到列表尽头,然后做一个极限设定
  249. if (ItemList[0].v > startValue)
  250. {
  251. float abs = Mathf.Abs(startValue - ItemList[0].v);
  252. if (abs > spaceValue)
  253. {
  254. return;
  255. }
  256. }
  257. if (ItemList[ItemList.Count - 1].v < startValue)
  258. {
  259. float abs = Mathf.Abs(startValue - ItemList[ItemList.Count - 1].v);
  260. if (abs > spaceValue)
  261. {
  262. return;
  263. }
  264. }
  265. add_vect = eventData.position - start_point;
  266. dragV = eventData.delta.x * 1.00f / itemWidth;
  267. //计算移动量,对应卡牌的比例
  268. for (int i = 0; i < ItemList.Count; i++)
  269. {
  270. ItemList[i].Drag(dragV);
  271. }
  272. }
  273. /// <summary>
  274. /// 这块需要调整
  275. /// 要不然不知道拖拽到哪个了......................
  276. /// </summary>
  277. /// <param name="eventData"></param>
  278. public void OnEndDrag(PointerEventData eventData)
  279. {
  280. float k = 0, v1;
  281. for (int i = 0; i < ItemList.Count; i++)
  282. {
  283. if (ItemList[i].v >= startValue)
  284. {
  285. v1 = (ItemList[i].v - startValue) % spaceValue;
  286. if (add_vect.x >= 0)
  287. {
  288. k = spaceValue - v1;
  289. //确定向右移动 ()
  290. }
  291. else
  292. {
  293. k = v1 * -1;
  294. }
  295. break;
  296. }
  297. }
  298. add_vect = Vector3.zero;
  299. // 判断是否拖拽到极限
  300. if (ItemList[0].v > startValue)
  301. {
  302. //说明向右滑道头了
  303. k = ItemList[0].v;
  304. k = startValue - k;
  305. AnimToEnd(k);
  306. return;
  307. }
  308. if (ItemList[ItemList.Count - 1].v < startValue)
  309. {
  310. k = ItemList[ItemList.Count - 1].v;
  311. k = startValue - k;
  312. AnimToEnd(k);
  313. return;
  314. }
  315. AnimToEnd(k);
  316. }
  317. /// <summary>
  318. ///
  319. /// </summary>
  320. /// <param name="v"></param>
  321. /// <returns></returns>
  322. public float GetPosition(float v, int _index)
  323. {
  324. //return v * itemWidth;
  325. return PositionCurve.Evaluate(v) * itemWidth;
  326. }
  327. /// <summary>
  328. /// 获取卡牌移动速度
  329. /// </summary>
  330. /// <param name="v"></param>
  331. /// <returns></returns>
  332. public float GetMoveSpeed(float v)
  333. {
  334. //return v * itemWidth;
  335. return SpeedCurve.Evaluate(v) * 1.0f;
  336. }
  337. /// <summary>
  338. ///
  339. /// </summary>
  340. /// <param name="v"></param>
  341. /// <returns></returns>
  342. public float GetScale(float v)
  343. {
  344. return ScaleCurve.Evaluate(v) * MaxScale;
  345. }
  346. /// <summary>
  347. /// 主要进行排序
  348. /// 除了中间之外的, 左侧的,从左到右绘制.
  349. /// 中间右侧,从右到左绘制
  350. /// </summary>
  351. public void LateUpdate()
  352. {
  353. List<UI_Control_ScrollFlow_Item> left = new List<UI_Control_ScrollFlow_Item>();
  354. List<UI_Control_ScrollFlow_Item> right = new List<UI_Control_ScrollFlow_Item>();
  355. List<UI_Control_ScrollFlow_Item> middle = new List<UI_Control_ScrollFlow_Item>();
  356. int index = 0;
  357. for (int i = 0; i < ItemList.Count; i++)
  358. {
  359. float abs = Mathf.Abs(startValue - ItemList[i].v);
  360. if (abs < 0.05f)
  361. {
  362. middle.Add(ItemList[i]);
  363. }
  364. else
  365. {
  366. if (ItemList[i].v > startValue)
  367. {
  368. right.Add(ItemList[i]);
  369. }
  370. else
  371. {
  372. left.Add(ItemList[i]);
  373. }
  374. }
  375. }
  376. for (int i = 0; i < left.Count; i++)
  377. {
  378. left[i].rect.SetSiblingIndex(index);
  379. index++;
  380. }
  381. for (int i = right.Count - 1; i >= 0; i--)
  382. {
  383. right[i].rect.SetSiblingIndex(index);
  384. index++;
  385. }
  386. for (int i = 0; i < middle.Count; i++)
  387. {
  388. middle[i].rect.SetSiblingIndex(index);
  389. index++;
  390. }
  391. }
  392. /// <summary>
  393. /// 移动结束
  394. /// </summary>
  395. /// <param name="k">移动距离</param>
  396. public void AnimToEnd(float k)
  397. {
  398. AddV = k;
  399. if (AddV > 0)
  400. {
  401. Vk = 1;
  402. }
  403. else if (AddV < 0)
  404. {
  405. Vk = -1;
  406. }
  407. else
  408. {
  409. return;
  410. }
  411. Vtotal = 0;
  412. _anim_speed = GetMoveSpeed(k);
  413. _anim = true;
  414. }
  415. /// <summary>
  416. ///
  417. /// </summary>
  418. private void Update()
  419. {
  420. if (_anim)
  421. {
  422. //// Debug.LogError("flow:::" + Time.deltaTime + " VKKK:" + Vk);
  423. CurrentV = Time.deltaTime * _anim_speed * Vk;
  424. ////通过update 来累加 CurrentV;
  425. ////直到移动量,达到要求的结束动画.
  426. ////主要对点击某个卡牌,移动直到显示某个具体位置卡牌有效.
  427. VT = Vtotal + CurrentV;
  428. if (Vk > 0 && VT >= AddV)
  429. {
  430. _anim = false;
  431. CurrentV = AddV - Vtotal;
  432. }
  433. if (Vk < 0 && VT <= AddV)
  434. {
  435. _anim = false;
  436. CurrentV = AddV - Vtotal;
  437. }
  438. ////=============================================
  439. for (int i = 0; i < ItemList.Count; i++)
  440. {
  441. ItemList[i].Drag(CurrentV);
  442. if (ItemList[i].v - startValue < 0.05f)
  443. {
  444. Current = ItemList[i];
  445. }
  446. }
  447. Vtotal = VT;
  448. if (!_anim)
  449. {
  450. //// Debug.LogError("end ened");
  451. if (MoveEnd != null)
  452. {
  453. MoveEnd(Current);
  454. }
  455. }
  456. }
  457. }
  458. /// <summary>
  459. /// 转到指定子对象显示
  460. /// </summary>
  461. /// <param name="script"></param>
  462. public void ToAppointedItem(UI_Control_ScrollFlow_Item script)
  463. {
  464. if (script == null)
  465. return;
  466. float k = script.v;
  467. k = startValue - k;
  468. AnimToEnd(k);
  469. }
  470. }