暂无描述
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

PhotoScrollView.cs 4.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using UnityEngine.EventSystems;
  5. using UnityEngine.UI;
  6. using TMPro;
  7. public class PhotoScrollView : MonoBehaviour, IBeginDragHandler, IEndDragHandler, IDragHandler
  8. {
  9. public ScrollRect smallScrollView;
  10. public ScrollRect largeScrollView;
  11. public TextMeshProUGUI pageIndicatorText;
  12. public float swipeThreshold = 150f; // 拖曳触发阈值
  13. public float snapSpeed = 10f; // 吸附速度
  14. public float threshold = 20f;
  15. private Vector2 startDragPos; // 拖曳开始位置
  16. private Vector2 endDragPos; // 拖曳结束位置
  17. private bool isDragging = false; // 是否正在拖曳
  18. private bool isVerticalDrag;
  19. private int currentPage = 0;
  20. private int totalPages = 0;
  21. private void Awake()
  22. {
  23. StartCoroutine(InitAfterMainScriptStarts());
  24. }
  25. public IEnumerator InitAfterMainScriptStarts()
  26. {
  27. yield return new WaitForEndOfFrame(); // 等待到當前幀結束
  28. // 在這裡進行 PhotoScrollView 的初始化
  29. totalPages = smallScrollView.content.childCount - 1;
  30. UpdatePageIndicator();
  31. }
  32. public void OnBeginDrag(PointerEventData eventData)
  33. {
  34. startDragPos = eventData.position;
  35. Vector2 dragDelta = eventData.delta.normalized; // 正規化的拖曳向量
  36. isVerticalDrag = Mathf.Abs(dragDelta.y) > Mathf.Abs(dragDelta.x); // 判断拖拽方向
  37. if (isVerticalDrag)
  38. {
  39. largeScrollView.OnBeginDrag(eventData);
  40. // 如果是垂直方向的拖拽,则禁用小的水平滚动视图
  41. smallScrollView.enabled = false;
  42. }
  43. else
  44. {
  45. // 如果是水平方向的拖拽,则禁用大的垂直滚动视图
  46. largeScrollView.enabled = false;
  47. }
  48. }
  49. public void OnDrag(PointerEventData eventData)
  50. {
  51. if (isVerticalDrag)
  52. {
  53. // 垂直方向的拖拽,传递事件给大的垂直滚动视图
  54. largeScrollView.OnDrag(eventData);
  55. }
  56. else
  57. {
  58. // 水平方向的拖拽
  59. if (Mathf.Abs(eventData.delta.y) > threshold)
  60. {
  61. // 如果超過閥值,則禁用小的水平滾動視圖
  62. smallScrollView.enabled = false;
  63. }
  64. else
  65. {
  66. // 如果沒有超過閥值,則啟用小的水平滾動視圖
  67. smallScrollView.enabled = true;
  68. }
  69. }
  70. }
  71. public void OnEndDrag(PointerEventData eventData)
  72. {
  73. if (isVerticalDrag)
  74. {
  75. largeScrollView.OnEndDrag(eventData);
  76. smallScrollView.enabled = true;
  77. }
  78. else
  79. {
  80. // 水平方向的拖拽,恢复大的垂直滚动视图
  81. largeScrollView.enabled = true;
  82. // 判断水平拖动的距离,根据情况显示上一页或下一页
  83. float dragDistance = Mathf.Abs(eventData.position.x - startDragPos.x);
  84. if (dragDistance > swipeThreshold)
  85. {
  86. if (eventData.position.x > startDragPos.x)
  87. {
  88. ShowPreviousPage();
  89. }
  90. else
  91. {
  92. ShowNextPage();
  93. }
  94. }
  95. else
  96. {
  97. SnapToNearestPage();
  98. }
  99. }
  100. }
  101. private void ShowPreviousPage()
  102. {
  103. if (currentPage > 0)
  104. {
  105. currentPage--;
  106. float normalizedPosition = (float)currentPage / (float)(totalPages-1 );
  107. StartCoroutine(SmoothScrollTo(normalizedPosition));
  108. UpdatePageIndicator();
  109. }
  110. }
  111. private void ShowNextPage()
  112. {
  113. if (currentPage < totalPages - 1)
  114. {
  115. currentPage++;
  116. float normalizedPosition = (float)currentPage / (float)(totalPages-1 );
  117. StartCoroutine(SmoothScrollTo(normalizedPosition));
  118. UpdatePageIndicator();
  119. }
  120. }
  121. private IEnumerator SmoothScrollTo(float targetNormalizedPosition)
  122. {
  123. while (Mathf.Abs(smallScrollView.horizontalNormalizedPosition - targetNormalizedPosition) > 0.01f)
  124. {
  125. smallScrollView.horizontalNormalizedPosition = Mathf.Lerp(smallScrollView.horizontalNormalizedPosition, targetNormalizedPosition, snapSpeed * Time.deltaTime);
  126. yield return null;
  127. }
  128. smallScrollView.horizontalNormalizedPosition = targetNormalizedPosition;
  129. }
  130. private void SnapToNearestPage()
  131. {
  132. float targetNormalizedPosition = (float)currentPage / (float)(totalPages-1);
  133. StartCoroutine(SmoothScrollTo(targetNormalizedPosition));
  134. }
  135. public void UpdatePageIndicator()
  136. {
  137. pageIndicatorText.text = string.Format("{0}/{1}", currentPage + 1, totalPages);
  138. }
  139. }