Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Classes/Drawing/ReferenceLineDrawingView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ internal class ReferenceLineDrawingView : UIView {
}

private func boundingSize(forText text: String) -> CGSize {
return (text as NSString).size(attributes: [NSFontAttributeName:self.settings.referenceLineLabelFont])
return (text as NSString).size(withAttributes: [NSAttributedStringKey.font:self.settings.referenceLineLabelFont])
}

private func calculateYAxisValue(for point: CGPoint) -> Double {
Expand Down
66 changes: 66 additions & 0 deletions Classes/Drawing/ValueDrawingLayer.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
//
// ValueDrawingLayer.swift
// ScrollableGraphView
//
// Created by RiuHDuo on 2017/12/8.
// Copyright © 2017年 SGV. All rights reserved.
//

import UIKit

class ValueDrawingLayer: ScrollableGraphViewDrawingLayer {

let font: UIFont
let color: UIColor

private var textLayers = [CATextLayer]()

init(frame: CGRect, font: UIFont, color: UIColor) {

self.font = font
self.color = color

super.init(viewportWidth: frame.size.width, viewportHeight: frame.size.height)
}

required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

private func createDataPointPath() {

for layer in self.textLayers{
layer.removeFromSuperlayer()
}

guard let activePointsInterval = self.owner?.graphViewDrawingDelegate?.intervalForActivePoints() else{ return}
for i in activePointsInterval {

var location = CGPoint.zero

if let pointLocation = owner?.graphPoint(forIndex: i) {
location = pointLocation.location
}

let layer = CATextLayer()
layer.contentsScale = UIScreen.main.scale
layer.string = String(format:"%.2f", self.owner?.data[i] ?? 0)
layer.bounds = CGRect(x: 0, y: 0, width: 60, height: 14)
layer.font = self.font.fontName as CFTypeRef
layer.fontSize = self.font.pointSize
layer.alignmentMode = kCAAlignmentCenter
layer.position = CGPoint(x: location.x, y: location.y - 10)
layer.foregroundColor = UIColor.black.cgColor
self.addSublayer(layer)
self.textLayers.append(layer)
}


}



override func updatePath() {
createDataPointPath()
}
}
47 changes: 27 additions & 20 deletions Classes/Plots/Plot.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ open class Plot {
// The id for this plot. Used when determining which data to give it in the dataSource
open var identifier: String!

var graphViewDrawingDelegate: ScrollableGraphViewDrawingDelegate! = nil
weak var graphViewDrawingDelegate: ScrollableGraphViewDrawingDelegate? = nil

// Animation Settings
// ##################
Expand All @@ -22,6 +22,8 @@ open class Plot {
}
}
}

var data = [Int:Double]()
/// The animation style.
open var adaptAnimationType = ScrollableGraphViewAnimationType.easeOut
/// If adaptAnimationType is set to .Custom, then this is the easing function you would like applied for the animation.
Expand All @@ -35,9 +37,9 @@ open class Plot {
private var previousTimestamp: CFTimeInterval = 0
private var currentTimestamp: CFTimeInterval = 0

private var graphPoints = [GraphPoint]()
internal var graphPoints = [GraphPoint]()

deinit {
func release(){
displayLink?.invalidate()
}

Expand All @@ -64,7 +66,7 @@ open class Plot {
}
}

graphViewDrawingDelegate.updatePaths()
graphViewDrawingDelegate?.updatePaths()
}

private func animate(point: GraphPoint, to position: CGPoint, withDelay delay: Double = 0) {
Expand Down Expand Up @@ -145,15 +147,15 @@ open class Plot {

animatePlotPointPositions(forPoints: pointsToAnimate, withData: data, withDelay: stagger)
}

internal func createPlotPoints(numberOfPoints: Int, range: (min: Double, max: Double)) {
for i in 0 ..< numberOfPoints {

let value = range.min

let position = graphViewDrawingDelegate.calculatePosition(atIndex: i, value: value)
let point = GraphPoint(position: position)
graphPoints.append(point)
if let position = graphViewDrawingDelegate?.calculatePosition(atIndex: i, value: value){
let point = GraphPoint(position: position)
graphPoints.append(point)
}
}
}

Expand All @@ -170,26 +172,30 @@ open class Plot {

let value = data[dataPosition]

let newPosition = graphViewDrawingDelegate.calculatePosition(atIndex: i, value: value)
graphPoints[i].x = newPosition.x
graphPoints[i].y = newPosition.y
if let newPosition = graphViewDrawingDelegate?.calculatePosition(atIndex: i, value: value){
graphPoints[i].x = newPosition.x
graphPoints[i].y = newPosition.y
}
}
}

// Same as a above, but can take an array with the indicies of the activated points rather than a range.
internal func setPlotPointPositions(forNewlyActivatedPoints activatedPoints: [Int], withData data: [Double]) {

var index = 0

for activatedPointIndex in activatedPoints {

let dataPosition = index
let value = data[dataPosition]


let newPosition = graphViewDrawingDelegate.calculatePosition(atIndex: activatedPointIndex, value: value)
graphPoints[activatedPointIndex].x = newPosition.x
graphPoints[activatedPointIndex].y = newPosition.y

index += 1
if let newPosition = graphViewDrawingDelegate?.calculatePosition(atIndex: activatedPointIndex, value: value){
graphPoints[activatedPointIndex].x = newPosition.x
graphPoints[activatedPointIndex].y = newPosition.y

index += 1
}
}
}

Expand All @@ -200,10 +206,11 @@ open class Plot {
// For any visible points, kickoff the animation to their new position after the axis' min/max has changed.
var dataIndex = 0
for pointIndex in pointsToAnimate {
let newPosition = graphViewDrawingDelegate.calculatePosition(atIndex: pointIndex, value: data[dataIndex])
let point = graphPoints[pointIndex]
animate(point: point, to: newPosition, withDelay: Double(dataIndex) * delay)
dataIndex += 1
if let newPosition = graphViewDrawingDelegate?.calculatePosition(atIndex: pointIndex, value: data[dataIndex]){
let point = graphPoints[pointIndex]
animate(point: point, to: newPosition, withDelay: Double(dataIndex) * delay)
dataIndex += 1
}
}
}

Expand Down
31 changes: 31 additions & 0 deletions Classes/Plots/ValuePlot.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
//
// ValuePlot.swift
// ScrollableGraphView
//
// Created by RiuHDuo on 2017/12/8.
// Copyright © 2017年 SGV. All rights reserved.
//

import UIKit

open class ValuePlot: Plot {
private var dataPointLayer: ValueDrawingLayer?

open var font = UIFont.systemFont(ofSize: 10)
open var color = UIColor.black

public init(identifier: String) {
super.init()
self.identifier = identifier
}

override func layers(forViewport viewport: CGRect) -> [ScrollableGraphViewDrawingLayer?] {
createLayers(viewport: viewport)
return [dataPointLayer]
}

private func createLayers(viewport: CGRect) {
dataPointLayer = ValueDrawingLayer(frame: viewport, font: font, color: color)
dataPointLayer?.owner = self
}
}
2 changes: 1 addition & 1 deletion Classes/Protocols/ScrollableGraphViewDataSource.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

import UIKit

public protocol ScrollableGraphViewDataSource {
public protocol ScrollableGraphViewDataSource: class {
func value(forPlot plot: Plot, atIndex pointIndex: Int) -> Double
func label(atIndex pointIndex: Int) -> String
func numberOfPoints() -> Int // This now forces the same number of points in each plot.
Expand Down
2 changes: 1 addition & 1 deletion Classes/Protocols/ScrollableGraphViewDrawingDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import UIKit

// Delegate definition that provides the data required by the drawing layers.
internal protocol ScrollableGraphViewDrawingDelegate {
internal protocol ScrollableGraphViewDrawingDelegate: class{
func intervalForActivePoints() -> CountableRange<Int>
func rangeForActivePoints() -> (min: Double, max: Double)
func paddingForPoints() -> (leftmostPointPadding: CGFloat, rightmostPointPadding: CGFloat)
Expand Down
29 changes: 26 additions & 3 deletions Classes/ScrollableGraphView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -96,14 +96,21 @@ import UIKit
private var labelPool = LabelPool()

// Data Source
open var dataSource: ScrollableGraphViewDataSource? {
weak open var dataSource: ScrollableGraphViewDataSource? {
didSet {
if(plots.count > 0) {
reload()
}
}
}

deinit {
debugPrint("RELASE")
for plot in plots{
plot.release()
}
}

// Active Points & Range Calculation
private var previousActivePointsInterval: CountableRange<Int> = -1 ..< -1
private var activePointsInterval: CountableRange<Int> = -1 ..< -1 {
Expand Down Expand Up @@ -332,7 +339,7 @@ import UIKit
guard dataSource.numberOfPoints() > 0 else {
return
}

if (isInitialSetup) {
setup()

Expand Down Expand Up @@ -361,6 +368,7 @@ import UIKit
self.previousActivePointsInterval = self.activePointsInterval
self.activePointsInterval = newActivePointsInterval


// If adaption is enabled we want to
if(shouldAdaptRange) {
// TODO: This is currently called every single frame...
Expand Down Expand Up @@ -455,12 +463,26 @@ import UIKit
// Limitation: Can only be used when reloading the same number of data points!
public func reload() {
stopAnimations()
rangeDidChange()
resetPoint()
updateUI()
rangeDidChange()
updatePaths()
updateLabelsForCurrentInterval()
}

func resetPoint(){
let number = self.dataSource?.numberOfPoints() ?? 0
if number != (self.plots.first?.graphPoints.count ?? 0) {
for plot in self.plots {
plot.reset()
plot.createPlotPoints(numberOfPoints: number, range: self.range)
plot.setup()
}
totalGraphWidth = graphWidth(forNumberOfDataPoints: number)
self.contentSize = CGSize(width: totalGraphWidth, height: viewportHeight)
}
}

// The functions for adding plots and reference lines need to be able to add plots
// both before and after the graph knows its viewport/size.
// This needs to be the case so we can use it in interface builder as well as
Expand Down Expand Up @@ -659,6 +681,7 @@ import UIKit

for i in activeInterval.startIndex ..< activeInterval.endIndex {
let dataForIndexI = dataSource?.value(forPlot: plot, atIndex: i) ?? 0
plot.data[i] = dataForIndexI
dataForInterval.append(dataForIndexI)
}

Expand Down
Loading