dezhou_client/wb_unity_pro/Assets/Scripts/LuaHelper/CustomScrollView.cs

218 lines
6.8 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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;
// 缓冲效果参数
private float damping = 0.9f; // 阻尼系数,值越小缓冲越快
private float minVelocity = 0.1f; // 最小速度阈值
private Vector3 vecStart;
private Vector3 vecStartCenter;
private Vector3 vecStartTitle;
private Vector3 velocity = Vector3.zero; // 当前速度
private bool isDragging = false;
private float lastMouseY;
private bool shouldStopScrollUp = false; // 是否应该停止向上滑动
private bool shouldStopScrollDown = false; // 是否应该停止向下滑动
void Update()
{
if (Input.GetMouseButtonDown(0))
{
StartDragging();
}
if (Input.GetMouseButtonUp(0))
{
StopDragging();
}
if (Input.GetMouseButton(0))
{
HandleDragging();
}
// 应用缓冲效果
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;
// 计算基于鼠标Y值移动量的滑动
float deltaY = currentMousePos.y - vecStart.y;
Vector3 newPosition = vecStartCenter + new Vector3(0, deltaY, 0);
// 检查边界限制
CheckScrollLimits(deltaY);
// 根据边界限制决定是否更新rectCenter位置
if (!(deltaY > 0 && shouldStopScrollDown) && !(deltaY < 0 && shouldStopScrollUp))
{
// 直接设置rectCenter的位置
rectCenter.position = newPosition;
// 计算rectTitle应该移动到的位置
Vector3 newTitlePosition = vecStartTitle + new Vector3(0, deltaY, 0);
// 限制rectTitle的位置不能超过上下边界
float minY = rectStopDown.position.y;
float maxY = rectStopUp.position.y;
newTitlePosition.y = Mathf.Clamp(newTitlePosition.y, minY, maxY);
// 设置rectTitle的位置
rectTitle.position = newTitlePosition;
}
// 计算当前速度(用于缓冲效果)
float currentDeltaY = currentMousePos.y - lastMouseY;
velocity = new Vector3(0, currentDeltaY / Time.deltaTime, 0);
lastMouseY = currentMousePos.y;
}
private void ApplyInertia()
{
if (!isDragging && velocity.magnitude > minVelocity)
{
// 检查边界限制
CheckScrollLimits(velocity.y * Time.deltaTime);
// 检查是否应该停止惯性滑动
bool shouldStopInertia = (velocity.y > 0 && shouldStopScrollDown) || (velocity.y < 0 && shouldStopScrollUp);
if (!shouldStopInertia)
{
// 使用指数衰减的缓冲
float deceleration = Mathf.Pow(damping, Time.deltaTime * 60f);
velocity *= deceleration;
// rectCenter继续移动
rectCenter.position += velocity * Time.deltaTime;
// rectTitle跟随rectCenter移动但受边界限制
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
{
// 如果应该停止,则快速减速
velocity *= 0.5f;
}
if (velocity.magnitude <= minVelocity)
{
velocity = Vector3.zero;
}
}
else if (!isDragging && velocity.magnitude <= minVelocity)
{
// 当速度很小时确保rectTitle仍在边界内
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;
}
}
// 检查滑动边界限制
private void CheckScrollLimits(float deltaY)
{
// 重置标志
shouldStopScrollUp = false;
shouldStopScrollDown = false;
// 检查向下滑动时rectCenterSubUp不能低于rectCenterLimitUp
if (deltaY < 0) // 向上滑动rectCenter向下移动
{
if (rectCenterSubUp != null && rectCenterLimitUp != null)
{
// 检查rectCenterSubUp的底部是否低于rectCenterLimitUp的顶部
float subUpBottom = rectCenterSubUp.position.y - rectCenterSubUp.rect.height / 2;
float limitUpTop = rectCenterLimitUp.position.y + rectCenterLimitUp.rect.height / 2;
if (subUpBottom < limitUpTop)
{
shouldStopScrollUp = true;
}
}
}
// 检查向上滑动时rectCenterSubDown不能高于rectCenterLimitDown
if (deltaY > 0) // 向下滑动rectCenter向上移动
{
if (rectCenterSubDown != null && rectCenterLimitDown != null)
{
// 检查rectCenterSubDown的顶部是否高于rectCenterLimitDown的底部
float subDownTop = rectCenterSubDown.position.y + rectCenterSubDown.rect.height / 2;
float limitDownBottom = rectCenterLimitDown.position.y - rectCenterLimitDown.rect.height / 2;
if (subDownTop > limitDownBottom)
{
shouldStopScrollDown = true;
}
}
}
}
// 外部可以调用这个方法来添加额外的速度(例如反弹效果)
public void AddVelocity(Vector3 additionalVelocity)
{
velocity += additionalVelocity;
}
// 设置缓冲参数
public void SetDamping(float newDamping)
{
damping = Mathf.Clamp(newDamping, 0.1f, 0.99f);
}
// 获取当前速度
public Vector3 GetCurrentVelocity()
{
return velocity;
}
// 新增强制更新rectTitle位置到边界内可以在必要时调用
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;
}
}