//基础手动/自动滚动代码
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

public class PstPanel : MonoBehaviour ,IEndDragHandler,IBeginDragHandler
{
protected ScrollRect rect;
RectTransform content;
public int pageCount;
public float[] pagePos;//存储各滚动页的坐标

public float runTime = 0;//控制滚动快慢的记录系统时间
public float holdTime = 0.2f;//控制滚动快慢的时间
public float startPos;//滚动窗口rect.horizontalNormalizedPosition属性线性变化的开始值
public int currentPage = 0;//当前滚动窗口要显示页面

public bool isMoving = false;

public bool isAutoRoll;
public float autoHodeTime = 2;//自动股东间隔时间
private float AutoRunTimer=0;//控制自动滚动间隔的记录系统时间

private bool isDrag = false;

public Action<int> OnPageChange;//事件/委托链:公开变量用于外部订阅

// Start is called before the first frame update
protected virtual void Start()
{
    Init();
}

private void Init()
{
    rect = GetComponent<ScrollRect>();
    content = transform.Find("Viewport/Content").GetComponent<RectTransform>();
    pageCount = content.childCount;
    if (pageCount == 1)
    {
        throw new System.Exception("UnAutoR");
    }
    pagePos = new float[pageCount];
    for (int i = 0; i < pagePos.Length; i++)
    {
        pagePos[i] = i * (1.0f / (float)(pageCount - 1));//计算并存储每个页面的坐标
    }
}

// Update is called once per frame
protected virtual void Update()
{
    LisenerMove();//监听移动方法
    LisenerAutoRoll();//监听自动移动方法
}

private void LisenerMove()//每帧执行:使窗口显示目标页面
{
    if (isMoving)
    {
        runTime += Time.deltaTime / holdTime;
        rect.horizontalNormalizedPosition = Mathf.Lerp(rect.horizontalNormalizedPosition, pagePos[currentPage], runTime);//runTime=1时立即移动到目标值
        if (runTime >= 1)
        {
            isMoving = false;
        }
    }
}

public void LisenerAutoRoll()
{
    if (isDrag) return;
    if (isAutoRoll)//间隔时间调用滚动方法
    {
        AutoRunTimer += Time.deltaTime;
        if(AutoRunTimer>=autoHodeTime)
        {
            AutoRunTimer = 0;
            currentPage++ ;
            currentPage %= pageCount;
            ScrollToPage(currentPage);
        }
    }
}
/// <summary>
/// 滚动到指定页面方法
/// </summary>
/// <param name="page">要滚动到的页面</param>
public void ScrollToPage(int page)
{
    isMoving = true;
    currentPage =page;
    runTime = 0;
    startPos = rect.horizontalNormalizedPosition;//范围(0~1)
    if(OnPageChange!=null)// OnPageChange?.Invoke(this.currentPage);
    {//作用同于广播此事件(委托连不为空则调用)
        OnPageChange(this.currentPage);
    }
}

public void OnEndDrag(PointerEventData eventData)//结束拖拽接口实现:重置自动滚动时间,判断当前停留位置更接近那个页面并移动到目标页面
{
    isDrag = false;
    AutoRunTimer = 0;
    ToEndPos();
}
/// <summary>
/// 拖拽结束时一定到目标位置    
/// </summary>
private void ToEndPos()
{
    int pageIndex = 0;
    for (int i = 1; i < pagePos.Length; i++)
    {
        if (Mathf.Abs(pagePos[i] - rect.horizontalNormalizedPosition) < Mathf.Abs(pagePos[pageIndex] - rect.horizontalNormalizedPosition))
        {
            pageIndex = i;
        }
    }
    ScrollToPage(pageIndex);
}

public void OnBeginDrag(PointerEventData eventData)//开始拖拽接口实现
{
    isDrag = true;
}

}

//通过代码继承与多态对父类代码复用与扩展添加缓动效果
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PageScale : PstPanel
{
public GameObject[] items;
public float currentScle = 1f;
public float otherScle = 0.6f;
public int lastPage;
public int nextPage;
public float percent;
protected override void Start()
{
base.Start();
items = new GameObject[pageCount];
for (int i = 0; i < pageCount; i++)
{
items[i] = transform.Find("Viewport/Content").transform.GetChild(i).gameObject;
}
}

protected override void Update()
{
    base.Update();
    LissenterScale();
    //SetItenSize(currentPage);
}
/// <summary>
/// 监听Scale
/// </summary>
public void LissenterScale()
{
    //获取当前上一页,下一页
    for (int i = 0; i < pagePos.Length; i++)
    {
        if(pagePos[i]<=rect.horizontalNormalizedPosition)
        {
            lastPage = i;
        }            
    }
    for (int i = 0; i < pagePos.Length; i++)
    {
        if(pagePos[i]>rect.horizontalNormalizedPosition)
        {
            nextPage = i;
            break;
        }
    }

    if (lastPage == nextPage)
        return;
    percent = (rect.horizontalNormalizedPosition - pagePos[lastPage]) / (pagePos[nextPage] - pagePos[lastPage]);//当前页到下一页0~1变动
    items[lastPage].transform.localScale = Vector3.Lerp(Vector3.one * currentScle, Vector3.one * otherScle, percent);//按比例返回a,b间的值0返回a,1返回b
    items[nextPage].transform.localScale = Vector3.Lerp(Vector3.one * currentScle, Vector3.one * otherScle, 1-percent);

    for (int i = 0; i < items.Length; i++)
    {
        if (i!=lastPage&&i!=nextPage)
            items[i].transform.localScale = Vector3.one * otherScle;
    }
}

}