Created
May 2, 2019 19:30
-
-
Save Coder-ACJHP/b2233bfbcf61cd086c033b300edfccaa to your computer and use it in GitHub Desktop.
Build 3D carousel for image cards with Swift 4+
This file contains 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
// | |
// 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