title: How to create a zoomable canvas image in Unity for mobile without scaling the main camera?
body: <p>I have GameObject with Scroll Rect and Rect Mask in my canvas and there is an image in it. I want to zoom in and zoom out of that image. However <strong>I don't want to scale Main Camera</strong> because there will be other objects in the screen that I don't want to zoom. I searched it but all the tutorials are doing that by scaling Main Camera.</p>
  <p>This video is exactly what I want but it doesn't work in android. <a href="https://www.youtube.com/watch?v=BFX3FpUnoio&amp;ab_channel=JasonWeimann" rel="nofollow noreferrer">https://www.youtube.com/watch?v=BFX3FpUnoio&amp;ab_channel=JasonWeimann</a></p>
  <p><a href="https://i.stack.imgur.com/3JkeU.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/3JkeU.png" alt="enter image description here" /></a></p>
  <p>This is the script in that video which is added to &quot;image&quot;. I tried to modify it but I messed it up. How can I make it work in mobile?</p>
  <pre><code>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;
      }
  }
  </code></pre>
  <p>-------UPDATE---------</p>
  <p>I found this in Unity forum: <a href="https://answers.unity.com/questions/1280592/pinch-and-zoom-functionality-on-canvas-ui-images.html" rel="nofollow noreferrer">https://answers.unity.com/questions/1280592/pinch-and-zoom-functionality-on-canvas-ui-images.html</a></p>
  <p>It almost works but I need to pinch the screen 2-3 to zoom in or zoom out. On first touch nothing happens. It's so annoying. I tried to change _minZoom, _maxZoom, speed and sensitivity values but didn't work.</p>
  <p>This is the script there:</p>
  <pre><code>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(&quot;Mouse ScrollWheel&quot;);
           if (Mathf.Abs(scrollWheelInput) &gt; 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) &gt; 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;
       }
   }
  </code></pre>