using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; using TMPro; public class PhotoScrollView : MonoBehaviour, IBeginDragHandler, IEndDragHandler, IDragHandler { public ScrollRect smallScrollView; public ScrollRect largeScrollView; public TextMeshProUGUI pageIndicatorText; public float swipeThreshold = 150f; // 拖曳触发阈值 public float snapSpeed = 10f; // 吸附速度 public float threshold = 20f; private Vector2 startDragPos; // 拖曳开始位置 private Vector2 endDragPos; // 拖曳结束位置 private bool isDragging = false; // 是否正在拖曳 private bool isVerticalDrag; private int currentPage = 0; private int totalPages = 0; private void Awake() { StartCoroutine(InitAfterMainScriptStarts()); } public IEnumerator InitAfterMainScriptStarts() { yield return new WaitForEndOfFrame(); // 等待到當前幀結束 // 在這裡進行 PhotoScrollView 的初始化 totalPages = smallScrollView.content.childCount - 1; UpdatePageIndicator(); } public void OnBeginDrag(PointerEventData eventData) { startDragPos = eventData.position; Vector2 dragDelta = eventData.delta.normalized; // 正規化的拖曳向量 isVerticalDrag = Mathf.Abs(dragDelta.y) > Mathf.Abs(dragDelta.x); // 判断拖拽方向 if (isVerticalDrag) { largeScrollView.OnBeginDrag(eventData); // 如果是垂直方向的拖拽,则禁用小的水平滚动视图 smallScrollView.enabled = false; } else { // 如果是水平方向的拖拽,则禁用大的垂直滚动视图 largeScrollView.enabled = false; } } public void OnDrag(PointerEventData eventData) { if (isVerticalDrag) { // 垂直方向的拖拽,传递事件给大的垂直滚动视图 largeScrollView.OnDrag(eventData); } else { // 水平方向的拖拽 if (Mathf.Abs(eventData.delta.y) > threshold) { // 如果超過閥值,則禁用小的水平滾動視圖 smallScrollView.enabled = false; } else { // 如果沒有超過閥值,則啟用小的水平滾動視圖 smallScrollView.enabled = true; } } } public void OnEndDrag(PointerEventData eventData) { if (isVerticalDrag) { largeScrollView.OnEndDrag(eventData); smallScrollView.enabled = true; } else { // 水平方向的拖拽,恢复大的垂直滚动视图 largeScrollView.enabled = true; // 判断水平拖动的距离,根据情况显示上一页或下一页 float dragDistance = Mathf.Abs(eventData.position.x - startDragPos.x); if (dragDistance > swipeThreshold) { if (eventData.position.x > startDragPos.x) { ShowPreviousPage(); } else { ShowNextPage(); } } else { SnapToNearestPage(); } } } private void ShowPreviousPage() { if (currentPage > 0) { currentPage--; float normalizedPosition = (float)currentPage / (float)(totalPages-1 ); StartCoroutine(SmoothScrollTo(normalizedPosition)); UpdatePageIndicator(); } } private void ShowNextPage() { if (currentPage < totalPages - 1) { currentPage++; float normalizedPosition = (float)currentPage / (float)(totalPages-1 ); StartCoroutine(SmoothScrollTo(normalizedPosition)); UpdatePageIndicator(); } } private IEnumerator SmoothScrollTo(float targetNormalizedPosition) { while (Mathf.Abs(smallScrollView.horizontalNormalizedPosition - targetNormalizedPosition) > 0.01f) { smallScrollView.horizontalNormalizedPosition = Mathf.Lerp(smallScrollView.horizontalNormalizedPosition, targetNormalizedPosition, snapSpeed * Time.deltaTime); yield return null; } smallScrollView.horizontalNormalizedPosition = targetNormalizedPosition; } private void SnapToNearestPage() { float targetNormalizedPosition = (float)currentPage / (float)(totalPages-1); StartCoroutine(SmoothScrollTo(targetNormalizedPosition)); } public void UpdatePageIndicator() { pageIndicatorText.text = string.Format("{0}/{1}", currentPage + 1, totalPages); } }