[WIP] Move layoutcode and move plane (#690)

Turns out: Changing the constant of a layoutconstraint does the job, but is' laggy af, so I have to come up with another solution.
This commit is contained in:
Nathan Mattes 2022-12-04 21:07:11 +01:00
parent 32bc94322d
commit 38cafae28b
2 changed files with 247 additions and 299 deletions

View File

@ -12,202 +12,239 @@ import MastodonUI
import MastodonLocalization import MastodonLocalization
final class WelcomeIllustrationView: UIView { final class WelcomeIllustrationView: UIView {
let cloudBaseImageView = UIImageView()
let rightHillImageView = UIImageView()
let leftHillImageView = UIImageView()
let centerHillImageView = UIImageView()
private let cloudBaseImage = Asset.Scene.Welcome.Illustration.cloudBase.image
private let cloudBaseExtendImage = Asset.Scene.Welcome.Illustration.cloudBaseExtend.image
private let elephantThreeOnGrassWithTreeTwoImage = Asset.Scene.Welcome.Illustration.elephantThreeOnGrassWithTreeTwo.image
private let elephantThreeOnGrassWithTreeThreeImage = Asset.Scene.Welcome.Illustration.elephantThreeOnGrassWithTreeThree.image
private let elephantThreeOnGrassImage = Asset.Scene.Welcome.Illustration.elephantThreeOnGrass.image
private let elephantThreeOnGrassExtendImage = Asset.Scene.Welcome.Illustration.elephantThreeOnGrassExtend.image
// layout outside
let elephantOnAirplaneWithContrailImageView: UIImageView = {
let imageView = UIImageView(image: Asset.Scene.Welcome.Illustration.elephantOnAirplaneWithContrail.image)
imageView.contentMode = .scaleAspectFill
return imageView
}()
var layout: Layout = .compact {
didSet {
setNeedsLayout()
}
}
var aspectLayoutConstraint: NSLayoutConstraint!
override init(frame: CGRect) { let cloudBaseImageView = UIImageView()
super.init(frame: frame) let rightHillImageView = UIImageView()
_init() let leftHillImageView = UIImageView()
let centerHillImageView = UIImageView()
private let cloudBaseImage = Asset.Scene.Welcome.Illustration.cloudBase.image
private let cloudBaseExtendImage = Asset.Scene.Welcome.Illustration.cloudBaseExtend.image
private let elephantThreeOnGrassWithTreeTwoImage = Asset.Scene.Welcome.Illustration.elephantThreeOnGrassWithTreeTwo.image
private let elephantThreeOnGrassWithTreeThreeImage = Asset.Scene.Welcome.Illustration.elephantThreeOnGrassWithTreeThree.image
private let elephantThreeOnGrassImage = Asset.Scene.Welcome.Illustration.elephantThreeOnGrass.image
private let elephantThreeOnGrassExtendImage = Asset.Scene.Welcome.Illustration.elephantThreeOnGrassExtend.image
var bottomAnchorLayoutConstraint: NSLayoutConstraint?
var elephantOnAirplaneLeftConstraint: NSLayoutConstraint?
let elephantOnAirplaneWithContrailImageView: UIImageView = {
let imageView = UIImageView(image: Asset.Scene.Welcome.Illustration.elephantOnAirplaneWithContrail.image)
imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.contentMode = .scaleAspectFill
return imageView
}()
var layout: Layout = .compact {
didSet {
setNeedsLayout()
} }
}
required init?(coder: NSCoder) { var aspectLayoutConstraint: NSLayoutConstraint!
super.init(coder: coder)
_init() override init(frame: CGRect) {
} super.init(frame: frame)
_init()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
_init()
}
} }
extension WelcomeIllustrationView { extension WelcomeIllustrationView {
enum Layout { enum Layout {
case compact case compact
case regular case regular
var artworkImageSize: CGSize { var artworkImageSize: CGSize {
switch self { switch self {
case .compact: return CGSize(width: 375, height: 1500) case .compact: return CGSize(width: 375, height: 1500)
case .regular: return CGSize(width: 547, height: 3000) case .regular: return CGSize(width: 547, height: 3000)
} }
}
} }
} }
}
extension WelcomeIllustrationView {
extension WelcomeIllustrationView {
private func _init() {
backgroundColor = Asset.Scene.Welcome.Illustration.backgroundCyan.color private func _init() {
backgroundColor = Asset.Scene.Welcome.Illustration.backgroundCyan.color
let topPaddingView = UIView()
cloudBaseImageView.translatesAutoresizingMaskIntoConstraints = false
topPaddingView.translatesAutoresizingMaskIntoConstraints = false addSubview(cloudBaseImageView)
addSubview(topPaddingView) NSLayoutConstraint.activate([
NSLayoutConstraint.activate([ cloudBaseImageView.leadingAnchor.constraint(equalTo: leadingAnchor),
topPaddingView.topAnchor.constraint(equalTo: topAnchor), cloudBaseImageView.trailingAnchor.constraint(equalTo: trailingAnchor),
topPaddingView.leadingAnchor.constraint(equalTo: leadingAnchor), cloudBaseImageView.bottomAnchor.constraint(equalTo: bottomAnchor),
topPaddingView.trailingAnchor.constraint(equalTo: trailingAnchor), ])
])
addSubview(elephantOnAirplaneWithContrailImageView)
cloudBaseImageView.translatesAutoresizingMaskIntoConstraints = false
addSubview(cloudBaseImageView) let elephantOnAirplaneLeftConstraint = leftAnchor.constraint(equalTo: elephantOnAirplaneWithContrailImageView.leftAnchor, constant: 178) // add 12pt bleeding
NSLayoutConstraint.activate([ NSLayoutConstraint.activate([
cloudBaseImageView.topAnchor.constraint(equalTo: topPaddingView.bottomAnchor), elephantOnAirplaneLeftConstraint,
cloudBaseImageView.leadingAnchor.constraint(equalTo: leadingAnchor), elephantOnAirplaneWithContrailImageView.bottomAnchor.constraint(equalTo: centerYAnchor),
cloudBaseImageView.trailingAnchor.constraint(equalTo: trailingAnchor), // make a little bit large
cloudBaseImageView.bottomAnchor.constraint(equalTo: bottomAnchor), elephantOnAirplaneWithContrailImageView.widthAnchor.constraint(equalTo: widthAnchor, multiplier: 0.84),
]) ])
[ self.elephantOnAirplaneLeftConstraint = elephantOnAirplaneLeftConstraint
rightHillImageView, [
leftHillImageView, rightHillImageView,
centerHillImageView, leftHillImageView,
].forEach { imageView in centerHillImageView,
imageView.translatesAutoresizingMaskIntoConstraints = false ].forEach { imageView in
addSubview(imageView) imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.pinTo(to: cloudBaseImageView) addSubview(imageView)
} imageView.pinTo(to: cloudBaseImageView)
}
aspectLayoutConstraint = cloudBaseImageView.widthAnchor.constraint(equalTo: cloudBaseImageView.heightAnchor, multiplier: layout.artworkImageSize.width / layout.artworkImageSize.height)
aspectLayoutConstraint.isActive = true aspectLayoutConstraint = cloudBaseImageView.widthAnchor.constraint(equalTo: cloudBaseImageView.heightAnchor, multiplier: layout.artworkImageSize.width / layout.artworkImageSize.height)
} aspectLayoutConstraint.isActive = true
}
override func layoutSubviews() {
super.layoutSubviews() override func layoutSubviews() {
super.layoutSubviews()
switch layout {
case .compact: switch layout {
layoutCompact() case .compact:
case .regular: layoutCompact()
layoutRegular() case .regular:
} layoutRegular()
}
aspectLayoutConstraint.isActive = false
aspectLayoutConstraint = cloudBaseImageView.widthAnchor.constraint(equalTo: cloudBaseImageView.heightAnchor, multiplier: layout.artworkImageSize.width / layout.artworkImageSize.height) aspectLayoutConstraint.isActive = false
aspectLayoutConstraint.isActive = true aspectLayoutConstraint = cloudBaseImageView.widthAnchor.constraint(equalTo: cloudBaseImageView.heightAnchor, multiplier: layout.artworkImageSize.width / layout.artworkImageSize.height)
} aspectLayoutConstraint.isActive = true
}
private func layoutCompact() {
let size = layout.artworkImageSize private func layoutCompact() {
let width = size.width let size = layout.artworkImageSize
let height = size.height let width = size.width
let height = size.height
cloudBaseImageView.image = UIGraphicsImageRenderer(size: size).image { context in
// clear background cloudBaseImageView.image = UIGraphicsImageRenderer(size: size).image { context in
UIColor.clear.setFill() // clear background
context.fill(CGRect(origin: .zero, size: size)) UIColor.clear.setFill()
context.fill(CGRect(origin: .zero, size: size))
// draw cloud
cloudBaseImage.draw(at: CGPoint(x: 0, y: height - cloudBaseImage.size.height)) // draw cloud
} cloudBaseImage.draw(at: CGPoint(x: 0, y: height - cloudBaseImage.size.height))
}
rightHillImageView.image = UIGraphicsImageRenderer(size: size).image { context in
// clear background rightHillImageView.image = UIGraphicsImageRenderer(size: size).image { context in
UIColor.clear.setFill() // clear background
context.fill(CGRect(origin: .zero, size: size)) UIColor.clear.setFill()
context.fill(CGRect(origin: .zero, size: size))
// draw elephantThreeOnGrassWithTreeTwoImage
// elephantThreeOnGrassWithTreeTwo.bottomY - 25 align to elephantThreeOnGrassImage.centerY // draw elephantThreeOnGrassWithTreeTwoImage
elephantThreeOnGrassWithTreeTwoImage.draw(at: CGPoint(x: width - elephantThreeOnGrassWithTreeTwoImage.size.width, y: height - 0.5 * elephantThreeOnGrassImage.size.height - elephantThreeOnGrassWithTreeTwoImage.size.height + 25)) // elephantThreeOnGrassWithTreeTwo.bottomY - 25 align to elephantThreeOnGrassImage.centerY
} elephantThreeOnGrassWithTreeTwoImage.draw(at: CGPoint(x: width - elephantThreeOnGrassWithTreeTwoImage.size.width, y: height - 0.5 * elephantThreeOnGrassImage.size.height - elephantThreeOnGrassWithTreeTwoImage.size.height + 25))
}
leftHillImageView.image = UIGraphicsImageRenderer(size: size).image { context in
// clear background leftHillImageView.image = UIGraphicsImageRenderer(size: size).image { context in
UIColor.clear.setFill() // clear background
context.fill(CGRect(origin: .zero, size: size)) UIColor.clear.setFill()
context.fill(CGRect(origin: .zero, size: size))
// draw elephantThreeOnGrassWithTreeThree
// elephantThreeOnGrassWithTreeThree.bottomY + 30 align to elephantThreeOnGrassImage.centerY // draw elephantThreeOnGrassWithTreeThree
elephantThreeOnGrassWithTreeThreeImage.draw(at: CGPoint(x: 0, y: height - 0.5 * elephantThreeOnGrassImage.size.height - elephantThreeOnGrassWithTreeThreeImage.size.height - 30)) // elephantThreeOnGrassWithTreeThree.bottomY + 30 align to elephantThreeOnGrassImage.centerY
} elephantThreeOnGrassWithTreeThreeImage.draw(at: CGPoint(x: 0, y: height - 0.5 * elephantThreeOnGrassImage.size.height - elephantThreeOnGrassWithTreeThreeImage.size.height - 30))
}
centerHillImageView.image = UIGraphicsImageRenderer(size: size).image { context in
// clear background centerHillImageView.image = UIGraphicsImageRenderer(size: size).image { context in
UIColor.clear.setFill() // clear background
context.fill(CGRect(origin: .zero, size: size)) UIColor.clear.setFill()
context.fill(CGRect(origin: .zero, size: size))
// draw elephantThreeOnGrass
elephantThreeOnGrassImage.draw(at: CGPoint(x: 0, y: height - elephantThreeOnGrassImage.size.height)) // draw elephantThreeOnGrass
} elephantThreeOnGrassImage.draw(at: CGPoint(x: 0, y: height - elephantThreeOnGrassImage.size.height))
} }
}
private func layoutRegular() {
let size = layout.artworkImageSize private func layoutRegular() {
let width = size.width let size = layout.artworkImageSize
let height = size.height let width = size.width
let height = size.height
cloudBaseImageView.image = UIGraphicsImageRenderer(size: size).image { context in
// clear background cloudBaseImageView.image = UIGraphicsImageRenderer(size: size).image { context in
UIColor.clear.setFill() // clear background
context.fill(CGRect(origin: .zero, size: size)) UIColor.clear.setFill()
context.fill(CGRect(origin: .zero, size: size))
// draw cloud
cloudBaseExtendImage.draw(at: CGPoint(x: 0, y: height - cloudBaseExtendImage.size.height)) // draw cloud
cloudBaseExtendImage.draw(at: CGPoint(x: 0, y: height - cloudBaseExtendImage.size.height))
rightHillImageView.image = UIGraphicsImageRenderer(size: size).image { context in
// clear background rightHillImageView.image = UIGraphicsImageRenderer(size: size).image { context in
UIColor.clear.setFill() // clear background
context.fill(CGRect(origin: .zero, size: size)) UIColor.clear.setFill()
context.fill(CGRect(origin: .zero, size: size))
// draw elephantThreeOnGrassWithTreeTwoImage
// elephantThreeOnGrassWithTreeTwo.bottomY - 25 align to elephantThreeOnGrassImage.centerY // draw elephantThreeOnGrassWithTreeTwoImage
elephantThreeOnGrassWithTreeTwoImage.draw(at: CGPoint(x: width - elephantThreeOnGrassWithTreeTwoImage.size.width, y: height - 0.5 * elephantThreeOnGrassImage.size.height - elephantThreeOnGrassWithTreeTwoImage.size.height - 20)) // elephantThreeOnGrassWithTreeTwo.bottomY - 25 align to elephantThreeOnGrassImage.centerY
} elephantThreeOnGrassWithTreeTwoImage.draw(at: CGPoint(x: width - elephantThreeOnGrassWithTreeTwoImage.size.width, y: height - 0.5 * elephantThreeOnGrassImage.size.height - elephantThreeOnGrassWithTreeTwoImage.size.height - 20))
}
leftHillImageView.image = UIGraphicsImageRenderer(size: size).image { context in
// clear background leftHillImageView.image = UIGraphicsImageRenderer(size: size).image { context in
UIColor.clear.setFill() // clear background
context.fill(CGRect(origin: .zero, size: size)) UIColor.clear.setFill()
context.fill(CGRect(origin: .zero, size: size))
// draw elephantThreeOnGrassWithTreeThree
// elephantThreeOnGrassWithTreeThree.bottomY + 30 align to elephantThreeOnGrassImage.centerY // draw elephantThreeOnGrassWithTreeThree
elephantThreeOnGrassWithTreeThreeImage.draw(at: CGPoint(x: -160, y: height - 0.5 * elephantThreeOnGrassImage.size.height - elephantThreeOnGrassWithTreeThreeImage.size.height - 80)) // elephantThreeOnGrassWithTreeThree.bottomY + 30 align to elephantThreeOnGrassImage.centerY
} elephantThreeOnGrassWithTreeThreeImage.draw(at: CGPoint(x: -160, y: height - 0.5 * elephantThreeOnGrassImage.size.height - elephantThreeOnGrassWithTreeThreeImage.size.height - 80))
}
centerHillImageView.image = UIGraphicsImageRenderer(size: size).image { context in
// clear background centerHillImageView.image = UIGraphicsImageRenderer(size: size).image { context in
UIColor.clear.setFill() // clear background
context.fill(CGRect(origin: .zero, size: size)) UIColor.clear.setFill()
context.fill(CGRect(origin: .zero, size: size))
// draw elephantThreeOnGrass
elephantThreeOnGrassExtendImage.draw(at: CGPoint(x: 0, y: height - elephantThreeOnGrassExtendImage.size.height)) // draw elephantThreeOnGrass
} elephantThreeOnGrassExtendImage.draw(at: CGPoint(x: 0, y: height - elephantThreeOnGrassExtendImage.size.height))
} }
} }
}
func update(contentOffset: CGFloat) {
//TODO: @zeitschlag update frames func setup() {
print(Int(contentOffset)) layout = {
switch traitCollection.userInterfaceIdiom {
case .phone:
return .compact
default:
return .regular
}
}()
// set illustration
guard superview == nil else {
return
}
contentMode = .scaleAspectFit
cloudBaseImageView.addMotionEffect(
UIInterpolatingMotionEffect.motionEffect(minX: -5, maxX: 5, minY: -5, maxY: 5)
)
rightHillImageView.addMotionEffect(
UIInterpolatingMotionEffect.motionEffect(minX: -15, maxX: 25, minY: -10, maxY: 10)
)
leftHillImageView.addMotionEffect(
UIInterpolatingMotionEffect.motionEffect(minX: -25, maxX: 15, minY: -15, maxY: 15)
)
centerHillImageView.addMotionEffect(
UIInterpolatingMotionEffect.motionEffect(minX: -14, maxX: 14, minY: -5, maxY: 25)
)
elephantOnAirplaneWithContrailImageView.addMotionEffect(
UIInterpolatingMotionEffect.motionEffect(minX: -20, maxX: 12, minY: -20, maxY: 12) // maxX should not larger then the bleeding (12pt)
)
}
func update(contentOffset: CGFloat) {
// updating the constraints doesn't work smoothly.
elephantOnAirplaneLeftConstraint?.constant = -(contentOffset / 50) + 111
} }
} }

View File

@ -21,29 +21,9 @@ final class WelcomeViewController: UIViewController, NeedsDependency {
private(set) lazy var viewModel = WelcomeViewModel(context: context) private(set) lazy var viewModel = WelcomeViewModel(context: context)
let welcomeIllustrationView = WelcomeIllustrationView() let welcomeIllustrationView = WelcomeIllustrationView()
var welcomeIllustrationViewBottomAnchorLayoutConstraint: NSLayoutConstraint?
private(set) lazy var dismissBarButtonItem = UIBarButtonItem(barButtonSystemItem: .close, target: self, action: #selector(WelcomeViewController.dismissBarButtonItemDidPressed(_:))) private(set) lazy var dismissBarButtonItem = UIBarButtonItem(barButtonSystemItem: .close, target: self, action: #selector(WelcomeViewController.dismissBarButtonItemDidPressed(_:)))
private(set) lazy var logoImageView: UIImageView = {
let image = Asset.Scene.Welcome.mastodonLogo.image
let imageView = UIImageView(image: image)
imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.isHidden = true
return imageView
}()
private(set) lazy var sloganLabel: UILabel = {
let label = UILabel()
label.font = UIFontMetrics(forTextStyle: .largeTitle).scaledFont(for: .systemFont(ofSize: 34, weight: .bold))
label.textColor = Asset.Colors.Label.primary.color
label.text = L10n.Scene.Welcome.slogan
label.adjustsFontForContentSizeCategory = true
label.translatesAutoresizingMaskIntoConstraints = false
label.numberOfLines = 0
return label
}()
let buttonContainer = UIStackView() let buttonContainer = UIStackView()
private(set) lazy var signUpButton: PrimaryActionButton = { private(set) lazy var signUpButton: PrimaryActionButton = {
@ -101,7 +81,20 @@ extension WelcomeViewController {
view.overrideUserInterfaceStyle = .light view.overrideUserInterfaceStyle = .light
setupOnboardingAppearance() setupOnboardingAppearance()
setupIllustrationLayout()
view.addSubview(welcomeIllustrationView)
welcomeIllustrationView.translatesAutoresizingMaskIntoConstraints = false
let bottomAnchorLayoutConstraint = welcomeIllustrationView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
NSLayoutConstraint.activate([
welcomeIllustrationView.topAnchor.constraint(equalTo: view.topAnchor),
welcomeIllustrationView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
view.trailingAnchor.constraint(equalTo: welcomeIllustrationView.trailingAnchor),
bottomAnchorLayoutConstraint
])
welcomeIllustrationView.bottomAnchorLayoutConstraint = bottomAnchorLayoutConstraint
buttonContainer.axis = .vertical buttonContainer.axis = .vertical
buttonContainer.spacing = 12 buttonContainer.spacing = 12
@ -147,6 +140,8 @@ extension WelcomeViewController {
pageViewController.didMove(toParent: self) pageViewController.didMove(toParent: self)
let scrollviews = pageViewController.view.subviews.filter { type(of: $0).isSubclass(of: UIScrollView.self) }.compactMap { $0 as? UIScrollView } let scrollviews = pageViewController.view.subviews.filter { type(of: $0).isSubclass(of: UIScrollView.self) }.compactMap { $0 as? UIScrollView }
for scrollView in scrollviews { for scrollView in scrollviews {
@ -183,7 +178,7 @@ extension WelcomeViewController {
if view.safeAreaInsets.bottom == 0 { if view.safeAreaInsets.bottom == 0 {
overlap += 56 overlap += 56
} }
welcomeIllustrationViewBottomAnchorLayoutConstraint?.constant = overlap welcomeIllustrationView.bottomAnchorLayoutConstraint?.constant = overlap
} }
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
@ -194,7 +189,6 @@ extension WelcomeViewController {
setupIllustrationLayout() setupIllustrationLayout()
setupButtonShadowView() setupButtonShadowView()
} }
} }
extension WelcomeViewController { extension WelcomeViewController {
@ -245,91 +239,7 @@ extension WelcomeViewController {
} }
private func setupIllustrationLayout() { private func setupIllustrationLayout() {
welcomeIllustrationView.layout = { welcomeIllustrationView.setup()
switch traitCollection.userInterfaceIdiom {
case .phone:
return .compact
default:
return .regular
}
}()
// set logo
if logoImageView.superview == nil {
view.addSubview(logoImageView)
NSLayoutConstraint.activate([
logoImageView.topAnchor.constraint(equalTo: view.layoutMarginsGuide.topAnchor),
logoImageView.leadingAnchor.constraint(equalTo: view.readableContentGuide.leadingAnchor, constant: 35),
view.readableContentGuide.trailingAnchor.constraint(equalTo: logoImageView.trailingAnchor, constant: 35),
logoImageView.heightAnchor.constraint(equalTo: logoImageView.widthAnchor, multiplier: 75.0/269.0),
])
logoImageView.setContentHuggingPriority(.defaultHigh, for: .vertical)
}
// set illustration
guard welcomeIllustrationView.superview == nil else {
return
}
welcomeIllustrationView.contentMode = .scaleAspectFit
welcomeIllustrationView.translatesAutoresizingMaskIntoConstraints = false
welcomeIllustrationViewBottomAnchorLayoutConstraint = welcomeIllustrationView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 5)
view.addSubview(welcomeIllustrationView)
// welcomeIllustrationView.isHidden = true
NSLayoutConstraint.activate([
view.leftAnchor.constraint(equalTo: welcomeIllustrationView.leftAnchor, constant: 15),
welcomeIllustrationView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: 15),
welcomeIllustrationViewBottomAnchorLayoutConstraint!.priority(.required - 1),
])
welcomeIllustrationView.cloudBaseImageView.addMotionEffect(
UIInterpolatingMotionEffect.motionEffect(minX: -5, maxX: 5, minY: -5, maxY: 5)
)
welcomeIllustrationView.rightHillImageView.addMotionEffect(
UIInterpolatingMotionEffect.motionEffect(minX: -15, maxX: 25, minY: -10, maxY: 10)
)
welcomeIllustrationView.leftHillImageView.addMotionEffect(
UIInterpolatingMotionEffect.motionEffect(minX: -25, maxX: 15, minY: -15, maxY: 15)
)
welcomeIllustrationView.centerHillImageView.addMotionEffect(
UIInterpolatingMotionEffect.motionEffect(minX: -14, maxX: 14, minY: -5, maxY: 25)
)
let topPaddingView = UIView()
topPaddingView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(topPaddingView)
NSLayoutConstraint.activate([
topPaddingView.topAnchor.constraint(equalTo: logoImageView.bottomAnchor),
topPaddingView.leadingAnchor.constraint(equalTo: logoImageView.leadingAnchor),
topPaddingView.trailingAnchor.constraint(equalTo: logoImageView.trailingAnchor),
])
welcomeIllustrationView.elephantOnAirplaneWithContrailImageView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(welcomeIllustrationView.elephantOnAirplaneWithContrailImageView)
NSLayoutConstraint.activate([
view.leftAnchor.constraint(equalTo: welcomeIllustrationView.elephantOnAirplaneWithContrailImageView.leftAnchor, constant: 12), // add 12pt bleeding
welcomeIllustrationView.elephantOnAirplaneWithContrailImageView.topAnchor.constraint(equalTo: topPaddingView.bottomAnchor),
// make a little bit large
welcomeIllustrationView.elephantOnAirplaneWithContrailImageView.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.84),
welcomeIllustrationView.elephantOnAirplaneWithContrailImageView.heightAnchor.constraint(equalTo: welcomeIllustrationView.elephantOnAirplaneWithContrailImageView.widthAnchor, multiplier: 105.0/318.0),
])
let bottomPaddingView = UIView()
bottomPaddingView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(bottomPaddingView)
NSLayoutConstraint.activate([
bottomPaddingView.topAnchor.constraint(equalTo: welcomeIllustrationView.elephantOnAirplaneWithContrailImageView.bottomAnchor),
bottomPaddingView.leadingAnchor.constraint(equalTo: logoImageView.leadingAnchor),
bottomPaddingView.trailingAnchor.constraint(equalTo: logoImageView.trailingAnchor),
bottomPaddingView.bottomAnchor.constraint(equalTo: view.centerYAnchor),
bottomPaddingView.heightAnchor.constraint(equalTo: topPaddingView.heightAnchor, multiplier: 4),
])
welcomeIllustrationView.elephantOnAirplaneWithContrailImageView.addMotionEffect(
UIInterpolatingMotionEffect.motionEffect(minX: -20, maxX: 12, minY: -20, maxY: 12) // maxX should not larger then the bleeding (12pt)
)
view.bringSubviewToFront(logoImageView)
view.bringSubviewToFront(sloganLabel)
} }
} }
@ -410,6 +320,7 @@ extension WelcomeViewController: UIPageViewControllerDelegate {
if let pageIndex = WelcomeContentPage.allCases.firstIndex(of: currentPage) { if let pageIndex = WelcomeContentPage.allCases.firstIndex(of: currentPage) {
let offset = Int(pageIndex) * Int(pageViewController.view.frame.width) let offset = Int(pageIndex) * Int(pageViewController.view.frame.width)
currentPageOffset = offset currentPageOffset = offset
welcomeIllustrationView.update(contentOffset: CGFloat(offset))
} }
} }
} }