Last active
December 11, 2020 20:39
-
-
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | |
} | |
} | |
} |
Author
ryanlintott
commented
Dec 11, 2020
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment