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!
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
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:
void Update() {
Zoom(Input.GetAxis("Mouse ScrollWheel"));
}
void Zoom(float increment) {
currentScale += increment;
if (currentScale >= maxScale) {
currentScale = maxScale;
} else if (currentScale <= minScale) {
currentScale = minScale;
}
imageToZoom.rectTransform.localScale = new Vector2(currentScale, currentScale);
}
“Input.GetAxis(“Mouse ScrollWheel”))” returns a float that represents the direction and amount of scrolling.
Hope this helps!
2 Likes
Fantastic. That was exactly what I needed
Thanks.
I’m trying to do this myself now as well.
Did you find out how to do this properly?
I’ve spent about a week on this too… has anyone had any luck?
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.
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Events;
using UnityEngine.EventSystems;
public class ResizeOnMouseWheel : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler {
#region Inspector fields
[SerializeField] float startSize = 1;
[SerializeField] float minSize = 0.5f;
[SerializeField] float maxSize = 1;
[SerializeField] private float zoomRate = 5;
#endregion
#region Private Variables
private bool onObj = false;
#endregion
#region Unity Methods
private void Update() {
float scrollWheel = -Input.GetAxis(StringConstants.ZoomInput);
if (onObj && scrollWheel != 0) {
ChangeZoom(scrollWheel);
}
}
public void OnPointerEnter(PointerEventData eventData) {
onObj = true;
}
public void OnPointerExit(PointerEventData eventData) {
onObj = false;
}
public void OnDisable() {
onObj = false;
}
#endregion
#region Private Methods
private void ChangeZoom(float scrollWheel) {
float rate = 1 + zoomRate * Time.unscaledDeltaTime;
if (scrollWheel > 0) {
SetZoom(Mathf.Clamp(transform.localScale.y / rate, minSize, maxSize));
} else {
SetZoom(Mathf.Clamp(transform.localScale.y * rate, minSize, maxSize));
}
}
private void SetZoom(float targetSize) {
transform.localScale = new Vector3(targetSize, targetSize, 1);
}
#endregion
}
1 Like
Sindrom
February 22, 2016, 11:02pm
8
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.
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.
Hi,
Can we do the same thing with Pinch to Zoom via Touch input ?
Thanks
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!
HI,
Can we do with pinch zoom?
Tomer-Barkan_1:
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.
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Events;
using UnityEngine.EventSystems;
public class ResizeOnMouseWheel : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler {
#region Inspector fields
[SerializeField] float startSize = 1;
[SerializeField] float minSize = 0.5f;
[SerializeField] float maxSize = 1;
[SerializeField] private float zoomRate = 5;
#endregion
#region Private Variables
private bool onObj = false;
#endregion
#region Unity Methods
private void Update() {
float scrollWheel = -Input.GetAxis(StringConstants.ZoomInput);
if (onObj && scrollWheel != 0) {
ChangeZoom(scrollWheel);
}
}
public void OnPointerEnter(PointerEventData eventData) {
onObj = true;
}
public void OnPointerExit(PointerEventData eventData) {
onObj = false;
}
public void OnDisable() {
onObj = false;
}
#endregion
#region Private Methods
private void ChangeZoom(float scrollWheel) {
float rate = 1 + zoomRate * Time.unscaledDeltaTime;
if (scrollWheel > 0) {
SetZoom(Mathf.Clamp(transform.localScale.y / rate, minSize, maxSize));
} else {
SetZoom(Mathf.Clamp(transform.localScale.y * rate, minSize, maxSize));
}
}
private void SetZoom(float targetSize) {
transform.localScale = new Vector3(targetSize, targetSize, 1);
}
#endregion
}
I want to zooming image to mouse location. how can i do this? also I’m sorry wake up the thread
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
using UnityEngine;
public class ResizeOnMouseWheel : MonoBehaviour
{
[SerializeField] float startSize = 1;
[SerializeField] float minSize = 0.75f;
[SerializeField] float maxSize = 1;
[SerializeField] private float zoomRate = 5;
Vector3 difference;
Vector3 mousePos;
private void Update()
{
float scrollWheel = -Input.GetAxis("Mouse ScrollWheel");
if (scrollWheel != 0)
{
ChangeZoom(scrollWheel);
}
}
private void ChangeZoom(float scrollWheel)
{
float rate = 1 + zoomRate * Time.unscaledDeltaTime;
if (scrollWheel > 0 && transform.localScale.y > minSize)
{
mousePos = Input.mousePosition;
SetZoom(Mathf.Clamp(transform.localScale.y / rate, minSize, maxSize));
difference = transform.position - mousePos;
transform.position = mousePos + (difference * 0.9F);
}
else if (scrollWheel < 0 && transform.localScale.y < maxSize)
{
mousePos = Input.mousePosition;
SetZoom(Mathf.Clamp(transform.localScale.y * rate, minSize, maxSize));
difference = transform.position - mousePos;
transform.position = mousePos + (difference * 1.11F);
}
}
private void SetZoom(float targetSize)
{
transform.localScale = new Vector3(targetSize, targetSize, 1);
}
}
Script applied to scrollview >CONTENTS
Boz_1
July 14, 2020, 10:26am
15
@SomeVVhIteGuy Kudos for sharing, but it’s to far gone for tweeking I went for a complete rewrite.
using UnityEngine;
using UnityEngine.EventSystems;
/// <summary>
/// Zooms the attached image in or out.
/// Attach this script to scrollview content panel.
/// All anchors and pivots set to 0.5.
/// Position under mouse remains there.
/// </summary>
public class ZoomImage : MonoBehaviour, IScrollHandler
{
//Make sure these values are evenly divisible by scaleIncrement
[SerializeField] float _minimumScale = 0.5f;
[SerializeField] float _initialScale = 1f;
[SerializeField] float _maximumScale = 3f;
/////////////////////////////////////////////
[SerializeField] float _scaleIncrement = .5f;
/////////////////////////////////////////////
[HideInInspector] Vector3 _scale;
RectTransform _thisTransform;
private void Awake()
{
_thisTransform = transform as RectTransform;
_scale.Set(_initialScale, _initialScale, 1f);
_thisTransform.localScale = _scale;
}
public void OnScroll(PointerEventData eventData)
{
Vector2 relativeMousePosition;
RectTransformUtility.ScreenPointToLocalPointInRectangle(_thisTransform, Input.mousePosition, null, out relativeMousePosition);
float delta = eventData.scrollDelta.y;
if (delta > 0 && _scale.x < _maximumScale)
{ //zoom in
_scale.Set(_scale.x + _scaleIncrement, _scale.y + _scaleIncrement, 1f);
_thisTransform.localScale = _scale;
_thisTransform.anchoredPosition -= (relativeMousePosition * _scaleIncrement);
}
else if (delta < 0 && _scale.x > _minimumScale)
{ //zoom out
_scale.Set(_scale.x - _scaleIncrement, _scale.y - _scaleIncrement, 1f);
_thisTransform.localScale = _scale;
_thisTransform.anchoredPosition += (relativeMousePosition * _scaleIncrement);
}
}
}
9 Likes
Boz_1:
@SomeVVhIteGuy Kudos for sharing, but it’s to far gone for tweeking I went for a complete rewrite.
using UnityEngine;
using UnityEngine.EventSystems;
/// <summary>
/// Zooms the attached image in or out.
/// Attach this script to scrollview content panel.
/// All anchors and pivots set to 0.5.
/// Position under mouse remains there.
/// </summary>
public class ZoomImage : MonoBehaviour, IScrollHandler
{
//Make sure these values are evenly divisible by scaleIncrement
[SerializeField] float _minimumScale = 0.5f;
[SerializeField] float _initialScale = 1f;
[SerializeField] float _maximumScale = 3f;
/////////////////////////////////////////////
[SerializeField] float _scaleIncrement = .5f;
/////////////////////////////////////////////
[HideInInspector] Vector3 _scale;
RectTransform _thisTransform;
private void Awake()
{
_thisTransform = transform as RectTransform;
_scale.Set(_initialScale, _initialScale, 1f);
_thisTransform.localScale = _scale;
}
public void OnScroll(PointerEventData eventData)
{
Vector2 relativeMousePosition;
RectTransformUtility.ScreenPointToLocalPointInRectangle(_thisTransform, Input.mousePosition, null, out relativeMousePosition);
float delta = eventData.scrollDelta.y;
if (delta > 0 && _scale.x < _maximumScale)
{ //zoom in
_scale.Set(_scale.x + _scaleIncrement, _scale.y + _scaleIncrement, 1f);
_thisTransform.localScale = _scale;
_thisTransform.anchoredPosition -= (relativeMousePosition * _scaleIncrement);
}
else if (delta < 0 && _scale.x > _minimumScale)
{ //zoom out
_scale.Set(_scale.x - _scaleIncrement, _scale.y - _scaleIncrement, 1f);
_thisTransform.localScale = _scale;
_thisTransform.anchoredPosition += (relativeMousePosition * _scaleIncrement);
}
}
}
Code is nearly perfect. Just adding clamping values to the scale l.56 & 57 (first time i had negative scale, it was weird ahah)
using UnityEngine;
using UnityEngine;
using UnityEngine.EventSystems;
/// <summary>
/// Zooms the attached image in or out.
/// Attach this script to scrollview content panel.
/// All anchors and pivots set to 0.5.
/// Position under mouse remains there.
/// </summary>
public class ZoomImage : MonoBehaviour, IScrollHandler
{
//Make sure these values are evenly divisible by scaleIncrement
[SerializeField] float _minimumScale = 0.5f;
[SerializeField] float _initialScale = 1f;
[SerializeField] float _maximumScale = 3f;
/////////////////////////////////////////////
[SerializeField] float _scaleIncrement = .5f;
/////////////////////////////////////////////
[HideInInspector] Vector3 _scale;
RectTransform _thisTransform;
private void Awake()
{
_thisTransform = transform as RectTransform;
_scale.Set(_initialScale, _initialScale, 1f);
_thisTransform.localScale = _scale;
}
public void OnScroll(PointerEventData eventData)
{
Vector2 relativeMousePosition;
RectTransformUtility.ScreenPointToLocalPointInRectangle(_thisTransform, Input.mousePosition, null, out relativeMousePosition);
float delta = eventData.scrollDelta.y;
if (delta > 0 && _scale.x < _maximumScale)
{ //zoom in
_scale.Set(_scale.x + _scaleIncrement, _scale.y + _scaleIncrement, 1f);
_thisTransform.localScale = _scale;
_thisTransform.anchoredPosition -= (relativeMousePosition * _scaleIncrement);
}
else if (delta < 0 && _scale.x > _minimumScale)
{ //zoom out
float scalex = Mathf.Clamp(_scale.x - _scaleIncrement, _minimumScale, _maximumScale);
float scaley = Mathf.Clamp(_scale.y - _scaleIncrement, _minimumScale, _maximumScale);
_scale.Set(scalex, scaley, 1f);
_thisTransform.localScale = _scale;
_thisTransform.anchoredPosition += (relativeMousePosition * _scaleIncrement);
}
}
}
1 Like