2

I want to implement an image gallery with Unity (2D). I have a Canvas logically divided into squares of, say, 100x100 units. Then:

  • each "square" is populated by an image downloaded dynamically from the internet (using the www class);
  • the image is not necessarily square: in this case, I want to "scale and crop the image": the aspect ratio is preserved and the image fills the whole square;
  • when a user clicks on a square, the image expands to its natural size on the middle of the screen. Another click an the image goes back to the square size/position;
  • at a regular interval, a square is taken randomly and its image is replaced by a new one.

I am new to Unity and I already tried a lot of different approaches. My real problem is for the scale and crop. Indeed:

  • the Gui.DrawTexture() takes an argument scaleMode.ScaleAndCrop, which is exactly what I need. But this is part of the old UI system...
  • the new UI offers Image and RawImage Gui components, but out of the box we can either keep aspect ratio or fill the square, not both.
  • I tried to create a "texture thumbnail" by copying a square of pixels into a new texture. It works, but animations between thumbnail and fullsize image are not possible anymore...

I am sure there is a way to use the new UI functionalities and get the scale and crop effect, but I can't figure out how. Would someone have an advice for me ?

user3071284
  • 6,955
  • 6
  • 43
  • 57
Derlin
  • 9,572
  • 2
  • 32
  • 53

2 Answers2

1

You will need to use scaling an GameObject with Image component, and using Mask component.

I would do this in this way:

Create canvas with GridLayoutGroup, that will organize the thumbanils Images as you want (3 rows 3 columns etc).

each image has a parent GameObject with mask that will be set with GridLayoutGroup. Child of Mask will be an Image where you will show the downloaded content.

Have a reference to each Image component in controller of your choice.

image1 is a reference to first thumbnail;

When image is downloaded assign made Sprite of it to the image1.sprite.

Call image1.SetNativeSize();

Check the fimage1.GetComponent<RectTransform>().sizeDelta (this is the width and height) and scale the image1 according to the image size, taking in account to fit it into the mask borders. You need basicly some mathematical small algorithm.

The image1 also has Button component with attached OnClick event that will fire the lets say "ShowImagePressed (Image img)". Parameter is the Image of image1.

When this handler is fired, disable the mask by image1.transform.parent.GetComponent<Mask>().enabled = false, and scale the image1, moving it to the center.

Jerry Switalski
  • 2,690
  • 1
  • 18
  • 36
  • In short, what you say is simply scaling the mask instead of the image? But how to get the "thumbnails" side by side, without Borders? In this solution, we will see the mask borders, so it is the same as using an Image set to type filled/keep aspect ratio. Or did I misunderstand? – Derlin Dec 23 '15 at 09:05
  • OK, I had a look at the UI mask element. My bad, it could actually work. I'll try and get back to you. Thanks anyway! – Derlin Dec 23 '15 at 09:13
0

The easiest way to archieve the auto- scale and crop behaviour is to add an an AspectRatioFitter to the GameObject containing the image. Set the AspectMode to Envelope Parent. This way Unity will fill and if needed overlap the parent, see Unity Documentation:

Envelope Parent: The width, height, position, and anchors are automatically adjusted to make the rect cover the entire area of the parent while keeping the aspect ratio. This rect may extend further out than the parent rect.

You can then add a mask to the parent object to hide that unwanted overlay (don't forget to also add an empty image otherwise the mask won't work). The only thing you might have to handle in script is to find the correct aspect ratio of the images.