Search Unity

  1. Unity 2020.2 has been released.
    Dismiss Notice
  2. Good news ✨ We have more Unite Now videos available for you to watch on-demand! Come check them out and ask our experts any questions!
    Dismiss Notice

Code Snippet: Size RawImage to Parent, keep aspect ratio.

Discussion in 'UGUI & TextMesh Pro' started by shawnblais, Jan 24, 2016.

  1. shawnblais

    shawnblais

    Joined:
    Oct 11, 2012
    Posts:
    311
    Here's a handy little script I came up with, so you can tell any RawImage to fill it's parent's Rect, while maintaining the aspect ratio of the src texture. It also supports %-based padding, and images that have been rotated by 90 degree increments.
    Code (csharp):
    1.  
    2. static class CanvasExtensions {
    3.     public static Vector2 SizeToParent(this RawImage image, float padding = 0) {
    4.         var parent = image.transform.parent.GetComponent<RectTransform>();
    5.         var imageTransform = image.GetComponent<RectTransform>();
    6.         if (!parent) { return imageTransform.sizeDelta; } //if we don't have a parent, just return our current width;
    7.         padding = 1 - padding;
    8.         float w = 0, h = 0;
    9.         float ratio = image.texture.width / (float)image.texture.height;
    10.         var bounds = new Rect(0, 0, parent.rect.width, parent.rect.height);
    11.         if (Mathf.RoundToInt(imageTransform.eulerAngles.z) % 180 == 90) {
    12.               //Invert the bounds if the image is rotated
    13.               bounds.size = new Vector2(bounds.height, bounds.width);
    14.         }
    15.         //Size by height first
    16.         h = bounds.height * padding;
    17.         w = h * ratio;
    18.         if (w > bounds.width * padding) { //If it doesn't fit, fallback to width;
    19.             w = bounds.width * padding;
    20.             h = w / ratio;
    21.         }
    22.         imageTransform.sizeDelta = new Vector2(w, h);
    23.         return imageTransform.sizeDelta;
    24.     }
    25. }
    26.  
    Usage:
    Code (csharp):
    1. rawImage.SizeToParent();
    This is mostly useful for when you're loading a bunch of external images into a container, w/ random aspect ratios, and want them to fill the available space, without losing aspect ratio. The Image control is has a similar API, but requires you create a new Sprite() everytime you swap textures, which is a major performance drain.
     
    Last edited: Jun 20, 2019
  2. Freezy

    Freezy

    Joined:
    Jul 15, 2012
    Posts:
    233
    Thank you for sharing, this saved me some time ;-)
    I did make some adjustments, enjoy !


    Code (CSharp):
    1.    
    2. public static Vector2 SizeToParent(this RawImage image, float padding = 0) {
    3.         float w = 0, h = 0;
    4.         var parent = image.GetComponentInParent<RectTransform>();
    5.         var imageTransform = image.GetComponent<RectTransform>();
    6.  
    7.         // check if there is something to do
    8.         if (image.texture != null) {
    9.             if (!parent) { return imageTransform.sizeDelta; } //if we don't have a parent, just return our current width;
    10.             padding = 1 - padding;
    11.             float ratio = image.texture.width / (float)image.texture.height;
    12.             var bounds = new Rect(0, 0, parent.rect.width, parent.rect.height);
    13.             if (Mathf.RoundToInt(imageTransform.eulerAngles.z) % 180 == 90) {
    14.                 //Invert the bounds if the image is rotated
    15.                 bounds.size = new Vector2(bounds.height, bounds.width);
    16.             }
    17.             //Size by height first
    18.             h = bounds.height * padding;
    19.             w = h * ratio;
    20.             if (w > bounds.width * padding) { //If it doesn't fit, fallback to width;
    21.                 w = bounds.width * padding;
    22.                 h = w / ratio;
    23.             }
    24.         }
    25.         imageTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, w);
    26.         imageTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, h);
    27.         return imageTransform.sizeDelta;
    28.     }
    29.  
     
    MilenaRocha, Oli_C, punkbot and 4 others like this.
  3. elpuerco63

    elpuerco63

    Joined:
    Jun 26, 2014
    Posts:
    271
    Have tried this in various ways but I keep getting null reference on line: 4?
     
  4. Freezy

    Freezy

    Joined:
    Jul 15, 2012
    Posts:
    233
    var parent = image.transform.parent.GetComponentInParent<RectTransform>();

    Is the raw Image parented to an object with a recttransform?
     
    elpuerco63 likes this.
  5. elpuerco63

    elpuerco63

    Joined:
    Jun 26, 2014
    Posts:
    271
    DOH!!!! had script attached to wrong GO....!
     
    Freezy likes this.
  6. NorthStar79

    NorthStar79

    Joined:
    May 8, 2015
    Posts:
    86
    works like a charm, Thanks!
     
  7. lumoconnor

    lumoconnor

    Joined:
    Jan 17, 2016
    Posts:
    27
    Hey, thanks for this code. Its very useful, however, I think I found a bug.

    GetComponentInParent() returns a component on this game object or its parents. So, in my case it was returning the RectTransform of the image itself instead of the parent rect. Super annoying. Here's the documentation:
    https://docs.unity3d.com/ScriptReference/GameObject.GetComponentInParent.html

    A fix - change line 3 to...
    Code (CSharp):
    1. var parent = image.transform.parent.GetComponent<RectTransform>();
     
  8. BreynartStudios

    BreynartStudios

    Joined:
    Feb 3, 2018
    Posts:
    3
    I really appreciate it!!! Works flawlessly :)
     
  9. shawnblais

    shawnblais

    Joined:
    Oct 11, 2012
    Posts:
    311
    Fixed. Better late than never :)
     
  10. schreibtischkrieger2019

    schreibtischkrieger2019

    Joined:
    Jul 12, 2019
    Posts:
    13
    make sure ur RawImage RectTransform is not Stretched in the Editor.
     
unityunity