//-------------------------------------------------------- // [Author]: 第二世界 // [ Date ]: Monday, September 11, 2017 //-------------------------------------------------------- using UnityEngine; using System.Collections; using UnityEngine.UI; using UnityEngine.EventSystems; using System; namespace vnxbqy.UI { public class FlipScroll : MaskableGraphic, IBeginDragHandler, IEndDragHandler, IDragHandler { public enum FlipDirEnum { Horizon, Vertical, } private int page = 0; /// /// 当前页 /// public int Page { get { return page; } } [SerializeField] private FlipDirEnum flipType = FlipDirEnum.Horizon; public FlipDirEnum FlipType { get { return flipType; } set { flipType = value; } } [SerializeField] private bool m_Loop = false; public bool loop { get { return m_Loop; } set { m_Loop = value; } } [SerializeField] private TweenType _tweenType = TweenType.Linear; public TweenType tweenType { get { return _tweenType; } set { _tweenType = value; } } [SerializeField] private float sensitive = 5.0f; public float Sensitive { get { return sensitive; } set { sensitive = value; } } [SerializeField] public bool resetOnEnable = true; private bool tweening = false; public bool IsTweening { get { return tweening; } } [SerializeField] private float _tweenTime = 1.0f; public float TweenTime { get { return _tweenTime; } set { _tweenTime = value; } } public RectTransform presentRT; public RectTransform lastRT; private RectTransform presentFlipRT; private RectTransform lastFlipRT; public event Action OnRefreshData; public event Action OnTweenCompt; public int pageCnt = 0; [HideInInspector] public bool locked = false; protected override void Awake() { base.Awake(); if (presentRT == null || lastRT == null) return; presentRT.SetActive(false); lastRT.SetActive(false); presentFlipRT = presentRT; lastFlipRT = lastRT; } protected override void OnEnable() { base.OnEnable(); if (presentRT == null || lastRT == null || pageCnt == 0) return; presentRT.SetActive(true); lastRT.SetActive(true); presentRT.localPosition = Vector3.zero; if (resetOnEnable) { switch (FlipType) { case FlipDirEnum.Horizon: lastRT.localPosition = rectTransform.localPosition.SetX(rectTransform.sizeDelta.x); break; case FlipDirEnum.Vertical: lastRT.localPosition = rectTransform.localPosition.SetY(-rectTransform.sizeDelta.y); break; } page = 0; } presentFlipRT = presentRT; lastFlipRT = lastRT; RefreshActive(); } private Vector2 lastPos = Vector2.zero; public void OnBeginDrag(PointerEventData eventData) { lastPos = eventData.position; } public void OnEndDrag(PointerEventData eventData) { if (IsTweening || locked) return; Vector2 nPos = lastPos - eventData.position; switch (FlipType) { case FlipDirEnum.Horizon: { if (Math.Abs(nPos.x) < sensitive) return; if (nPos.x > 0) { FlipRight(); } else { FlipLeft(); } } break; case FlipDirEnum.Vertical: { if (Math.Abs(nPos.y) < sensitive) return; Vector3 pos = Vector3.zero; if (nPos.y < 0) { FlipLeft(); } else { FlipRight(); } } break; } } protected override void OnDisable() { tweening = false; StopAllCoroutines(); base.OnDisable(); } IEnumerator TweenPosition(Vector3 lPos, Vector3 nPos, Vector3 lastRtPos) { float time = 0; Vector3 newPresentPos = Vector3.zero; Vector3 newLastPos = Vector3.zero; bool InView = false; tweening = true; while (time < _tweenTime) { float per = 0; switch (tweenType) { case TweenType.Immediate: per = 1; break; case TweenType.Linear: per = Linear(time / _tweenTime); break; case TweenType.Smooth: per = Smooth(time / _tweenTime); break; } newPresentPos = Vector3.Lerp(lPos, nPos, per); newLastPos = Vector3.Lerp(lastRtPos, Vector3.zero, per); presentFlipRT.localPosition = newPresentPos; lastFlipRT.localPosition = newLastPos; time += Time.unscaledDeltaTime; if (!InView) { InView = InViewSide(); } if (tweenType == TweenType.Immediate) { break; } yield return null; } tweening = false; presentFlipRT.localPosition = nPos; lastFlipRT.localPosition = Vector3.zero; RectTransform temp = presentFlipRT; presentFlipRT = lastFlipRT; lastFlipRT = temp; if (OnTweenCompt != null) OnTweenCompt(); } public bool InViewSide() { switch (FlipType) { case FlipDirEnum.Horizon: { if (Vector3.Distance(Vector3.zero, lastFlipRT.localPosition) < lastFlipRT.sizeDelta.x + rectTransform.sizeDelta.x) { if (OnRefreshData != null) { lastFlipRT.SetActive(true); OnRefreshData(page, lastFlipRT); } return true; } } break; case FlipDirEnum.Vertical: { if (Vector3.Distance(Vector3.zero, lastFlipRT.localPosition) < lastFlipRT.sizeDelta.y + rectTransform.sizeDelta.y) { if (OnRefreshData != null) { lastFlipRT.SetActive(true); OnRefreshData(page, lastFlipRT); } return true; } } break; } return false; } private float Linear(float val) { return Mathf.Lerp(0, 1, val); } private float Smooth(float val) { float result = Mathf.SmoothStep(0, 1, val); result = Mathf.Clamp(result, 0, 1); return result; } public void RefreshActive() { if (pageCnt == 0 || presentFlipRT == null) return; if (OnRefreshData != null) { presentFlipRT.SetActive(true); OnRefreshData(page, presentFlipRT); } } public void FlipLeft() { if (IsTweening || pageCnt == 0) return; Vector3 pos = Vector3.zero; page--; if (page < 0) { if (loop) { page = pageCnt - 1; } else { page = 0; return; } } switch (FlipType) { case FlipDirEnum.Horizon: { lastFlipRT.localPosition = rectTransform.localPosition.SetX(-rectTransform.sizeDelta.x); pos = rectTransform.localPosition.SetX(rectTransform.sizeDelta.x); } break; case FlipDirEnum.Vertical: { lastFlipRT.localPosition = rectTransform.localPosition.SetY(rectTransform.sizeDelta.y); pos = rectTransform.localPosition.SetY(-rectTransform.sizeDelta.y); } break; } StartCoroutine(TweenPosition(presentFlipRT.localPosition, pos, lastFlipRT.localPosition)); } public void FlipRight() { if (IsTweening || pageCnt == 0) return; Vector3 pos = Vector3.zero; page++; if (page >= pageCnt) { if (loop) { page = 0; } else { page = pageCnt - 1; return; } } switch (FlipType) { case FlipDirEnum.Horizon: { lastFlipRT.localPosition = rectTransform.localPosition.SetX(rectTransform.sizeDelta.x); pos = rectTransform.localPosition.SetX(-rectTransform.sizeDelta.x); } break; case FlipDirEnum.Vertical: { lastFlipRT.localPosition = rectTransform.localPosition.SetY(-rectTransform.sizeDelta.y); pos = rectTransform.localPosition.SetY(rectTransform.sizeDelta.y); } break; } StartCoroutine(TweenPosition(presentFlipRT.localPosition, pos, lastFlipRT.localPosition)); } public void OnDrag(PointerEventData eventData) { } public enum TweenType { Immediate, Linear, Smooth, } } }