c# - 如何在不缩放主摄像头的情况下在 Unity for mobile 中创建可缩放的画布图像?
问题描述
我的画布中有带有 Scroll Rect 和 Rect Mask 的 GameObject,其中有一个图像。我想放大和缩小该图像。但是我不想缩放主摄像头,因为屏幕上会有其他我不想缩放的对象。我搜索了它,但所有教程都是通过缩放主摄像头来实现的。
这个视频正是我想要的,但它在 android 中不起作用。https://www.youtube.com/watch?v=BFX3FpUnoio&ab_channel=JasonWeimann
这是该视频中添加到“图像”的脚本。我试图修改它,但我搞砸了。我怎样才能让它在手机上工作?
using UnityEngine;
using UnityEngine.EventSystems;
public class UIZoomImage : MonoBehaviour, IScrollHandler
{
private Vector3 initialScale;
[SerializeField]
private float zoomSpeed = 0.1f;
[SerializeField]
private float maxZoom = 10f;
private void Awake()
{
initialScale = transform.localScale;
}
public void OnScroll(PointerEventData eventData)
{
var delta = Vector3.one * (eventData.scrollDelta.y * zoomSpeed);
var desiredScale = transform.localScale + delta;
desiredScale = ClampDesiredScale(desiredScale);
transform.localScale = desiredScale;
}
private Vector3 ClampDesiredScale(Vector3 desiredScale)
{
desiredScale = Vector3.Max(initialScale, desiredScale);
desiredScale = Vector3.Min(initialScale * maxZoom, desiredScale);
return desiredScale;
}
}
- - - -更新 - - - - -
我在 Unity 论坛中找到了这个:https ://answers.unity.com/questions/1280592/pinch-and-zoom-functionality-on-canvas-ui-images.html
它几乎可以工作,但我需要捏住屏幕 2-3 来放大或缩小。第一次触摸没有任何反应。这太烦人了。我尝试更改 _minZoom、_maxZoom、速度和灵敏度值,但没有奏效。
这是那里的脚本:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class PinchableScrollRect : ScrollRect
{
[SerializeField] float _minZoom = .1f;
[SerializeField] float _maxZoom = 10;
[SerializeField] float _zoomLerpSpeed = 10f;
float _currentZoom = 1;
bool _isPinching = false;
float _startPinchDist;
float _startPinchZoom;
Vector2 _startPinchCenterPosition;
Vector2 _startPinchScreenPosition;
float _mouseWheelSensitivity = 1;
bool blockPan = false;
protected override void Awake()
{
Input.multiTouchEnabled = true;
}
private void Update()
{
if (Input.touchCount == 2)
{
if (!_isPinching)
{
_isPinching = true;
OnPinchStart();
}
OnPinch();
}
else
{
_isPinching = false;
if (Input.touchCount == 0)
{
blockPan = false;
}
}
//pc input
float scrollWheelInput = Input.GetAxis("Mouse ScrollWheel");
if (Mathf.Abs(scrollWheelInput) > float.Epsilon)
{
_currentZoom *= 1 + scrollWheelInput * _mouseWheelSensitivity;
_currentZoom = Mathf.Clamp(_currentZoom, _minZoom, _maxZoom);
_startPinchScreenPosition = (Vector2)Input.mousePosition;
RectTransformUtility.ScreenPointToLocalPointInRectangle(content, _startPinchScreenPosition, null, out _startPinchCenterPosition);
Vector2 pivotPosition = new Vector3(content.pivot.x * content.rect.size.x, content.pivot.y * content.rect.size.y);
Vector2 posFromBottomLeft = pivotPosition + _startPinchCenterPosition;
SetPivot(content, new Vector2(posFromBottomLeft.x / content.rect.width, posFromBottomLeft.y / content.rect.height));
}
//pc input end
if (Mathf.Abs(content.localScale.x - _currentZoom) > 0.001f)
content.localScale = Vector3.Lerp(content.localScale, Vector3.one * _currentZoom, _zoomLerpSpeed * Time.deltaTime);
}
protected override void SetContentAnchoredPosition(Vector2 position)
{
if (_isPinching || blockPan) return;
base.SetContentAnchoredPosition(position);
}
void OnPinchStart()
{
Vector2 pos1 = Input.touches[0].position;
Vector2 pos2 = Input.touches[1].position;
_startPinchDist = Distance(pos1, pos2) * content.localScale.x;
_startPinchZoom = _currentZoom;
_startPinchScreenPosition = (pos1 + pos2) / 2;
RectTransformUtility.ScreenPointToLocalPointInRectangle(content, _startPinchScreenPosition, null, out _startPinchCenterPosition);
Vector2 pivotPosition = new Vector3(content.pivot.x * content.rect.size.x, content.pivot.y * content.rect.size.y);
Vector2 posFromBottomLeft = pivotPosition + _startPinchCenterPosition;
SetPivot(content, new Vector2(posFromBottomLeft.x / content.rect.width, posFromBottomLeft.y / content.rect.height));
blockPan = true;
}
void OnPinch()
{
float currentPinchDist = Distance(Input.touches[0].position, Input.touches[1].position) * content.localScale.x;
_currentZoom = (currentPinchDist / _startPinchDist) * _startPinchZoom;
_currentZoom = Mathf.Clamp(_currentZoom, _minZoom, _maxZoom);
}
float Distance(Vector2 pos1, Vector2 pos2)
{
RectTransformUtility.ScreenPointToLocalPointInRectangle(content, pos1, null, out pos1);
RectTransformUtility.ScreenPointToLocalPointInRectangle(content, pos2, null, out pos2);
return Vector2.Distance(pos1, pos2);
}
static void SetPivot(RectTransform rectTransform, Vector2 pivot)
{
if (rectTransform == null) return;
Vector2 size = rectTransform.rect.size;
Vector2 deltaPivot = rectTransform.pivot - pivot;
Vector3 deltaPosition = new Vector3(deltaPivot.x * size.x, deltaPivot.y * size.y) * rectTransform.localScale.x;
rectTransform.pivot = pivot;
rectTransform.localPosition -= deltaPosition;
}
}
解决方案
如果相机投影设置为正交,则此脚本可以解决问题。从这个 来源。
using UnityEngine;
public class Zoom : MonoBehaviour {
public float zoomSpeed = 1;
public float targetOrtho;
public float smoothSpeed = 2.0f;
public float minOrtho = 1.0f;
public float maxOrtho = 20.0f;
void Start() {
targetOrtho = Camera.main.orthographicSize;
}
void Update () {
float scroll = Input.GetAxis ("Mouse ScrollWheel");
if (scroll != 0.0f) {
targetOrtho -= scroll * zoomSpeed;
targetOrtho = Mathf.Clamp (targetOrtho, minOrtho, maxOrtho);
}
Camera.main.orthographicSize = Mathf.MoveTowards (Camera.main.orthographicSize, targetOrtho, smoothSpeed * Time.deltaTime);
}
}
推荐阅读
- python - 如果字典中的列表中存在值,则返回键
- python - Django 在 UpdateView 类中设置 ModelForm ModelChoiceField 初始值
- android - 如何从回收站视图中获取项目?
- node.js - Stripe Connect - 如何以最安全的方式使用令牌来传递敏感数据?
- python - 有没有一种“热交换”列表的pythonic方法?
- css - CSS自定义样式复选框:使复选标记出现并(删除焦点样式)
- node.js - NodeJS 和 Express - 安全地区分发出请求的客户端
- python - 我需要使用 matplotlib 打印图表
- javascript - 如何仅将 CSS 文件应用于特定的 div
- asp.net-core - DefaultAzureCredential() 需要哪些配置属性来将部署的应用程序验证到密钥库?