Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Zoom in/out on ScrollRect.Content image

Discussion in 'UGUI & TextMesh Pro' started by rainbowegg, Dec 9, 2014.

  1. rainbowegg

    rainbowegg

    Joined:
    May 6, 2014
    Posts:
    12
    Hi! I'm trying to make a map that the player can zoom in and out. I'm using a ScrollRect for masking/scrolling the map because it's larger than the screen at normal zoom. I wrote a script to change the scale of the image via buttons, which is working fine. However, the image doesn't snap to the borders of the ScrollRect as it should after scaling. Once I click to drag the image, however, it moves to where it should.

    Here's what it looks like before zooming out:


    Then, upon zooming out, we can see the background of the ScrollRect (not desired):


    And finally, after clicking to drag even a tiny bit (this is how I'd like it to look after zooming):


    Is there a way to get the ScrollRect to reposition in code? Or should be zooming a different way?

    Thanks!
     
  2. ntwinter

    ntwinter

    Joined:
    Oct 24, 2013
    Posts:
    14
    I don't have the answer to this but I would like to know how you did the zoom on the image. I have a scrollrect with a large image that is masked but i haven't yet found how to scale or zoom out to fit the masked size. Ideally I'd like to have it done by use of the mouse scroll wheel.
    Thanks
     
  3. rainbowegg

    rainbowegg

    Joined:
    May 6, 2014
    Posts:
    12
    Can you explain what you mean by the "masked size"? Are you talking about the viewable area in the ScrollRect? A picture would be very helpful!

    What I'm basically doing is changing the rectTransform.scale property in code for the ScrollRect's content. Each click of my Zoom In/Out buttons increases/decreases the scale.

    For a scroll wheel, you'd do something like this:
    Code (CSharp):
    1. void Update() {
    2.         Zoom(Input.GetAxis("Mouse ScrollWheel"));
    3.     }
    4.  
    5. void Zoom(float increment) {
    6.         currentScale += increment;
    7.         if (currentScale >= maxScale) {
    8.             currentScale = maxScale;
    9.         } else if (currentScale <= minScale) {
    10.             currentScale = minScale;
    11.         }
    12.         imageToZoom.rectTransform.localScale = new Vector2(currentScale, currentScale);
    13.     }
    "Input.GetAxis("Mouse ScrollWheel"))" returns a float that represents the direction and amount of scrolling.

    Hope this helps!
     
    Zenov likes this.
  4. ntwinter

    ntwinter

    Joined:
    Oct 24, 2013
    Posts:
    14
    Fantastic. That was exactly what I needed :)
    Thanks.
     
  5. Tomer-Barkan

    Tomer-Barkan

    Joined:
    Jul 31, 2012
    Posts:
    150
    I'm trying to do this myself now as well.
    Did you find out how to do this properly?
     
  6. directusgames

    directusgames

    Joined:
    May 8, 2015
    Posts:
    14
    I've spent about a week on this too... has anyone had any luck?
     
  7. Tomer-Barkan

    Tomer-Barkan

    Joined:
    Jul 31, 2012
    Posts:
    150
    Yes, I did.

    Here's a very basic script that you need to put on the contents of the scrollview to have it zoom with mouse wheel.
    You probably want to improve it to ease the zoom so it's smoother.

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.UI;
    3. using UnityEngine.Events;
    4. using UnityEngine.EventSystems;
    5.  
    6. public class ResizeOnMouseWheel : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler {
    7.     #region Inspector fields
    8.     [SerializeField] float startSize = 1;
    9.     [SerializeField] float minSize = 0.5f;
    10.     [SerializeField] float maxSize = 1;
    11.  
    12.     [SerializeField] private float zoomRate = 5;
    13.     #endregion
    14.  
    15.     #region Private Variables
    16.     private bool onObj = false;
    17.     #endregion
    18.  
    19.     #region Unity Methods
    20.     private void Update() {
    21.         float scrollWheel = -Input.GetAxis(StringConstants.ZoomInput);
    22.  
    23.         if (onObj && scrollWheel != 0) {
    24.             ChangeZoom(scrollWheel);
    25.         }
    26.     }
    27.  
    28.     public void OnPointerEnter(PointerEventData eventData) {
    29.         onObj = true;
    30.     }
    31.  
    32.     public void OnPointerExit(PointerEventData eventData) {
    33.         onObj = false;
    34.     }
    35.  
    36.     public void OnDisable() {
    37.         onObj = false;
    38.     }
    39.     #endregion
    40.  
    41.     #region Private Methods
    42.     private void ChangeZoom(float scrollWheel) {
    43.         float rate = 1 + zoomRate * Time.unscaledDeltaTime;
    44.         if (scrollWheel > 0) {
    45.             SetZoom(Mathf.Clamp(transform.localScale.y / rate, minSize, maxSize));
    46.         } else {
    47.             SetZoom(Mathf.Clamp(transform.localScale.y * rate, minSize, maxSize));
    48.         }
    49.     }
    50.  
    51.     private void SetZoom(float targetSize) {
    52.         transform.localScale = new Vector3(targetSize, targetSize, 1);
    53.     }
    54.     #endregion
    55. }
    56.  
     
    omelchor likes this.
  8. Sindrom

    Sindrom

    Joined:
    Jun 1, 2014
    Posts:
    4
    Hi, I want to center the zoom to the position of the mouse. My content doesn't necessarily have to be inside a scrollview, maybe just an UI object with an image component attached. The problem is that I'm not able to correctly reposition the pivot point of my rectTransform to match the mouse position.
     
  9. Tomer-Barkan

    Tomer-Barkan

    Joined:
    Jul 31, 2012
    Posts:
    150
    Didn't try this myself, but try setting all 4 anchors to the mouse position relative to the scroll view. You can use RectTransformUtility.ScreenPointToLocalPointInRectangle to get the relative position from screen position.
     
  10. Saddamjit_Singh

    Saddamjit_Singh

    Joined:
    Dec 4, 2015
    Posts:
    22
    Hi,

    Can we do the same thing with Pinch to Zoom via Touch input ?

    Thanks
     
  11. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Since this post is old, I would suggest that you try setting up your zoom and using the Pinch to Zoom.
    I have never used that, but it sounds perfectly sensible that such a thing could work with a scroll rect and zooming a map.
    If you try it and get stuck, post a thread showing your work and ask for some help/feedback :)
    Good luck!
     
  12. firoz-khira

    firoz-khira

    Joined:
    May 11, 2015
    Posts:
    1
    HI,

    Can we do with pinch zoom?
     
  13. freedom667

    freedom667

    Joined:
    Sep 6, 2015
    Posts:
    424
    I want to zooming image to mouse location. how can i do this? also I'm sorry wake up the thread
     
    Last edited: Jun 20, 2018
  14. SomeVVhIteGuy

    SomeVVhIteGuy

    Joined:
    Mar 31, 2018
    Posts:
    162
    Old Post is Old, but i more or less got this code to "zoom" the Content in and out with the scroll wheel, towards mouse location.

    It functions more smoothly zooming out than in, but perhaps someone else could tweek it further to improve it


    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class ResizeOnMouseWheel : MonoBehaviour
    4. {
    5.     [SerializeField] float startSize = 1;
    6.     [SerializeField] float minSize = 0.75f;
    7.     [SerializeField] float maxSize = 1;
    8.  
    9.     [SerializeField] private float zoomRate = 5;
    10.  
    11.     Vector3 difference;
    12.     Vector3 mousePos;
    13.  
    14.     private void Update()
    15.     {
    16.         float scrollWheel = -Input.GetAxis("Mouse ScrollWheel");
    17.  
    18.         if (scrollWheel != 0)
    19.         {
    20.             ChangeZoom(scrollWheel);
    21.         }
    22.     }
    23.  
    24.     private void ChangeZoom(float scrollWheel)
    25.     {
    26.  
    27.         float rate = 1 + zoomRate * Time.unscaledDeltaTime;
    28.         if (scrollWheel > 0 && transform.localScale.y > minSize)
    29.         {
    30.             mousePos = Input.mousePosition;
    31.             SetZoom(Mathf.Clamp(transform.localScale.y / rate, minSize, maxSize));
    32.             difference = transform.position - mousePos;
    33.             transform.position = mousePos + (difference * 0.9F);
    34.         }
    35.         else if (scrollWheel < 0 && transform.localScale.y < maxSize)
    36.         {
    37.             mousePos = Input.mousePosition;
    38.             SetZoom(Mathf.Clamp(transform.localScale.y * rate, minSize, maxSize));
    39.             difference = transform.position - mousePos;
    40.             transform.position = mousePos + (difference * 1.11F);
    41.         }
    42.     }
    43.  
    44.     private void SetZoom(float targetSize)
    45.     {
    46.         transform.localScale = new Vector3(targetSize, targetSize, 1);
    47.     }
    48. }
    Script applied to scrollview >CONTENTS
     
  15. AlwaysBaroque

    AlwaysBaroque

    Joined:
    Dec 20, 2014
    Posts:
    33
    @SomeVVhIteGuy Kudos for sharing, but it's to far gone for tweeking :) I went for a complete rewrite.

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.EventSystems;
    3.  
    4. /// <summary>
    5. /// Zooms the attached image in or out.
    6. /// Attach this script to scrollview content panel.
    7. /// All anchors and pivots set to 0.5.
    8. /// Position under mouse remains there.
    9. /// </summary>
    10.  
    11. public class ZoomImage : MonoBehaviour, IScrollHandler
    12. {
    13.  
    14.     //Make sure these values are evenly divisible by scaleIncrement
    15.     [SerializeField] float _minimumScale = 0.5f;
    16.     [SerializeField] float _initialScale = 1f;
    17.     [SerializeField] float _maximumScale = 3f;
    18.     /////////////////////////////////////////////
    19.     [SerializeField] float _scaleIncrement = .5f;
    20.     /////////////////////////////////////////////
    21.  
    22.     [HideInInspector] Vector3 _scale;
    23.  
    24.     RectTransform _thisTransform;
    25.  
    26.     private void Awake()
    27.     {
    28.  
    29.         _thisTransform = transform as RectTransform;
    30.  
    31.         _scale.Set(_initialScale, _initialScale, 1f);
    32.         _thisTransform.localScale = _scale;
    33.  
    34.     }
    35.  
    36.     public void OnScroll(PointerEventData eventData)
    37.     {
    38.         Vector2 relativeMousePosition;
    39.  
    40.         RectTransformUtility.ScreenPointToLocalPointInRectangle(_thisTransform, Input.mousePosition, null, out relativeMousePosition);
    41.  
    42.         float delta = eventData.scrollDelta.y;
    43.  
    44.         if (delta > 0 && _scale.x < _maximumScale)
    45.         {   //zoom in
    46.  
    47.             _scale.Set(_scale.x + _scaleIncrement, _scale.y + _scaleIncrement, 1f);
    48.             _thisTransform.localScale = _scale;
    49.             _thisTransform.anchoredPosition -= (relativeMousePosition * _scaleIncrement);
    50.         }
    51.  
    52.        else if (delta < 0 && _scale.x > _minimumScale)
    53.         {   //zoom out
    54.  
    55.             _scale.Set(_scale.x - _scaleIncrement, _scale.y - _scaleIncrement, 1f);
    56.             _thisTransform.localScale = _scale;
    57.             _thisTransform.anchoredPosition += (relativeMousePosition * _scaleIncrement);
    58.         }
    59.     }
    60. }
    61.  
     
    Last edited: Jul 14, 2020
    Gustav, SmoothD, Tymianek and 4 others like this.