Skip to content

Instantly share code, notes, and snippets.

@Coder-ACJHP
Last active April 12, 2019 18:56
Show Gist options
  • Save Coder-ACJHP/734e4c4e53c13dc80dde74913e84d795 to your computer and use it in GitHub Desktop.
Save Coder-ACJHP/734e4c4e53c13dc80dde74913e84d795 to your computer and use it in GitHub Desktop.
How to draw chart bar with animation in swift 4+
//
// ChartBarViewController.swift
//
// Created by Onur Işık on 12.04.2019.
// Copyright © 2019 Onur Işık. All rights reserved.
//
import UIKit
class ChartBarViewController: UIViewController {
var chartLineList: [NSLayoutConstraint] = []
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor(red:0.99, green:0.96, blue:1.00, alpha:1.0)
setupChartView()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.perform(#selector(animateBars), with: nil, afterDelay: 1.0)
}
@objc fileprivate func animateBars() {
chartLineList.forEach { (heightConstraint) in
heightConstraint.isActive = true
}
UIView.animate(withDuration: 1.0, delay: 0,
usingSpringWithDamping: 1,
initialSpringVelocity: 1,
options: .curveEaseIn, animations: {
self.view.layoutIfNeeded()
}, completion: nil)
}
private func setupChartView() {
let chartViewContainer = UIView()
chartViewContainer.backgroundColor = .white
chartViewContainer.layer.cornerRadius = 10
chartViewContainer.layer.shadowColor = UIColor.darkGray.cgColor
chartViewContainer.layer.shadowRadius = 10
chartViewContainer.layer.shadowOffset = CGSize(width: 0, height: 0)
chartViewContainer.layer.shadowOpacity = 0.3;
chartViewContainer.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(chartViewContainer)
let label = UILabel()
label.font = UIFont.boldSystemFont(ofSize: 30)
label.textColor = .darkGray
label.text = "Focus Time"
label.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(label)
let chartBarStackView = UIStackView(arrangedSubviews: [])
chartBarStackView.distribution = .fillEqually
chartBarStackView.alignment = .fill
chartBarStackView.axis = .horizontal
chartBarStackView.spacing = 3
chartBarStackView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(chartBarStackView)
addChartLines(in: chartBarStackView)
NSLayoutConstraint.activate([
chartViewContainer.heightAnchor.constraint(equalToConstant: 270),
chartViewContainer.widthAnchor.constraint(equalToConstant: 350),
chartViewContainer.centerXAnchor.constraint(equalTo: view.centerXAnchor),
chartViewContainer.centerYAnchor.constraint(equalTo: view.centerYAnchor),
label.leadingAnchor.constraint(equalTo: chartViewContainer.leadingAnchor, constant: 8),
label.topAnchor.constraint(equalTo: chartViewContainer.topAnchor, constant: 10),
label.trailingAnchor.constraint(equalTo: chartViewContainer.trailingAnchor, constant: -8),
label.heightAnchor.constraint(equalToConstant: 25),
chartBarStackView.leadingAnchor.constraint(equalTo: chartViewContainer.leadingAnchor, constant: 8),
chartBarStackView.topAnchor.constraint(equalTo: label.bottomAnchor, constant: 10),
chartBarStackView.trailingAnchor.constraint(equalTo: chartViewContainer.trailingAnchor, constant: -8),
chartBarStackView.bottomAnchor.constraint(equalTo: chartViewContainer.bottomAnchor, constant: -10)
])
}
private func addChartLines(in stackView: UIStackView) {
createMockChartData().forEach { (chart) in
let chartLineBackground = UIView()
chartLineBackground.backgroundColor = UIColor.init(white: 0.93, alpha: 1)
chartLineBackground.layer.cornerRadius = 5
chartLineBackground.layer.masksToBounds = true
stackView.addArrangedSubview(chartLineBackground)
let chartLine = ChartLine()
chartLine.chart = chart
chartLine.layoutSubviews()
chartLine.translatesAutoresizingMaskIntoConstraints = false
chartLineBackground.addSubview(chartLine)
NSLayoutConstraint.activate([
chartLine.leadingAnchor.constraint(equalTo: chartLineBackground.leadingAnchor),
chartLine.trailingAnchor.constraint(equalTo: chartLineBackground.trailingAnchor),
chartLine.bottomAnchor.constraint(equalTo: chartLineBackground.bottomAnchor)
])
chartLine.heightAnchor.constraint(equalTo: chartLineBackground.heightAnchor, multiplier: 0).isActive = true
let heightConstraint = chartLine.heightAnchor.constraint(equalTo: chartLineBackground.heightAnchor, multiplier: chart.range)
heightConstraint.isActive = false
chartLineList.append(heightConstraint)
}
}
private func createMockChartData() -> [Chart] {
return [
Chart(topColor: .red, bottomColor: .purple, range: 0.2),
Chart(topColor: .red, bottomColor: .purple, range: 0.3),
Chart(topColor: .red, bottomColor: .purple, range: 0.4),
Chart(topColor: .red, bottomColor: .purple, range: 0.5),
Chart(topColor: .red, bottomColor: .purple, range: 0.3),
Chart(topColor: .red, bottomColor: .purple, range: 0.8),
Chart(topColor: .red, bottomColor: .purple, range: 0.9),
Chart(topColor: .red, bottomColor: .purple, range: 0.6),
Chart(topColor: .red, bottomColor: .purple, range: 0.8),
Chart(topColor: .red, bottomColor: .purple, range: 0.4),
Chart(topColor: .red, bottomColor: .purple, range: 0.7),
Chart(topColor: .red, bottomColor: .purple, range: 0.4),
Chart(topColor: .red, bottomColor: .purple, range: 0.7),
Chart(topColor: .red, bottomColor: .purple, range: 0.8),
Chart(topColor: .red, bottomColor: .purple, range: 0.6),
Chart(topColor: .red, bottomColor: .purple, range: 0.4),
Chart(topColor: .red, bottomColor: .purple, range: 0.7),
Chart(topColor: .red, bottomColor: .purple, range: 0.9),
Chart(topColor: .red, bottomColor: .purple, range: 0.1),
Chart(topColor: .red, bottomColor: .purple, range: 0.8),
Chart(topColor: .red, bottomColor: .purple, range: 0.2),
Chart(topColor: .red, bottomColor: .purple, range: 0.8),
Chart(topColor: .red, bottomColor: .purple, range: 0.6),
Chart(topColor: .red, bottomColor: .purple, range: 0.8),
Chart(topColor: .red, bottomColor: .purple, range: 0.4),
Chart(topColor: .red, bottomColor: .purple, range: 0.7),
Chart(topColor: .red, bottomColor: .purple, range: 0.4),
Chart(topColor: .red, bottomColor: .purple, range: 0.7),
Chart(topColor: .red, bottomColor: .purple, range: 0.8),
Chart(topColor: .red, bottomColor: .purple, range: 0.4),
]
}
}
struct Chart {
let topColor: UIColor!
let bottomColor: UIColor!
let range: CGFloat!
}
class ChartLine: UIView {
var chart: Chart! {
didSet {
gradientLayer.colors = [chart.topColor.cgColor, chart.bottomColor.cgColor]
}
}
let gradientLayer = CAGradientLayer()
override init(frame: CGRect) {
super.init(frame: frame)
gradientLayer.colors = []
gradientLayer.cornerRadius = 5
gradientLayer.masksToBounds = true
gradientLayer.locations = [0.0, 0.5]
layer.addSublayer(gradientLayer)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
super.layoutSubviews()
gradientLayer.frame = bounds
}
}
@Coder-ACJHP
Copy link
Author

Coder-ACJHP commented Apr 12, 2019

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