In my app, I need to display images (textures). Some are tiled, and some are stretched.
At the time, I have this code working:
Image(frame.image)
.resizable(resizingMode: (frame.repeatTexture == true) ? .tile : .stretch)
.frame(width: frame.width, height: frame.height)
However,the render of the .tile is not good. The texture is cropped in X axis. In the image sent, you can see that the bezel is not present at the right, it's truncated.
Original texture where there is a bezel at left and right:
I would like to have the "repeat" only in Y for example. Seems there is no option for that by default.
Is there a tip, an option, or maybe another idea like using background() to force the texture to tile only in one axis?
You can draw a stretched version of the image using a GraphicsContext
, and then tile that using resizable
,
let imageHeight = ... // replace this with the height of your image
let frame = CGSize(width: 300, height: 700) // as an example
Image(size: .init(width: frame.width, height: imageHeight)) { gc in
let image = gc.resolve(Image(.tile))
let scale = frame.width / image.size.width
gc.scaleBy(x: scale, y: 1)
gc.draw(image, at: .zero, anchor: .topLeading)
gc.scaleBy(x: 1 / scale, y: 1)
}
.resizable(resizingMode: .tile)
.frame(width: frame.width, height: frame.height)
Or, just draw the entire tiled image with the GraphicsContext
.
Image(size: frame) { gc in
var startY: CGFloat = 0
let image = gc.resolve(Image(.tile))
while startY < frame.height {
let scale = frame.width / image.size.width
gc.scaleBy(x: scale, y: 1)
gc.draw(image, at: .init(x: 0, y: startY), anchor: .topLeading)
gc.scaleBy(x: 1 / scale, y: 1)
startY += image.size.height
}
}