当前位置: 首页 > news >正文

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

需求
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;
        }
    }
}

相关文章:

  • Axure项目实战:智慧运输平台后台管理端-母版、登录(文本框高级交互)
  • 【C++】AVL树
  • 音视频 一 看书的笔记 基础视频知识
  • 电话号码的字母组合组合总和II 回溯注意事项(Java)
  • AI玩具迎来爆发式增长,IoT行业如何抓住机遇?
  • Linux 目录结构(文件系统结构)示例说明
  • Python第六章15:字典(dict)定义
  • XCode中使用MonkeyDev开发iOS版的Comand-line Tool的daemon程序
  • IntelliJ IDEA(2024版) 的安装、配置与使用教程:常用配置、创建工程等操作(很详细,你想要的都在这里)
  • Redis 和 MySQL双写一致性的更新策略有哪些?常见面试题深度解答。
  • vue3 vite mock实践
  • 使用 Docker 18 安装 Eureka:解决新版本 Docker 不支持的问题
  • Spring Boot 实现定时任务的案例
  • 使用django的DRF业务逻辑应该放在序列化器类还是模型类
  • pyqt第一个窗口程序
  • 黑马点评项目
  • Maven声明周期
  • 第4.1节:使用正则表达式
  • Jira讲解
  • wgcloud怎么实现服务器或者主机的远程关机、重启操作吗
  • 网站空间上传软件/夸克搜索入口
  • 张家港网站推广/新seo排名点击软件
  • 网站上的高清图怎么做/游戏推广员平台
  • 便利的广州微网站建设/福州seo博客
  • wordpress search.php/关键词优化排名首页
  • 太原哪家网站建设公司好/网络营销的模式有哪些?