218 lines
6.8 KiB
C#
218 lines
6.8 KiB
C#
|
|
using UnityEngine;
|
|||
|
|
|
|||
|
|
public class CustomScrollView : MonoBehaviour
|
|||
|
|
{
|
|||
|
|
public RectTransform rectStopUp;
|
|||
|
|
public RectTransform rectStopDown;
|
|||
|
|
public RectTransform rectTitle;
|
|||
|
|
public RectTransform rectCenter;
|
|||
|
|
|
|||
|
|
public RectTransform rectCenterLimitUp;
|
|||
|
|
public RectTransform rectCenterLimitDown;
|
|||
|
|
public RectTransform rectCenterSubUp;
|
|||
|
|
public RectTransform rectCenterSubDown;
|
|||
|
|
|
|||
|
|
// <20><><EFBFBD><EFBFBD>Ч<EFBFBD><D0A7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
private float damping = 0.9f; // <20><><EFBFBD><EFBFBD>ϵ<EFBFBD><CFB5><EFBFBD><EFBFBD>ֵԽС<D4BD><D0A1><EFBFBD><EFBFBD>Խ<EFBFBD><D4BD>
|
|||
|
|
private float minVelocity = 0.1f; // <20><>С<EFBFBD>ٶ<EFBFBD><D9B6><EFBFBD>ֵ
|
|||
|
|
|
|||
|
|
private Vector3 vecStart;
|
|||
|
|
private Vector3 vecStartCenter;
|
|||
|
|
private Vector3 vecStartTitle;
|
|||
|
|
private Vector3 velocity = Vector3.zero; // <20><>ǰ<EFBFBD>ٶ<EFBFBD>
|
|||
|
|
private bool isDragging = false;
|
|||
|
|
private float lastMouseY;
|
|||
|
|
private bool shouldStopScrollUp = false; // <20>Ƿ<EFBFBD>Ӧ<EFBFBD><D3A6>ֹͣ<CDA3><D6B9><EFBFBD>ϻ<EFBFBD><CFBB><EFBFBD>
|
|||
|
|
private bool shouldStopScrollDown = false; // <20>Ƿ<EFBFBD>Ӧ<EFBFBD><D3A6>ֹͣ<CDA3><D6B9><EFBFBD>»<EFBFBD><C2BB><EFBFBD>
|
|||
|
|
|
|||
|
|
void Update()
|
|||
|
|
{
|
|||
|
|
if (Input.GetMouseButtonDown(0))
|
|||
|
|
{
|
|||
|
|
StartDragging();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (Input.GetMouseButtonUp(0))
|
|||
|
|
{
|
|||
|
|
StopDragging();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (Input.GetMouseButton(0))
|
|||
|
|
{
|
|||
|
|
HandleDragging();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Ӧ<>û<EFBFBD><C3BB><EFBFBD>Ч<EFBFBD><D0A7>
|
|||
|
|
ApplyInertia();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void StartDragging()
|
|||
|
|
{
|
|||
|
|
vecStart = Input.mousePosition;
|
|||
|
|
vecStartCenter = rectCenter.position;
|
|||
|
|
vecStartTitle = rectTitle.position;
|
|||
|
|
lastMouseY = Input.mousePosition.y;
|
|||
|
|
velocity = Vector3.zero;
|
|||
|
|
isDragging = true;
|
|||
|
|
shouldStopScrollUp = false;
|
|||
|
|
shouldStopScrollDown = false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void StopDragging()
|
|||
|
|
{
|
|||
|
|
isDragging = false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void HandleDragging()
|
|||
|
|
{
|
|||
|
|
if (!isDragging) return;
|
|||
|
|
|
|||
|
|
Vector3 currentMousePos = Input.mousePosition;
|
|||
|
|
|
|||
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Yֵ<59>ƶ<EFBFBD><C6B6><EFBFBD><EFBFBD>Ļ<EFBFBD><C4BB><EFBFBD>
|
|||
|
|
float deltaY = currentMousePos.y - vecStart.y;
|
|||
|
|
Vector3 newPosition = vecStartCenter + new Vector3(0, deltaY, 0);
|
|||
|
|
|
|||
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD>߽<EFBFBD><DFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
CheckScrollLimits(deltaY);
|
|||
|
|
|
|||
|
|
// <20><><EFBFBD>ݱ߽<DDB1><DFBD><EFBFBD><EFBFBD>ƾ<EFBFBD><C6BE><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD>rectCenterλ<72><CEBB>
|
|||
|
|
if (!(deltaY > 0 && shouldStopScrollDown) && !(deltaY < 0 && shouldStopScrollUp))
|
|||
|
|
{
|
|||
|
|
// ֱ<><D6B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>rectCenter<65><72>λ<EFBFBD><CEBB>
|
|||
|
|
rectCenter.position = newPosition;
|
|||
|
|
|
|||
|
|
// <20><><EFBFBD><EFBFBD>rectTitleӦ<65><D3A6><EFBFBD>ƶ<EFBFBD><C6B6><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><CEBB>
|
|||
|
|
Vector3 newTitlePosition = vecStartTitle + new Vector3(0, deltaY, 0);
|
|||
|
|
|
|||
|
|
// <20><><EFBFBD><EFBFBD>rectTitle<6C><65>λ<EFBFBD>ã<EFBFBD><C3A3><EFBFBD><EFBFBD>ܳ<EFBFBD><DCB3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>±߽<C2B1>
|
|||
|
|
float minY = rectStopDown.position.y;
|
|||
|
|
float maxY = rectStopUp.position.y;
|
|||
|
|
newTitlePosition.y = Mathf.Clamp(newTitlePosition.y, minY, maxY);
|
|||
|
|
|
|||
|
|
// <20><><EFBFBD><EFBFBD>rectTitle<6C><65>λ<EFBFBD><CEBB>
|
|||
|
|
rectTitle.position = newTitlePosition;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// <20><><EFBFBD>㵱ǰ<E3B5B1>ٶȣ<D9B6><C8A3><EFBFBD><EFBFBD>ڻ<EFBFBD><DABB><EFBFBD>Ч<EFBFBD><D0A7><EFBFBD><EFBFBD>
|
|||
|
|
float currentDeltaY = currentMousePos.y - lastMouseY;
|
|||
|
|
velocity = new Vector3(0, currentDeltaY / Time.deltaTime, 0);
|
|||
|
|
lastMouseY = currentMousePos.y;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void ApplyInertia()
|
|||
|
|
{
|
|||
|
|
if (!isDragging && velocity.magnitude > minVelocity)
|
|||
|
|
{
|
|||
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD>߽<EFBFBD><DFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
CheckScrollLimits(velocity.y * Time.deltaTime);
|
|||
|
|
|
|||
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD>Ӧ<EFBFBD><D3A6>ֹͣ<CDA3><D6B9><EFBFBD>Ի<EFBFBD><D4BB><EFBFBD>
|
|||
|
|
bool shouldStopInertia = (velocity.y > 0 && shouldStopScrollDown) || (velocity.y < 0 && shouldStopScrollUp);
|
|||
|
|
|
|||
|
|
if (!shouldStopInertia)
|
|||
|
|
{
|
|||
|
|
// ʹ<><CAB9>ָ<EFBFBD><D6B8>˥<EFBFBD><CBA5><EFBFBD>Ļ<EFBFBD><C4BB><EFBFBD>
|
|||
|
|
float deceleration = Mathf.Pow(damping, Time.deltaTime * 60f);
|
|||
|
|
velocity *= deceleration;
|
|||
|
|
|
|||
|
|
// rectCenter<65><72><EFBFBD><EFBFBD><EFBFBD>ƶ<EFBFBD>
|
|||
|
|
rectCenter.position += velocity * Time.deltaTime;
|
|||
|
|
|
|||
|
|
// rectTitle<6C><65><EFBFBD><EFBFBD>rectCenter<65>ƶ<EFBFBD><C6B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܱ߽<DCB1><DFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
Vector3 newTitlePosition = rectTitle.position + velocity * Time.deltaTime;
|
|||
|
|
float minY = rectStopDown.position.y;
|
|||
|
|
float maxY = rectStopUp.position.y;
|
|||
|
|
newTitlePosition.y = Mathf.Clamp(newTitlePosition.y, minY, maxY);
|
|||
|
|
rectTitle.position = newTitlePosition;
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
// <20><><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6>ֹͣ<CDA3><D6B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ټ<EFBFBD><D9BC><EFBFBD>
|
|||
|
|
velocity *= 0.5f;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (velocity.magnitude <= minVelocity)
|
|||
|
|
{
|
|||
|
|
velocity = Vector3.zero;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else if (!isDragging && velocity.magnitude <= minVelocity)
|
|||
|
|
{
|
|||
|
|
// <20><><EFBFBD>ٶȺ<D9B6>Сʱ<D0A1><CAB1>ȷ<EFBFBD><C8B7>rectTitle<6C><65><EFBFBD>ڱ߽<DAB1><DFBD><EFBFBD>
|
|||
|
|
Vector3 currentTitlePos = rectTitle.position;
|
|||
|
|
float minY = rectStopDown.position.y;
|
|||
|
|
float maxY = rectStopUp.position.y;
|
|||
|
|
currentTitlePos.y = Mathf.Clamp(currentTitlePos.y, minY, maxY);
|
|||
|
|
rectTitle.position = currentTitlePos;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// <20><><EFBFBD>黬<EFBFBD><E9BBAC><EFBFBD>߽<EFBFBD><DFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
private void CheckScrollLimits(float deltaY)
|
|||
|
|
{
|
|||
|
|
// <20><><EFBFBD>ñ<EFBFBD>־
|
|||
|
|
shouldStopScrollUp = false;
|
|||
|
|
shouldStopScrollDown = false;
|
|||
|
|
|
|||
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>»<EFBFBD><C2BB><EFBFBD>ʱrectCenterSubUp<55><70><EFBFBD>ܵ<EFBFBD><DCB5><EFBFBD>rectCenterLimitUp
|
|||
|
|
if (deltaY < 0) // <20><><EFBFBD>ϻ<EFBFBD><CFBB><EFBFBD><EFBFBD><EFBFBD>rectCenter<65><72><EFBFBD><EFBFBD><EFBFBD>ƶ<EFBFBD><C6B6><EFBFBD>
|
|||
|
|
{
|
|||
|
|
if (rectCenterSubUp != null && rectCenterLimitUp != null)
|
|||
|
|
{
|
|||
|
|
// <20><><EFBFBD><EFBFBD>rectCenterSubUp<55>ĵײ<C4B5><D7B2>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD>rectCenterLimitUp<55>Ķ<EFBFBD><C4B6><EFBFBD>
|
|||
|
|
float subUpBottom = rectCenterSubUp.position.y - rectCenterSubUp.rect.height / 2;
|
|||
|
|
float limitUpTop = rectCenterLimitUp.position.y + rectCenterLimitUp.rect.height / 2;
|
|||
|
|
|
|||
|
|
if (subUpBottom < limitUpTop)
|
|||
|
|
{
|
|||
|
|
shouldStopScrollUp = true;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϻ<EFBFBD><CFBB><EFBFBD>ʱrectCenterSubDown<77><6E><EFBFBD>ܸ<EFBFBD><DCB8><EFBFBD>rectCenterLimitDown
|
|||
|
|
if (deltaY > 0) // <20><><EFBFBD>»<EFBFBD><C2BB><EFBFBD><EFBFBD><EFBFBD>rectCenter<65><72><EFBFBD><EFBFBD><EFBFBD>ƶ<EFBFBD><C6B6><EFBFBD>
|
|||
|
|
{
|
|||
|
|
if (rectCenterSubDown != null && rectCenterLimitDown != null)
|
|||
|
|
{
|
|||
|
|
// <20><><EFBFBD><EFBFBD>rectCenterSubDown<77>Ķ<EFBFBD><C4B6><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD>rectCenterLimitDown<77>ĵײ<C4B5>
|
|||
|
|
float subDownTop = rectCenterSubDown.position.y + rectCenterSubDown.rect.height / 2;
|
|||
|
|
float limitDownBottom = rectCenterLimitDown.position.y - rectCenterLimitDown.rect.height / 2;
|
|||
|
|
|
|||
|
|
if (subDownTop > limitDownBottom)
|
|||
|
|
{
|
|||
|
|
shouldStopScrollDown = true;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// <20>ⲿ<EFBFBD><E2B2BF><EFBFBD>Ե<EFBFBD><D4B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӷ<EFBFBD><D3B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ٶȣ<D9B6><C8A3><EFBFBD><EFBFBD>練<EFBFBD><E7B7B4>Ч<EFBFBD><D0A7><EFBFBD><EFBFBD>
|
|||
|
|
public void AddVelocity(Vector3 additionalVelocity)
|
|||
|
|
{
|
|||
|
|
velocity += additionalVelocity;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// <20><><EFBFBD>û<EFBFBD><C3BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
public void SetDamping(float newDamping)
|
|||
|
|
{
|
|||
|
|
damping = Mathf.Clamp(newDamping, 0.1f, 0.99f);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// <20><>ȡ<EFBFBD><C8A1>ǰ<EFBFBD>ٶ<EFBFBD>
|
|||
|
|
public Vector3 GetCurrentVelocity()
|
|||
|
|
{
|
|||
|
|
return velocity;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǿ<EFBFBD>Ƹ<EFBFBD><C6B8><EFBFBD>rectTitleλ<65>õ<EFBFBD><C3B5>߽<EFBFBD><DFBD>ڣ<EFBFBD><DAA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڱ<EFBFBD>Ҫʱ<D2AA><CAB1><EFBFBD>ã<EFBFBD>
|
|||
|
|
public void ClampTitlePosition()
|
|||
|
|
{
|
|||
|
|
Vector3 currentTitlePos = rectTitle.position;
|
|||
|
|
float minY = rectStopDown.position.y;
|
|||
|
|
float maxY = rectStopUp.position.y;
|
|||
|
|
currentTitlePos.y = Mathf.Clamp(currentTitlePos.y, minY, maxY);
|
|||
|
|
rectTitle.position = currentTitlePos;
|
|||
|
|
}
|
|||
|
|
}
|