Skip to content

Instantly share code, notes, and snippets.

@ryanlintott
Last active December 11, 2020 20:39
Show Gist options
  • Save ryanlintott/173f711528ae450d78fc803d77303001 to your computer and use it in GitHub Desktop.
Save ryanlintott/173f711528ae450d78fc803d77303001 to your computer and use it in GitHub Desktop.
An image that will overlap content based on a percent of height or width. This allows an overlap to occur in the same location regardless of scale.
import SwiftUI
struct OverlappingImage: View {
let uiImage: UIImage
let xShift: CGFloat
let yShift: CGFloat
let newAspect: CGFloat
init(_ uiImage: UIImage, top: CGFloat = 0, bottom: CGFloat = 0) {
self.uiImage = uiImage
let newHeightPercent = 1 - top - bottom
self.xShift = 0
self.yShift = (bottom - top) / (2 * newHeightPercent)
self.newAspect = uiImage.size.aspectRatio / newHeightPercent
}
init(_ uiImage: UIImage, left: CGFloat = 0, right: CGFloat = 0) {
self.uiImage = uiImage
let newWidthPercent = 1 - left - right
self.xShift = (right - left) / (2 * newWidthPercent)
self.yShift = 0
self.newAspect = uiImage.size.aspectRatio * newWidthPercent
}
var body: some View {
GeometryReader { proxy in
Image(uiImage: uiImage)
.resizable()
.scaledToFill()
.offset(x: proxy.size.height * xShift, y: proxy.size.height * yShift)
.frame(width: proxy.size.width, height: proxy.size.height)
}
.aspectRatio(newAspect, contentMode: .fit)
}
}
extension OverlappingImage {
init(_ uiImage: UIImage, vertical: CGFloat = 0) {
self.init(uiImage, top: vertical, bottom: vertical)
}
init(_ uiImage: UIImage, horizontal: CGFloat = 0) {
self.init(uiImage, left: horizontal, right: horizontal)
}
}
struct OverlappingImage_Previews: PreviewProvider {
static let previewImage = UIImage(systemName: "sun.max")!
static var previews: some View {
Group {
VStack(spacing: 0) {
Text("Overlapping Image")
.font(.system(size: 50))
Rectangle()
.frame(height: 5)
OverlappingImage(previewImage, top: 0.05, bottom: 0.11)
.padding(.horizontal, 50)
.zIndex(1)
VStack {
Text("The image above will overlap content above and below with an inset based on a percent of the image height. This allows the overlap to occur in the same location regardless of scale.")
.padding(20)
}
.background(Color.gray)
.border(Color.red, width: 3)
}
.frame(width: 400, height: 400)
.previewLayout(.sizeThatFits)
HStack(spacing: 0) {
Text("Overlapping Image")
.font(.system(size: 20))
Rectangle()
.frame(width: 5)
OverlappingImage(previewImage, left: 0.05, right: 0.11)
.padding(.vertical, 50)
.zIndex(1)
VStack {
Text("The image to the left will overlap content to the left and right with an inset based on a percent of the image width.")
.padding(20)
}
.background(Color.gray)
.border(Color.red, width: 3)
}
.frame(width: 400, height: 200)
.previewLayout(.sizeThatFits)
}
}
}
@ryanlintott
Copy link
Author

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment