Skip to content

Instantly share code, notes, and snippets.

@Coder-ACJHP
Created May 2, 2019 19:30
Show Gist options
  • Save Coder-ACJHP/b2233bfbcf61cd086c033b300edfccaa to your computer and use it in GitHub Desktop.
Save Coder-ACJHP/b2233bfbcf61cd086c033b300edfccaa to your computer and use it in GitHub Desktop.
Build 3D carousel for image cards with Swift 4+
//
// CarouselViewController.swift
//
// Created by Onur Işık on 2.05.2019.
// Copyright © 2019 Fitbest Bilgi Teknolojileri A.Ş. All rights reserved.
//
import UIKit
class CarouselViewController: UIViewController {
var currentAngle: CGFloat = 0
var currentOffset: CGFloat = 0
let transformLayer = CATransformLayer()
override func viewDidLoad() {
super.viewDidLoad()
let panGesture = UIPanGestureRecognizer(target: self, action: #selector(handlePan(_:)))
view.addGestureRecognizer(panGesture)
transformLayer.frame = view.bounds
view.layer.addSublayer(transformLayer)
// Getting images from Assets so you need to change here and add your own image names
(0...5).forEach { index in
addImageCard(name: "demoImage\(index)")
}
turnCarosel()
}
override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
private func degreeToRadians(degree: CGFloat) -> CGFloat {
return (degree * CGFloat.pi) / 180
}
private func addImageCard(name: String) {
let cardSize = CGSize(width: 200, height: 300)
let imageLayer = CALayer()
let origin = CGPoint(x: (view.bounds.width / 2) - (cardSize.width / 2),
y: (view.bounds.height / 2) - (cardSize.height / 2))
imageLayer.frame = CGRect(origin: origin, size: cardSize)
guard let cardImage = UIImage(named: name)?.cgImage else { return }
imageLayer.contents = cardImage
imageLayer.contentsGravity = .resizeAspectFill
imageLayer.borderColor = UIColor.lightGray.cgColor
imageLayer.borderWidth = 3.0
imageLayer.cornerRadius = 8
imageLayer.masksToBounds = true
imageLayer.isDoubleSided = true
transformLayer.addSublayer(imageLayer)
}
private func turnCarosel() {
guard let transformSubLayers = transformLayer.sublayers else { return }
let segmentForImageCard = CGFloat(360 / transformSubLayers.count)
var angleOffset = currentAngle
transformSubLayers.forEach { (layer) in
var transform = CATransform3DIdentity
transform.m34 = -1 / 500
transform = CATransform3DRotate(transform, degreeToRadians(degree: angleOffset), 0, 1, 0)
transform = CATransform3DTranslate(transform, 0, 0, 200)
CATransaction.setAnimationDuration(0)
layer.transform = transform
angleOffset += segmentForImageCard
}
}
@objc private func handlePan(_ gestureRecognier: UIPanGestureRecognizer) {
let xOffset = gestureRecognier.translation(in: view).x
if gestureRecognier.state == .began {
currentOffset = 0
}
let xDifference = xOffset * 0.6 - currentOffset
currentOffset += xDifference
currentAngle += xDifference
turnCarosel()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment