unity实现图片查看器有限制的移动缩放功能

发布于:2025-03-29 ⋅ 阅读:(32) ⋅ 点赞:(0)

需求
unity实现键盘wasd键控制图片的移动,图片长度未超出屏幕不能移动,宽度未超出屏幕不能移动。jk键控制图片的缩放,缩放有限制

using UnityEngine;

public class ImageController : MonoBehaviour
{
    [Header("移动设置")]
    public float moveSpeed = 5f; // 移动速度
    private RectTransform rectTransform;
    private Vector2 originalSize; // 原始尺寸
    private Vector2 minPosition; // 最小位置限制
    private Vector2 maxPosition; // 最大位置限制

    [Header("缩放设置")]
    public float scaleSpeed = 0.1f; // 缩放速度
    public float minScale = 0.5f; // 最小缩放比例
    public float maxScale = 2f; // 最大缩放比例
    private Vector3 currentScale; // 当前缩放值

    private void Start()
    {
        rectTransform = GetComponent<RectTransform>();
        originalSize = rectTransform.sizeDelta;
        currentScale = rectTransform.localScale;

        // 计算初始位置限制
        CalculatePositionLimits();
    }

    private void Update()
    {
        HandleMovement();
        HandleScaling();
    }

    private void HandleMovement()
    {
        Vector2 moveInput = Vector2.zero;

        // 获取WASD输入
        if (Input.GetKey(KeyCode.W)) moveInput.y = 1f;
        if (Input.GetKey(KeyCode.S)) moveInput.y = -1f;
        if (Input.GetKey(KeyCode.A)) moveInput.x = -1f;
        if (Input.GetKey(KeyCode.D)) moveInput.x = 1f;

        // 归一化并应用速度
        if (moveInput.magnitude > 0)
        {
            moveInput.Normalize();
            Vector2 newPosition = rectTransform.anchoredPosition + moveInput * moveSpeed * Time.deltaTime;

            // 应用位置限制
            newPosition.x = Mathf.Clamp(newPosition.x, minPosition.x, maxPosition.x);
            newPosition.y = Mathf.Clamp(newPosition.y, minPosition.y, maxPosition.y);

            rectTransform.anchoredPosition = newPosition;
        }
    }

    private void HandleScaling()
    {
        float scaleInput = 0f;

        // 获取JK输入
        if (Input.GetKey(KeyCode.J)) scaleInput = -1f;
        if (Input.GetKey(KeyCode.K)) scaleInput = 1f;

        if (scaleInput != 0f)
        {
            // 计算新缩放值
            float newScale = currentScale.x + scaleInput * scaleSpeed * Time.deltaTime;
            newScale = Mathf.Clamp(newScale, minScale, maxScale);

            currentScale = new Vector3(newScale, newScale, 1f);
            rectTransform.localScale = currentScale;

            // 缩放后重新计算位置限制
            CalculatePositionLimits();

            // 确保缩放后图片不会超出边界
            Vector2 clampedPosition = rectTransform.anchoredPosition;
            clampedPosition.x = Mathf.Clamp(clampedPosition.x, minPosition.x, maxPosition.x);
            clampedPosition.y = Mathf.Clamp(clampedPosition.y, minPosition.y, maxPosition.y);
            rectTransform.anchoredPosition = clampedPosition;
        }
    }

    private void CalculatePositionLimits()
    {
        // 获取Canvas的尺寸
        RectTransform canvasRect = GetComponentInParent<Canvas>().GetComponent<RectTransform>();
        Vector2 canvasSize = canvasRect.sizeDelta;

        // 计算当前图片的实际尺寸(考虑缩放)
        Vector2 scaledSize = new Vector2(
            originalSize.x * currentScale.x,
            originalSize.y * currentScale.y
        );

        // 计算位置限制
        // 当图片尺寸小于等于屏幕尺寸时,不能移动
        if (scaledSize.x <= canvasSize.x)
        {
            minPosition.x = 0;
            maxPosition.x = 0;
        }
        else
        {
            float halfImageWidth = scaledSize.x / 2f;
            float halfCanvasWidth = canvasSize.x / 2f;
            minPosition.x = halfCanvasWidth - halfImageWidth;
            maxPosition.x = halfImageWidth - halfCanvasWidth;
        }

        if (scaledSize.y <= canvasSize.y)
        {
            minPosition.y = 0;
            maxPosition.y = 0;
        }
        else
        {
            float halfImageHeight = scaledSize.y / 2f;
            float halfCanvasHeight = canvasSize.y / 2f;
            minPosition.y = halfCanvasHeight - halfImageHeight;
            maxPosition.y = halfImageHeight - halfCanvasHeight;
        }
    }
}