├── ORCharts ├── Assets │ └── .gitkeep └── Classes │ ├── .gitkeep │ ├── ORCharts.h │ ├── ORLineChart │ ├── ORLineChartButton.h │ ├── ORLineChartCell.h │ ├── ORLineChartView.h │ ├── ORLineChartValue.h │ ├── ORLineChartConfig.m │ ├── ORLineChartCell.m │ ├── ORLineChartButton.m │ ├── ORLineChartValue.m │ ├── ORLineChartConfig.h │ └── ORLineChartView.m │ ├── ORRingChart │ ├── ORRingChartConfig.m │ ├── ORRingChartView.h │ ├── ORChartUtilities+ORRing.h │ ├── ORRingChartConfig.h │ ├── ORChartUtilities+ORRing.m │ └── ORRingChartView.m │ └── ORChartUtilities │ ├── ORChartUtilities.h │ └── ORChartUtilities.m ├── _Pods.xcodeproj ├── .DS_Store ├── gif ├── 001.png ├── 002.gif ├── 002.png ├── 003.gif ├── 003.png ├── 004.png └── ring.gif ├── Example ├── Tests │ ├── en.lproj │ │ └── InfoPlist.strings │ ├── Tests-Prefix.pch │ ├── Tests-Info.plist │ └── Tests.m ├── ORCharts │ ├── en.lproj │ │ └── InfoPlist.strings │ ├── ORAppDelegate.h │ ├── Controller │ │ ├── LineChartVC │ │ │ ├── ORLineMoreViewController.h │ │ │ ├── ORLineViewController.h │ │ │ ├── ORLineViewController.m │ │ │ └── ORLineMoreViewController.m │ │ └── RingChartVC │ │ │ ├── ORRingViewController.h │ │ │ ├── ORRingMoreViewController.h │ │ │ ├── ORRingViewController.m │ │ │ └── ORRingMoreViewController.m │ ├── ORCharts-Prefix.pch │ ├── main.m │ ├── ORCharts-Info.plist │ ├── Base.lproj │ │ └── LaunchScreen.storyboard │ ├── Images.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ └── ORAppDelegate.m ├── Pods │ ├── Target Support Files │ │ ├── ORCharts │ │ │ ├── ORCharts.modulemap │ │ │ ├── ORCharts-dummy.m │ │ │ ├── ORCharts-prefix.pch │ │ │ ├── ORCharts.xcconfig │ │ │ ├── ORCharts-umbrella.h │ │ │ └── ORCharts-Info.plist │ │ ├── Pods-ORCharts_Tests │ │ │ ├── Pods-ORCharts_Tests.modulemap │ │ │ ├── Pods-ORCharts_Tests-dummy.m │ │ │ ├── Pods-ORCharts_Tests-acknowledgements.markdown │ │ │ ├── Pods-ORCharts_Tests-umbrella.h │ │ │ ├── Pods-ORCharts_Tests.debug.xcconfig │ │ │ ├── Pods-ORCharts_Tests.release.xcconfig │ │ │ ├── Pods-ORCharts_Tests-Info.plist │ │ │ └── Pods-ORCharts_Tests-acknowledgements.plist │ │ └── Pods-ORCharts_Example │ │ │ ├── Pods-ORCharts_Example.modulemap │ │ │ ├── Pods-ORCharts_Example-dummy.m │ │ │ ├── Pods-ORCharts_Example-umbrella.h │ │ │ ├── Pods-ORCharts_Example.debug.xcconfig │ │ │ ├── Pods-ORCharts_Example.release.xcconfig │ │ │ ├── Pods-ORCharts_Example-Info.plist │ │ │ ├── Pods-ORCharts_Example-acknowledgements.markdown │ │ │ ├── Pods-ORCharts_Example-acknowledgements.plist │ │ │ └── Pods-ORCharts_Example-frameworks.sh │ ├── Pods.xcodeproj │ │ └── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ ├── Manifest.lock │ └── Local Podspecs │ │ └── ORCharts.podspec.json ├── ORCharts.xcodeproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ ├── xcshareddata │ │ └── xcschemes │ │ │ └── ORCharts-Example.xcscheme │ └── project.pbxproj ├── Podfile ├── ORCharts.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ ├── IDEWorkspaceChecks.plist │ │ └── WorkspaceSettings.xcsettings └── Podfile.lock ├── .travis.yml ├── .gitignore ├── LICENSE ├── ORCharts.podspec └── README.md /ORCharts/Assets/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ORCharts/Classes/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /_Pods.xcodeproj: -------------------------------------------------------------------------------- 1 | Example/Pods/Pods.xcodeproj -------------------------------------------------------------------------------- /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reference/ORCharts/master/.DS_Store -------------------------------------------------------------------------------- /gif/001.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reference/ORCharts/master/gif/001.png -------------------------------------------------------------------------------- /gif/002.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reference/ORCharts/master/gif/002.gif -------------------------------------------------------------------------------- /gif/002.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reference/ORCharts/master/gif/002.png -------------------------------------------------------------------------------- /gif/003.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reference/ORCharts/master/gif/003.gif -------------------------------------------------------------------------------- /gif/003.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reference/ORCharts/master/gif/003.png -------------------------------------------------------------------------------- /gif/004.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reference/ORCharts/master/gif/004.png -------------------------------------------------------------------------------- /gif/ring.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reference/ORCharts/master/gif/ring.gif -------------------------------------------------------------------------------- /Example/Tests/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Example/ORCharts/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/ORCharts/ORCharts.modulemap: -------------------------------------------------------------------------------- 1 | framework module ORCharts { 2 | umbrella header "ORCharts-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Example/Tests/Tests-Prefix.pch: -------------------------------------------------------------------------------- 1 | // The contents of this file are implicitly included at the beginning of every test case source file. 2 | 3 | #ifdef __OBJC__ 4 | 5 | 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/ORCharts/ORCharts-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_ORCharts : NSObject 3 | @end 4 | @implementation PodsDummy_ORCharts 5 | @end 6 | -------------------------------------------------------------------------------- /Example/Pods/Pods.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-ORCharts_Tests/Pods-ORCharts_Tests.modulemap: -------------------------------------------------------------------------------- 1 | framework module Pods_ORCharts_Tests { 2 | umbrella header "Pods-ORCharts_Tests-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-ORCharts_Example/Pods-ORCharts_Example.modulemap: -------------------------------------------------------------------------------- 1 | framework module Pods_ORCharts_Example { 2 | umbrella header "Pods-ORCharts_Example-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-ORCharts_Tests/Pods-ORCharts_Tests-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_ORCharts_Tests : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_ORCharts_Tests 5 | @end 6 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-ORCharts_Tests/Pods-ORCharts_Tests-acknowledgements.markdown: -------------------------------------------------------------------------------- 1 | # Acknowledgements 2 | This application makes use of the following third party libraries: 3 | Generated by CocoaPods - https://cocoapods.org 4 | -------------------------------------------------------------------------------- /Example/ORCharts.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-ORCharts_Example/Pods-ORCharts_Example-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_ORCharts_Example : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_ORCharts_Example 5 | @end 6 | -------------------------------------------------------------------------------- /Example/Podfile: -------------------------------------------------------------------------------- 1 | use_frameworks! 2 | 3 | platform :ios, '8.0' 4 | 5 | target 'ORCharts_Example' do 6 | pod 'ORCharts', :path => '../' 7 | 8 | target 'ORCharts_Tests' do 9 | inherit! :search_paths 10 | 11 | 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/ORCharts/ORCharts-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | -------------------------------------------------------------------------------- /Example/ORCharts.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Example/ORCharts.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Example/ORCharts.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BuildSystemType 6 | Original 7 | 8 | 9 | -------------------------------------------------------------------------------- /Example/ORCharts.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Example/Pods/Pods.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ORCharts/Classes/ORCharts.h: -------------------------------------------------------------------------------- 1 | // 2 | // ORCharts.h 3 | // ORChartsDemo 4 | // 5 | // Created by OrangesAL on 2019/7/14. 6 | // Copyright © 2019 欧阳荣. All rights reserved. 7 | // 8 | 9 | #ifndef ORCharts_h 10 | #define ORCharts_h 11 | 12 | #import "ORLineChartView.h" 13 | #import "ORRingChartView.h" 14 | 15 | 16 | #endif /* ORCharts_h */ 17 | -------------------------------------------------------------------------------- /Example/ORCharts/ORAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // ORAppDelegate.h 3 | // ORCharts 4 | // 5 | // Created by sunrise_oy@163.com on 07/14/2019. 6 | // Copyright (c) 2019 sunrise_oy@163.com. All rights reserved. 7 | // 8 | 9 | @import UIKit; 10 | 11 | @interface ORAppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Example/ORCharts/Controller/LineChartVC/ORLineMoreViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ORLineViewController.h 3 | // ORChartsDemo 4 | // 5 | // Created by 欧阳荣 on 2019/7/11. 6 | // Copyright © 2019 欧阳荣. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface ORLineMoreViewController : UIViewController 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /Example/ORCharts/Controller/LineChartVC/ORLineViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ORLineChartViewController.h 3 | // ORChartView 4 | // 5 | // Created by OrangesAL on 2019/5/4. 6 | // Copyright © 2019年 OrangesAL. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface ORLineViewController : UIViewController 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /Example/ORCharts/Controller/RingChartVC/ORRingViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ORRingViewController.h 3 | // ORChartView 4 | // 5 | // Created by OrangesAL on 2019/4/27. 6 | // Copyright © 2019年 OrangesAL. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface ORRingViewController : UIViewController 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /Example/ORCharts/Controller/RingChartVC/ORRingMoreViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ORRingMoreViewController.h 3 | // ORChartView 4 | // 5 | // Created by OrangesAL on 2019/6/3. 6 | // Copyright © 2019 OrangesAL. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface ORRingMoreViewController : UIViewController 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /Example/ORCharts/ORCharts-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header 3 | // 4 | // The contents of this file are implicitly included at the beginning of every source file. 5 | // 6 | 7 | #import 8 | 9 | #ifndef __IPHONE_5_0 10 | #warning "This project uses features only available in iOS SDK 5.0 and later." 11 | #endif 12 | 13 | #ifdef __OBJC__ 14 | @import UIKit; 15 | @import Foundation; 16 | #endif 17 | -------------------------------------------------------------------------------- /Example/ORCharts/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // ORCharts 4 | // 5 | // Created by sunrise_oy@163.com on 07/14/2019. 6 | // Copyright (c) 2019 sunrise_oy@163.com. All rights reserved. 7 | // 8 | 9 | @import UIKit; 10 | #import "ORAppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) 13 | { 14 | @autoreleasepool { 15 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([ORAppDelegate class])); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /ORCharts/Classes/ORLineChart/ORLineChartButton.h: -------------------------------------------------------------------------------- 1 | // 2 | // ORChartControl.h 3 | // ORChartsDemo 4 | // 5 | // Created by 欧阳荣 on 2019/7/12. 6 | // Copyright © 2019 欧阳荣. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface ORLineChartButton : UIButton 14 | 15 | - (void)or_setTintColor:(UIColor *)tintColor backgroundColor:(UIColor *)backgroundColor; 16 | 17 | @end 18 | 19 | NS_ASSUME_NONNULL_END 20 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/ORCharts/ORCharts.xcconfig: -------------------------------------------------------------------------------- 1 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/ORCharts 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | PODS_BUILD_DIR = ${BUILD_DIR} 4 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 5 | PODS_ROOT = ${SRCROOT} 6 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/../.. 7 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 8 | SKIP_INSTALL = YES 9 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-ORCharts_Tests/Pods-ORCharts_Tests-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | 14 | FOUNDATION_EXPORT double Pods_ORCharts_TestsVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char Pods_ORCharts_TestsVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-ORCharts_Example/Pods-ORCharts_Example-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | 14 | FOUNDATION_EXPORT double Pods_ORCharts_ExampleVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char Pods_ORCharts_ExampleVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /ORCharts/Classes/ORLineChart/ORLineChartCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // ORLineChartCell.h 3 | // ORChartView 4 | // 5 | // Created by OrangesAL on 2019/5/2. 6 | // Copyright © 2019年 OrangesAL. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @class ORLineChartConfig; 14 | 15 | @interface ORLineChartCell : UICollectionViewCell 16 | 17 | @property (nonatomic, strong) NSAttributedString *title; 18 | @property (nonatomic, strong) ORLineChartConfig *config; 19 | 20 | @end 21 | 22 | NS_ASSUME_NONNULL_END 23 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-ORCharts_Tests/Pods-ORCharts_Tests.debug.xcconfig: -------------------------------------------------------------------------------- 1 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/ORCharts" 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/ORCharts/ORCharts.framework/Headers" 4 | OTHER_LDFLAGS = $(inherited) -framework "ORCharts" 5 | PODS_BUILD_DIR = ${BUILD_DIR} 6 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 7 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 8 | PODS_ROOT = ${SRCROOT}/Pods 9 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-ORCharts_Tests/Pods-ORCharts_Tests.release.xcconfig: -------------------------------------------------------------------------------- 1 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/ORCharts" 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/ORCharts/ORCharts.framework/Headers" 4 | OTHER_LDFLAGS = $(inherited) -framework "ORCharts" 5 | PODS_BUILD_DIR = ${BUILD_DIR} 6 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 7 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 8 | PODS_ROOT = ${SRCROOT}/Pods 9 | -------------------------------------------------------------------------------- /Example/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - ORCharts (2.1.7): 3 | - ORCharts/Line (= 2.1.7) 4 | - ORCharts/Ring (= 2.1.7) 5 | - ORCharts/Util (= 2.1.7) 6 | - ORCharts/Line (2.1.7): 7 | - ORCharts/Util 8 | - ORCharts/Ring (2.1.7): 9 | - ORCharts/Util 10 | - ORCharts/Util (2.1.7) 11 | 12 | DEPENDENCIES: 13 | - ORCharts (from `../`) 14 | 15 | EXTERNAL SOURCES: 16 | ORCharts: 17 | :path: "../" 18 | 19 | SPEC CHECKSUMS: 20 | ORCharts: 130f25273c7707e65a2a0a88baca6b064f30d3a3 21 | 22 | PODFILE CHECKSUM: 164365fbe16bb8d73a78d749d34c32d7e1ee2bb8 23 | 24 | COCOAPODS: 1.7.4 25 | -------------------------------------------------------------------------------- /Example/Pods/Manifest.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - ORCharts (2.1.7): 3 | - ORCharts/Line (= 2.1.7) 4 | - ORCharts/Ring (= 2.1.7) 5 | - ORCharts/Util (= 2.1.7) 6 | - ORCharts/Line (2.1.7): 7 | - ORCharts/Util 8 | - ORCharts/Ring (2.1.7): 9 | - ORCharts/Util 10 | - ORCharts/Util (2.1.7) 11 | 12 | DEPENDENCIES: 13 | - ORCharts (from `../`) 14 | 15 | EXTERNAL SOURCES: 16 | ORCharts: 17 | :path: "../" 18 | 19 | SPEC CHECKSUMS: 20 | ORCharts: 130f25273c7707e65a2a0a88baca6b064f30d3a3 21 | 22 | PODFILE CHECKSUM: 164365fbe16bb8d73a78d749d34c32d7e1ee2bb8 23 | 24 | COCOAPODS: 1.7.4 25 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # references: 2 | # * https://www.objc.io/issues/6-build-tools/travis-ci/ 3 | # * https://github.com/supermarin/xcpretty#usage 4 | 5 | osx_image: xcode7.3 6 | language: objective-c 7 | # cache: cocoapods 8 | # podfile: Example/Podfile 9 | # before_install: 10 | # - gem install cocoapods # Since Travis is not always on latest version 11 | # - pod install --project-directory=Example 12 | script: 13 | - set -o pipefail && xcodebuild test -enableCodeCoverage YES -workspace Example/ORCharts.xcworkspace -scheme ORCharts-Example -sdk iphonesimulator9.3 ONLY_ACTIVE_ARCH=NO | xcpretty 14 | - pod lib lint 15 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-ORCharts_Example/Pods-ORCharts_Example.debug.xcconfig: -------------------------------------------------------------------------------- 1 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/ORCharts" 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/ORCharts/ORCharts.framework/Headers" 4 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 5 | OTHER_LDFLAGS = $(inherited) -framework "ORCharts" 6 | PODS_BUILD_DIR = ${BUILD_DIR} 7 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 8 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 9 | PODS_ROOT = ${SRCROOT}/Pods 10 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-ORCharts_Example/Pods-ORCharts_Example.release.xcconfig: -------------------------------------------------------------------------------- 1 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/ORCharts" 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/ORCharts/ORCharts.framework/Headers" 4 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 5 | OTHER_LDFLAGS = $(inherited) -framework "ORCharts" 6 | PODS_BUILD_DIR = ${BUILD_DIR} 7 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 8 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 9 | PODS_ROOT = ${SRCROOT}/Pods 10 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/ORCharts/ORCharts-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | #import "ORLineChartButton.h" 14 | #import "ORLineChartCell.h" 15 | #import "ORLineChartConfig.h" 16 | #import "ORLineChartValue.h" 17 | #import "ORLineChartView.h" 18 | #import "ORChartUtilities+ORRing.h" 19 | #import "ORRingChartConfig.h" 20 | #import "ORRingChartView.h" 21 | #import "ORChartUtilities.h" 22 | 23 | FOUNDATION_EXPORT double ORChartsVersionNumber; 24 | FOUNDATION_EXPORT const unsigned char ORChartsVersionString[]; 25 | 26 | -------------------------------------------------------------------------------- /Example/Tests/Tests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /Example/Tests/Tests.m: -------------------------------------------------------------------------------- 1 | // 2 | // ORChartsTests.m 3 | // ORChartsTests 4 | // 5 | // Created by sunrise_oy@163.com on 07/14/2019. 6 | // Copyright (c) 2019 sunrise_oy@163.com. All rights reserved. 7 | // 8 | 9 | @import XCTest; 10 | 11 | @interface Tests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation Tests 16 | 17 | - (void)setUp 18 | { 19 | [super setUp]; 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | } 22 | 23 | - (void)tearDown 24 | { 25 | // Put teardown code here. This method is called after the invocation of each test method in the class. 26 | [super tearDown]; 27 | } 28 | 29 | - (void)testExample 30 | { 31 | XCTFail(@"No implementation for \"%s\"", __PRETTY_FUNCTION__); 32 | } 33 | 34 | @end 35 | 36 | -------------------------------------------------------------------------------- /ORCharts/Classes/ORLineChart/ORLineChartView.h: -------------------------------------------------------------------------------- 1 | // 2 | // ORLineChartView.h 3 | // ORChartView 4 | // 5 | // Created by OrangesAL on 2019/5/1. 6 | // Copyright © 2019年 OrangesAL. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "ORLineChartConfig.h" 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface ORLineChartView : UIView 15 | 16 | @property (nonatomic, weak) IBOutlet __nullable id dataSource; 17 | @property (nonatomic, weak) IBOutlet __nullable id delegate; 18 | 19 | @property (nonatomic, readonly) ORLineChartConfig *config; 20 | @property (nonatomic, assign) NSInteger defaultSelectIndex; 21 | 22 | - (void)reloadData; 23 | - (void)showDataAtIndex:(NSInteger)index animated:(BOOL)animated; 24 | @end 25 | 26 | 27 | 28 | NS_ASSUME_NONNULL_END 29 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OS X 2 | .DS_Store 3 | 4 | # Xcode 5 | build/ 6 | *.pbxuser 7 | !default.pbxuser 8 | *.mode1v3 9 | !default.mode1v3 10 | *.mode2v3 11 | !default.mode2v3 12 | *.perspectivev3 13 | !default.perspectivev3 14 | xcuserdata/ 15 | *.xccheckout 16 | profile 17 | *.moved-aside 18 | DerivedData 19 | *.hmap 20 | *.ipa 21 | 22 | # Bundler 23 | .bundle 24 | 25 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 26 | # Carthage/Checkouts 27 | 28 | Carthage/Build 29 | 30 | # We recommend against adding the Pods directory to your .gitignore. However 31 | # you should judge for yourself, the pros and cons are mentioned at: 32 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control 33 | # 34 | # Note: if you ignore the Pods directory, make sure to uncomment 35 | # `pod install` in .travis.yml 36 | # 37 | # Pods/ 38 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/ORCharts/ORCharts-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 2.1.7 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /ORCharts/Classes/ORRingChart/ORRingChartConfig.m: -------------------------------------------------------------------------------- 1 | // 2 | // ORRingChartConfig.m 3 | // ORChartView 4 | // 5 | // Created by OrangesAL on 2019/6/1. 6 | // Copyright © 2019 OrangesAL. All rights reserved. 7 | // 8 | 9 | #import "ORRingChartConfig.h" 10 | 11 | @implementation ORRingChartConfig 12 | 13 | - (instancetype)init 14 | { 15 | self = [super init]; 16 | if (self) { 17 | 18 | _clockwise = YES; 19 | _neatInfoLine = NO; 20 | 21 | _startAngle = M_PI * 3 / 2; 22 | _ringLineWidth = 2; 23 | _infoLineWidth = 2; 24 | 25 | _minInfoInset = 0; 26 | _infoLineMargin = 10; 27 | _infoLineInMargin = 10; 28 | _infoLineBreakMargin = 15; 29 | _infoViewMargin = 4; 30 | _pointWidth = 5; 31 | 32 | _animateDuration = 1; 33 | 34 | _ringWidth = 60; 35 | 36 | _animateDuration = 1; 37 | 38 | 39 | } 40 | return self; 41 | } 42 | 43 | @end 44 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-ORCharts_Tests/Pods-ORCharts_Tests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-ORCharts_Example/Pods-ORCharts_Example-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-ORCharts_Tests/Pods-ORCharts_Tests-acknowledgements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreferenceSpecifiers 6 | 7 | 8 | FooterText 9 | This application makes use of the following third party libraries: 10 | Title 11 | Acknowledgements 12 | Type 13 | PSGroupSpecifier 14 | 15 | 16 | FooterText 17 | Generated by CocoaPods - https://cocoapods.org 18 | Title 19 | 20 | Type 21 | PSGroupSpecifier 22 | 23 | 24 | StringsTable 25 | Acknowledgements 26 | Title 27 | Acknowledgements 28 | 29 | 30 | -------------------------------------------------------------------------------- /ORCharts/Classes/ORRingChart/ORRingChartView.h: -------------------------------------------------------------------------------- 1 | // 2 | // ORRingChartView.h 3 | // ORAnimateTest 4 | // 5 | // Created by OrangesAL on 2019/4/24. 6 | // Copyright © 2019 OrangesAL. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "ORRingChartConfig.h" 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | typedef enum : NSUInteger { 15 | ORRingChartStyleRing, 16 | ORRingChartStylePie, 17 | ORRingChartStyleFan, 18 | } ORRingChartStyle; 19 | 20 | 21 | @interface ORRingChartView : UIView 22 | 23 | @property (nonatomic, weak) IBOutlet __nullable id dataSource; 24 | 25 | @property (nonatomic, assign) ORRingChartStyle style; 26 | 27 | @property (nonatomic, strong, readonly) ORRingChartConfig *config; 28 | 29 | - (void)reloadData; 30 | 31 | - (__kindof UIView *)dequeueCenterView; 32 | - (__kindof UIView *)dequeueTopInfoViewAtIndex:(NSInteger)index; 33 | - (__kindof UIView *)dequeueBottomInfoViewAtIndex:(NSInteger)index; 34 | - (__kindof UIView *)dequeueRingInfoViewAtIndex:(NSInteger)index; 35 | 36 | @end 37 | 38 | 39 | NS_ASSUME_NONNULL_END 40 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2019 sunrise_oy@163.com 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /ORCharts/Classes/ORChartUtilities/ORChartUtilities.h: -------------------------------------------------------------------------------- 1 | // 2 | // ORChartUtilities.h 3 | // ORAnimateTest 4 | // 5 | // Created by OrangesAL on 2019/4/24. 6 | // Copyright © 2019 OrangesAL. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | static inline CGFloat ORInterpolation(CGFloat from, CGFloat to, CGFloat ratio){ 14 | return from + (to - from) * ratio; 15 | } 16 | 17 | @interface ORChartUtilities : NSObject 18 | 19 | + (CAAnimation *)or_strokeAnimationWithDurantion:(NSTimeInterval)duration; 20 | 21 | + (CAGradientLayer *)or_grandientLayerWithColors:(NSArray *)colors leftToRight:(BOOL)leftToRight; 22 | + (void)or_configGrandientLayer:(CAGradientLayer *)gradientLayer withColors:(NSArray *)colors leftToRight:(BOOL)leftToRight; 23 | 24 | + (CAShapeLayer *)or_shapelayerWithLineWidth:(CGFloat)lineWidth strokeColor:(UIColor * _Nullable)color; 25 | 26 | + (UIBezierPath *)or_pathWithPoints:(NSArray *)points isCurve:(BOOL)isCurve; 27 | + (UIBezierPath *)or_closePathWithPoints:(NSArray *)points isCurve:(BOOL)isCurve maxY:(CGFloat)maxY; 28 | 29 | 30 | 31 | @end 32 | 33 | @interface UIColor (ORRingConfiger) 34 | 35 | + (UIColor *)or_randomColor; 36 | 37 | @end 38 | 39 | 40 | 41 | 42 | 43 | 44 | NS_ASSUME_NONNULL_END 45 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-ORCharts_Example/Pods-ORCharts_Example-acknowledgements.markdown: -------------------------------------------------------------------------------- 1 | # Acknowledgements 2 | This application makes use of the following third party libraries: 3 | 4 | ## ORCharts 5 | 6 | Copyright (c) 2019 sunrise_oy@163.com 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in 16 | all copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | THE SOFTWARE. 25 | 26 | Generated by CocoaPods - https://cocoapods.org 27 | -------------------------------------------------------------------------------- /ORCharts/Classes/ORLineChart/ORLineChartValue.h: -------------------------------------------------------------------------------- 1 | // 2 | // ORLineChartValue.h 3 | // ORChartsDemo 4 | // 5 | // Created by 欧阳荣 on 2019/7/12. 6 | // Copyright © 2019 欧阳荣. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface ORLineChartHorizontal : NSObject 15 | 16 | @property (nonatomic, assign) CGFloat value; 17 | @property (nonatomic, copy) NSAttributedString *title; 18 | 19 | @end 20 | 21 | @interface ORLineChartValue : NSObject 22 | 23 | @property (nonatomic, assign, readonly) CGFloat max; 24 | @property (nonatomic, assign, readonly) CGFloat min; 25 | @property (nonatomic, assign, readonly) CGFloat middle; 26 | @property (nonatomic, assign, readonly) BOOL isDecimal; 27 | @property (nonatomic, copy, readonly) NSArray * separatedValues;//等分值 由低到高 28 | @property (nonatomic, copy) NSArray * ramValues; 29 | 30 | 31 | 32 | - (instancetype)initWithData:(NSMutableArray *)values; 33 | 34 | - (instancetype)initWithData:(NSArray *)values numberWithSeparate:(NSInteger)separate customMin:(CGFloat)min; 35 | - (instancetype)initWithData:(NSArray *)values numberWithSeparate:(NSInteger)separate; 36 | - (instancetype)initWithHorizontalData:(NSArray *)horizontals numberWithSeparate:(NSInteger)separate; 37 | 38 | @end 39 | 40 | NS_ASSUME_NONNULL_END 41 | -------------------------------------------------------------------------------- /Example/Pods/Local Podspecs/ORCharts.podspec.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ORCharts", 3 | "version": "2.1.7", 4 | "summary": "A lightweight, easy-to-use lightweight library of charts, including ring, pie, pie, line, and graph", 5 | "description": "TODO: A lightweight, easy-to-use lightweight library of charts, including ring, pie, pie, line, and graph", 6 | "homepage": "https://github.com/SunriseOYR/ORCharts", 7 | "license": { 8 | "type": "MIT", 9 | "file": "LICENSE" 10 | }, 11 | "authors": { 12 | "Oranges and lemons": "sunrise_oy@163.com" 13 | }, 14 | "source": { 15 | "git": "https://github.com/SunriseOYR/ORCharts.git", 16 | "tag": "2.1.7" 17 | }, 18 | "platforms": { 19 | "ios": "8.0" 20 | }, 21 | "subspecs": [ 22 | { 23 | "name": "Util", 24 | "platforms": { 25 | "ios": "8.0" 26 | }, 27 | "source_files": "ORCharts/Classes/ORChartUtilities/**/*.{h,m}" 28 | }, 29 | { 30 | "name": "Ring", 31 | "platforms": { 32 | "ios": "8.0" 33 | }, 34 | "source_files": "ORCharts/Classes/ORRingChart/**/*.{h,m}", 35 | "dependencies": { 36 | "ORCharts/Util": [ 37 | 38 | ] 39 | } 40 | }, 41 | { 42 | "name": "Line", 43 | "platforms": { 44 | "ios": "8.0" 45 | }, 46 | "source_files": "ORCharts/Classes/ORLineChart/**/*.{h,m}", 47 | "dependencies": { 48 | "ORCharts/Util": [ 49 | 50 | ] 51 | } 52 | } 53 | ] 54 | } 55 | -------------------------------------------------------------------------------- /Example/ORCharts/ORCharts-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | UILaunchStoryboardName 28 | LaunchScreen 29 | UIMainStoryboardFile 30 | Main 31 | UIRequiredDeviceCapabilities 32 | 33 | armv7 34 | 35 | UISupportedInterfaceOrientations 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationLandscapeLeft 39 | UIInterfaceOrientationLandscapeRight 40 | 41 | UISupportedInterfaceOrientations~ipad 42 | 43 | UIInterfaceOrientationPortrait 44 | UIInterfaceOrientationPortraitUpsideDown 45 | UIInterfaceOrientationLandscapeLeft 46 | UIInterfaceOrientationLandscapeRight 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /Example/ORCharts/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /Example/ORCharts/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /Example/ORCharts/ORAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // ORAppDelegate.m 3 | // ORCharts 4 | // 5 | // Created by sunrise_oy@163.com on 07/14/2019. 6 | // Copyright (c) 2019 sunrise_oy@163.com. All rights reserved. 7 | // 8 | 9 | #import "ORAppDelegate.h" 10 | 11 | @implementation ORAppDelegate 12 | 13 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 14 | { 15 | // Override point for customization after application launch. 16 | return YES; 17 | } 18 | 19 | - (void)applicationWillResignActive:(UIApplication *)application 20 | { 21 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 22 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 23 | } 24 | 25 | - (void)applicationDidEnterBackground:(UIApplication *)application 26 | { 27 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 28 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 29 | } 30 | 31 | - (void)applicationWillEnterForeground:(UIApplication *)application 32 | { 33 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 34 | } 35 | 36 | - (void)applicationDidBecomeActive:(UIApplication *)application 37 | { 38 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application 42 | { 43 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 44 | } 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /ORCharts/Classes/ORRingChart/ORChartUtilities+ORRing.h: -------------------------------------------------------------------------------- 1 | // 2 | // ORChartUtilities+ORRing.h 3 | // ORCharts 4 | // 5 | // Created by OrangesAL on 2020/3/21. 6 | // 7 | 8 | #import "ORChartUtilities.h" 9 | 10 | NS_ASSUME_NONNULL_BEGIN 11 | 12 | @interface ORChartUtilities (ORRing) 13 | 14 | + (UIBezierPath *)or_breakLinePathWithRawRect:(CGRect)rawRect 15 | circleWidth:(CGFloat)circleWidth 16 | ringWidth:(CGFloat)ringWidth 17 | startAngle:(CGFloat)startAngle 18 | endAngle:(CGFloat)endAngle 19 | margin:(CGFloat)margin 20 | inMargin:(CGFloat)inMargin 21 | breakMargin:(CGFloat)breakMargin 22 | neatLine:(BOOL)neatLine 23 | clockWise:(BOOL)clockWise 24 | checkBlock:(CGFloat(^)(CGPoint breakPoint))checkBlock 25 | detailInfoBlock:(void(^)(CGPoint edgePoint, CGPoint endPoint))detailInfoBlock; 26 | 27 | 28 | + (UIBezierPath *)or_ringPathWithRect:(CGRect)rect 29 | startAngle:(CGFloat)startAngle 30 | endAngle:(CGFloat)endAngle 31 | ringWidth:(CGFloat)ringWidth 32 | closckWise:(BOOL)clockWidth 33 | isPie:(BOOL)isPie; 34 | 35 | //Diagonal of an angle 36 | + (CGFloat)or_opposingAngleWithAngle:(CGFloat)angle; 37 | 38 | //plus angle 39 | + (CGFloat)or_angle:(CGFloat)angle byAddAngle:(CGFloat)addAngle; 40 | 41 | + (CGFloat)or_differAngleWithSubtractionAngle:(CGFloat)subtractionAngle subtractedAngle:(CGFloat)subtractedAngle; 42 | 43 | //middle angle 44 | + (CGFloat)or_middleAngleWithStartAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle; 45 | 46 | //The midpoint of the ring at any angle (tangential to the radius) 47 | + (CGPoint)or_centerWithRect:(CGRect)rect angle:(CGFloat)angle ringWidth:(CGFloat)ringWidth; 48 | 49 | //a point on the circle at any angle 50 | + (CGPoint)or_pointWithCircleRect:(CGRect)rect angle:(CGFloat)angle; 51 | 52 | 53 | 54 | @end 55 | 56 | NS_ASSUME_NONNULL_END 57 | -------------------------------------------------------------------------------- /ORCharts/Classes/ORLineChart/ORLineChartConfig.m: -------------------------------------------------------------------------------- 1 | // 2 | // ORLineChartConfig.m 3 | // ORChartView 4 | // 5 | // Created by OrangesAL on 2019/5/4. 6 | // Copyright © 2019年 OrangesAL. All rights reserved. 7 | // 8 | 9 | #import "ORLineChartConfig.h" 10 | 11 | @implementation ORLineChartConfig 12 | 13 | - (instancetype)init 14 | { 15 | self = [super init]; 16 | if (self) { 17 | [self _or_initData]; 18 | } 19 | return self; 20 | } 21 | 22 | - (void)_or_initData { 23 | 24 | _style = ORLineChartStyleSlider; 25 | 26 | _chartLineColor = [UIColor orangeColor]; 27 | _shadowLineColor = [[UIColor lightGrayColor] colorWithAlphaComponent:0.5]; 28 | _bgLineColor = [[UIColor lightGrayColor] colorWithAlphaComponent:0.5]; 29 | 30 | 31 | _showShadowLine = YES; 32 | _showHorizontalBgline = YES; 33 | _showVerticalBgline = YES; 34 | _dottedBGLine = YES; 35 | _isBreakLine = NO; 36 | 37 | _chartLineWidth = 3; 38 | _bglineWidth = 1; 39 | 40 | _bottomInset = 10; 41 | _topInset = 0; 42 | _contentMargin = 10; 43 | _leftWidth = 40; 44 | 45 | _bottomLabelWidth = 50; 46 | _bottomLabelInset = 10; 47 | 48 | _indicatorContentInset = 7; 49 | _indicatorCircleWidth = 13; 50 | _indicatorLineWidth = 0.8; 51 | _animateDuration = 0; 52 | 53 | self.gradientColors = @[[[UIColor redColor] colorWithAlphaComponent:0.3], [[UIColor blueColor] colorWithAlphaComponent:0.3]]; 54 | 55 | } 56 | 57 | - (UIColor *)indicatorTintColor { 58 | if (!_indicatorTintColor) { 59 | _indicatorTintColor = _chartLineColor; 60 | } 61 | return _indicatorTintColor; 62 | } 63 | 64 | - (UIColor *)indicatorLineColor { 65 | if (!_indicatorLineColor) { 66 | _indicatorLineColor = _chartLineColor; 67 | } 68 | return _indicatorLineColor; 69 | } 70 | 71 | - (void)setGradientColors:(NSArray *)gradientColors { 72 | _gradientColors = gradientColors; 73 | NSMutableArray *array = [NSMutableArray arrayWithCapacity:gradientColors.count]; 74 | [gradientColors enumerateObjectsUsingBlock:^(UIColor * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { 75 | [array addObject:(__bridge id)(obj.CGColor)]; 76 | }]; 77 | _gradientCGColors = array.copy; 78 | } 79 | 80 | @end 81 | 82 | 83 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-ORCharts_Example/Pods-ORCharts_Example-acknowledgements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreferenceSpecifiers 6 | 7 | 8 | FooterText 9 | This application makes use of the following third party libraries: 10 | Title 11 | Acknowledgements 12 | Type 13 | PSGroupSpecifier 14 | 15 | 16 | FooterText 17 | Copyright (c) 2019 sunrise_oy@163.com <sunrise_oy@163.com> 18 | 19 | Permission is hereby granted, free of charge, to any person obtaining a copy 20 | of this software and associated documentation files (the "Software"), to deal 21 | in the Software without restriction, including without limitation the rights 22 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 23 | copies of the Software, and to permit persons to whom the Software is 24 | furnished to do so, subject to the following conditions: 25 | 26 | The above copyright notice and this permission notice shall be included in 27 | all copies or substantial portions of the Software. 28 | 29 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 30 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 31 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 32 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 33 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 34 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 35 | THE SOFTWARE. 36 | 37 | License 38 | MIT 39 | Title 40 | ORCharts 41 | Type 42 | PSGroupSpecifier 43 | 44 | 45 | FooterText 46 | Generated by CocoaPods - https://cocoapods.org 47 | Title 48 | 49 | Type 50 | PSGroupSpecifier 51 | 52 | 53 | StringsTable 54 | Acknowledgements 55 | Title 56 | Acknowledgements 57 | 58 | 59 | -------------------------------------------------------------------------------- /ORCharts.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # Be sure to run `pod lib lint ORCharts.podspec' to ensure this is a 3 | # valid spec before submitting. 4 | # 5 | # Any lines starting with a # are optional, but their use is encouraged 6 | # To learn more about a Podspec see https://guides.cocoapods.org/syntax/podspec.html 7 | # 8 | 9 | Pod::Spec.new do |s| 10 | s.name = 'ORCharts' 11 | s.version = '2.1.8' 12 | s.summary = 'A lightweight, easy-to-use lightweight library of charts, including ring, pie, pie, line, and graph' 13 | 14 | # This description is used to generate tags and improve search results. 15 | # * Think: What does it do? Why did you write it? What is the focus? 16 | # * Try to keep it short, snappy and to the point. 17 | # * Write the description between the DESC delimiters below. 18 | # * Finally, don't worry about the indent, CocoaPods strips it! 19 | 20 | s.description = <<-DESC 21 | TODO: A lightweight, easy-to-use lightweight library of charts, including ring, pie, pie, line, and graph 22 | DESC 23 | 24 | s.homepage = 'https://github.com/SunriseOYR/ORCharts' 25 | # s.screenshots = 'www.example.com/screenshots_1', 'www.example.com/screenshots_2' 26 | s.license = { :type => 'MIT', :file => 'LICENSE' } 27 | s.author = { 'Oranges and lemons' => 'sunrise_oy@163.com' } 28 | s.source = { :git => 'https://github.com/SunriseOYR/ORCharts.git', :tag => s.version.to_s } 29 | # s.social_media_url = 'https://twitter.com/' 30 | 31 | s.ios.deployment_target = '8.0' 32 | 33 | # s.source_files = 'ORCharts/Classes/**/*' 34 | 35 | #s.public_header_files = 'ORCharts/Classes/ORCharts.h' 36 | 37 | s.subspec 'Util' do |su| 38 | su.ios.deployment_target = '8.0' 39 | su.source_files = 'ORCharts/Classes/ORChartUtilities/**/*.{h,m}' 40 | end 41 | s.subspec 'Ring' do |ss| 42 | ss.ios.deployment_target = '8.0' 43 | ss.source_files = 'ORCharts/Classes/ORRingChart/**/*.{h,m}' 44 | # ss.public_header_files = 'ORCharts/Classes/ORRingChart/ORRingChartView.h' 45 | ss.dependency 'ORCharts/Util' 46 | end 47 | s.subspec 'Line' do |sss| 48 | sss.ios.deployment_target = '8.0' 49 | sss.source_files = 'ORCharts/Classes/ORLineChart/**/*.{h,m}' 50 | # sss.public_header_files = 'ORCharts/Classes/ORLineChart/ORLineChartView.h' 51 | sss.dependency 'ORCharts/Util' 52 | end 53 | 54 | end 55 | -------------------------------------------------------------------------------- /ORCharts/Classes/ORLineChart/ORLineChartCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // ORLineChartCell.m 3 | // ORChartView 4 | // 5 | // Created by OrangesAL on 2019/5/2. 6 | // Copyright © 2019年 OrangesAL. All rights reserved. 7 | // 8 | 9 | #import "ORLineChartCell.h" 10 | #import "ORLineChartConfig.h" 11 | 12 | @interface ORLineChartCell () 13 | 14 | @property (nonatomic, strong) UILabel *titleLabel; 15 | @property (nonatomic, strong) CAShapeLayer *lineLayer; 16 | 17 | @end 18 | 19 | @implementation ORLineChartCell 20 | 21 | - (instancetype)initWithFrame:(CGRect)frame 22 | { 23 | self = [super initWithFrame:frame]; 24 | if (self) { 25 | [self _or_initUI]; 26 | } 27 | return self; 28 | } 29 | 30 | - (instancetype)initWithCoder:(NSCoder *)coder 31 | { 32 | self = [super initWithCoder:coder]; 33 | if (self) { 34 | [self _or_initUI]; 35 | } 36 | return self; 37 | } 38 | 39 | - (void)_or_initUI { 40 | 41 | self.titleLabel = [UILabel new]; 42 | self.titleLabel.textAlignment = NSTextAlignmentCenter; 43 | 44 | self.lineLayer = [CAShapeLayer layer]; 45 | 46 | [self.contentView.layer addSublayer:self.lineLayer]; 47 | [self.contentView addSubview:self.titleLabel]; 48 | 49 | self.titleLabel.font = [UIFont systemFontOfSize:10]; 50 | self.titleLabel.textColor = [UIColor blackColor]; 51 | } 52 | 53 | - (void)layoutSubviews { 54 | [super layoutSubviews]; 55 | 56 | CGFloat width = self.bounds.size.width; 57 | 58 | CGFloat height = [self.titleLabel.attributedText boundingRectWithSize:CGSizeMake(width, CGFLOAT_MAX) options:NSStringDrawingUsesFontLeading context:nil].size.height; 59 | self.titleLabel.frame = CGRectMake(0, self.bounds.size.height - height , width, height); 60 | 61 | UIBezierPath *path = [UIBezierPath bezierPath]; 62 | [path moveToPoint:CGPointMake(width * 0.5, 0)]; 63 | [path addLineToPoint:CGPointMake(width * 0.5, self.bounds.size.height - height - _config.bottomLabelInset)]; 64 | _lineLayer.path = path.CGPath; 65 | 66 | } 67 | 68 | 69 | - (void)setTitle:(NSAttributedString *)title { 70 | self.titleLabel.attributedText = title; 71 | } 72 | 73 | - (void)setConfig:(ORLineChartConfig *)config { 74 | _config = config; 75 | _lineLayer.strokeColor = _config.bgLineColor.CGColor; 76 | _lineLayer.lineDashPattern = @[@(1.5), @(_config.dottedBGLine ? 3 : 0)]; 77 | _lineLayer.lineWidth = _config.bglineWidth; 78 | _lineLayer.hidden = !_config.showVerticalBgline; 79 | [self setNeedsLayout]; 80 | } 81 | 82 | @end 83 | -------------------------------------------------------------------------------- /ORCharts/Classes/ORLineChart/ORLineChartButton.m: -------------------------------------------------------------------------------- 1 | // 2 | // ORChartControl.m 3 | // ORChartsDemo 4 | // 5 | // Created by 欧阳荣 on 2019/7/12. 6 | // Copyright © 2019 欧阳荣. All rights reserved. 7 | // 8 | 9 | #import "ORLineChartButton.h" 10 | #import 11 | 12 | @implementation ORLineChartButton (EnlargeTouchArea) 13 | 14 | static char topNameKey; 15 | static char rightNameKey; 16 | static char bottomNameKey; 17 | static char leftNameKey; 18 | 19 | - (void)setEnlargeEdgeWithTop:(CGFloat)top 20 | right:(CGFloat)right 21 | bottom:(CGFloat)bottom 22 | left:(CGFloat)left { 23 | objc_setAssociatedObject(self, &topNameKey, [NSNumber numberWithFloat:top], OBJC_ASSOCIATION_COPY_NONATOMIC); 24 | objc_setAssociatedObject(self, &rightNameKey, [NSNumber numberWithFloat:right], OBJC_ASSOCIATION_COPY_NONATOMIC); 25 | objc_setAssociatedObject(self, &bottomNameKey, [NSNumber numberWithFloat:bottom], OBJC_ASSOCIATION_COPY_NONATOMIC); 26 | objc_setAssociatedObject(self, &leftNameKey, [NSNumber numberWithFloat:left], OBJC_ASSOCIATION_COPY_NONATOMIC); 27 | } 28 | 29 | - (CGRect)enlargedRect 30 | { 31 | NSNumber* topEdge = objc_getAssociatedObject(self, &topNameKey); 32 | NSNumber* rightEdge = objc_getAssociatedObject(self, &rightNameKey); 33 | NSNumber* bottomEdge = objc_getAssociatedObject(self, &bottomNameKey); 34 | NSNumber* leftEdge = objc_getAssociatedObject(self, &leftNameKey); 35 | if (topEdge && rightEdge && bottomEdge && leftEdge) 36 | { 37 | return CGRectMake(self.bounds.origin.x - leftEdge.floatValue, 38 | self.bounds.origin.y - topEdge.floatValue, 39 | self.bounds.size.width + leftEdge.floatValue + rightEdge.floatValue, 40 | self.bounds.size.height + topEdge.floatValue + bottomEdge.floatValue); 41 | } 42 | else 43 | { 44 | return self.bounds; 45 | } 46 | } 47 | 48 | - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent*)event 49 | { 50 | CGRect rect = [self enlargedRect]; 51 | if (CGRectEqualToRect(rect, self.bounds)) 52 | { 53 | return [super hitTest:point withEvent:event]; 54 | } 55 | return CGRectContainsPoint(rect, point) ? self : nil; 56 | } 57 | 58 | 59 | @end 60 | 61 | 62 | @implementation ORLineChartButton { 63 | UIColor *_orTintColor; 64 | UIColor *_orBackGroundColor; 65 | } 66 | 67 | - (instancetype)init 68 | { 69 | self = [super init]; 70 | if (self) { 71 | [self setEnlargeEdgeWithTop:20 right:20 bottom:20 left:20]; 72 | } 73 | return self; 74 | } 75 | 76 | - (void)setSelected:(BOOL)selected { 77 | [super setSelected:selected]; 78 | self.backgroundColor = selected ? _orTintColor : _orBackGroundColor; 79 | } 80 | 81 | - (void)or_setTintColor:(UIColor *)tintColor backgroundColor:(UIColor *)backgroundColor { 82 | _orTintColor = tintColor; 83 | _orBackGroundColor = backgroundColor; 84 | self.backgroundColor = self.selected ? _orTintColor : _orBackGroundColor; 85 | self.layer.borderColor = tintColor.CGColor; 86 | } 87 | 88 | @end 89 | -------------------------------------------------------------------------------- /Example/ORCharts/Controller/RingChartVC/ORRingViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ORRingViewController.m 3 | // ORChartView 4 | // 5 | // Created by OrangesAL on 2019/4/27. 6 | // Copyright © 2019年 OrangesAL. All rights reserved. 7 | // 8 | 9 | #import "ORRingViewController.h" 10 | #import "ORRingChartView.h" 11 | 12 | @interface ORRingViewController () 13 | 14 | @property (nonatomic, strong) ORRingChartView *ringChartView; 15 | 16 | @end 17 | 18 | @implementation ORRingViewController 19 | 20 | - (void)viewDidLoad { 21 | [super viewDidLoad]; 22 | // Do any additional setup after loading the view. 23 | 24 | self.view.backgroundColor = [UIColor blackColor]; 25 | 26 | _ringChartView = [[ORRingChartView alloc] initWithFrame:self.view.bounds]; 27 | _ringChartView.dataSource = self; 28 | _ringChartView.config.ringWidth = self.view.bounds.size.width / 4.0; 29 | 30 | [self.view addSubview:_ringChartView]; 31 | 32 | _ringChartView.center = self.view.center; 33 | // _ringChartView.config.clockwise = NO; 34 | } 35 | 36 | - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 37 | _ringChartView.style = arc4random() % 3; 38 | [_ringChartView reloadData]; 39 | } 40 | 41 | - (NSInteger)numberOfRingsOfChartView:(ORRingChartView *)chartView { 42 | return 5; 43 | } 44 | 45 | - (CGFloat)chartView:(ORRingChartView *)chartView valueAtRingIndex:(NSInteger)index { 46 | if (index == 0) { 47 | return 50; 48 | } 49 | return 50; 50 | } 51 | 52 | //- (UIView *)chartView:(ORRingChartView *)chartView viewForTopInfoAtRingIndex:(NSInteger)index { 53 | // 54 | // UILabel *label = [chartView dequeueTopInfoViewAtIndex:index]; 55 | // if (!label) { 56 | // label = [UILabel new]; 57 | // label.font = [UIFont systemFontOfSize:12]; 58 | // label.textColor = [UIColor lightGrayColor]; 59 | // } 60 | // label.text = [NSString stringWithFormat:@"Top %zd", index]; 61 | // [label sizeToFit]; 62 | // return label; 63 | //} 64 | 65 | //- (UIView *)chartView:(ORRingChartView *)chartView viewForBottomInfoAtRingIndex:(NSInteger)index { 66 | // UILabel *label = [chartView dequeueBottomInfoViewAtIndex:index]; 67 | // if (!label) { 68 | // label = [UILabel new]; 69 | // label.font = [UIFont systemFontOfSize:12]; 70 | // label.textColor = [UIColor lightGrayColor]; 71 | // } 72 | // label.text = [NSString stringWithFormat:@"Bot %zd", index]; 73 | // [label sizeToFit]; 74 | // return label; 75 | //} 76 | // 77 | - (UIView *)chartView:(ORRingChartView *)chartView viewForRingInfoAtRingIndex:(NSInteger)index { 78 | UILabel *label = [chartView dequeueRingInfoViewAtIndex:index]; 79 | if (!label) { 80 | label = [UILabel new]; 81 | label.font = [UIFont systemFontOfSize:12]; 82 | label.textColor = [UIColor whiteColor]; 83 | } 84 | label.text = [NSString stringWithFormat:@"R %zd", index]; 85 | [label sizeToFit]; 86 | return label; 87 | } 88 | 89 | - (CGFloat)chartView:(ORRingChartView *)chartView pointWidthForInfoLineAtRingIndex:(NSInteger)index { 90 | return 4; 91 | } 92 | 93 | @end 94 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ORCharts 2 | 3 | [![CI Status](https://img.shields.io/travis/sunrise_oy@163.com/ORCharts.svg?style=flat)](https://travis-ci.org/sunrise_oy@163.com/ORCharts) 4 | [![Version](https://img.shields.io/cocoapods/v/ORCharts.svg?style=flat)](https://cocoapods.org/pods/ORCharts) 5 | [![License](https://img.shields.io/cocoapods/l/ORCharts.svg?style=flat)](https://cocoapods.org/pods/ORCharts) 6 | [![Platform](https://img.shields.io/cocoapods/p/ORCharts.svg?style=flat)](https://cocoapods.org/pods/ORCharts) 7 | 8 | ## Table of contents 9 | * [Screenshots](#screenshots) 10 | * [Installation](#installation) 11 | * [Setup](#setup) 12 | 13 | # Screenshots 14 | 15 | ### RingChart 16 | ![RingChart](https://upload-images.jianshu.io/upload_images/5192751-6b13744cc1b9926d.png?imageMogr2/auto-orient/strip%7CimageView2/2/h/440) 17 | 18 | ### LineChart 19 | | Slider | Control | 20 | |--------------|-------------| 21 | |![Slider](https://upload-images.jianshu.io/upload_images/5192751-3f68f4db547e98e3.gif?imageMogr2/auto-orient/strip)|![Control](https://upload-images.jianshu.io/upload_images/5192751-cc2abfaa9d6a4330.gif?imageMogr2/auto-orient/strip)| 22 | 23 | 24 | ### Example Config 25 | 26 | To run the example project. 27 | 28 | | Ring | Line | 29 | |--------------|-------------| 30 | | ![Config](https://upload-images.jianshu.io/upload_images/5192751-0a70eb88d3829d58.gif?imageMogr2/auto-orient/strip) | ![101.gif](https://upload-images.jianshu.io/upload_images/5192751-00b5849cfb364bc4.gif?imageMogr2/auto-orient/strip) | 31 | 32 | 33 | # Installation 34 | 35 | ### ORCharts 36 | ```ruby 37 | pod 'ORCharts' 38 | ``` 39 | ### Only Ring 40 | 41 | ```ruby 42 | pod 'ORCharts/Ring' 43 | ``` 44 | ### Only Line 45 | 46 | ```ruby 47 | pod 'ORCharts/Line' 48 | ``` 49 | # Setup 50 | 51 | ## Use Interface Builder 52 | 1、 Drag an UIView object to ViewController Scene 53 | 2、 Change the `Custom Class` to `ORLineChartView` or `ORRingChartView`
54 | 3、 Link `dataSource` and `delegate` to the ViewController
55 | 56 | ## Or use code 57 | 58 | ```objc 59 | @property (nonatomic, strong) ORRingChartView *ringChartView; 60 | ``` 61 | ```objc 62 | _ringChartView = [[ORRingChartView alloc] initWithFrame:CGRectMake(0, 0, 375, 375)]; 63 | _ringChartView.dataSource = self; 64 | [self.view addSubview:_ringChartView]; 65 | ``` 66 |
67 | ```objc 68 | @property (nonatomic, strong) ORLineChartView *lineChartView; 69 | ``` 70 | ```objc 71 | _lineChartView = [[ORLineChartView alloc] initWithFrame:CGRectMake(0, 0, 375, 350)]; 72 | _lineChartView.dataSource = self; 73 | _lineChartView.delegate = self; 74 | [self.view addSubview:_lineChartView]; 75 | ``` 76 |
77 | 78 | ## reloadData 79 | reloadData when data or config changed, see more usage and config in example 80 | 81 | ```objc 82 | [_ringChartView reloadData]; 83 | ``` 84 | ```objc 85 | [_lineChartView reloadData]; 86 | ``` 87 | ## dataSource && delegate && config 88 | Refer to the Example Or Click the link below 89 | 90 | * [ORCharts:Ring](https://www.jianshu.com/p/317a79890984) 91 | * [ORCharts:Line](https://www.jianshu.com/p/a571ae110ba5) 92 | 93 | 94 | 95 | ## License 96 | 97 | ORCharts is available under the MIT license. See the LICENSE file for more info. 98 | 99 | ### [中文简书](https://www.jianshu.com/p/6f65bf7dfbbf) 100 | -------------------------------------------------------------------------------- /ORCharts/Classes/ORRingChart/ORRingChartConfig.h: -------------------------------------------------------------------------------- 1 | // 2 | // ORRingChartConfig.h 3 | // ORChartView 4 | // 5 | // Created by OrangesAL on 2019/6/1. 6 | // Copyright © 2019 OrangesAL. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | 15 | @interface ORRingChartConfig : NSObject 16 | 17 | //The direction in chart. default YES 18 | @property (nonatomic, assign) BOOL clockwise; 19 | 20 | //neatInfoLine. if YES infoLines alignment chartview, if NO infoLines has same width. default NO 21 | @property (nonatomic, assign) BOOL neatInfoLine; 22 | 23 | //The starting angle of the chart. default M_PI * 3 / 2 24 | @property (nonatomic, assign) CGFloat startAngle; 25 | 26 | //ringLine width. default 2 27 | @property (nonatomic, assign) CGFloat ringLineWidth; 28 | 29 | //infoLine width. default 2 30 | @property (nonatomic, assign) CGFloat infoLineWidth; 31 | 32 | //minInset Of infoView. This value will make the infoView show wider. default 0 33 | @property (nonatomic, assign) CGFloat minInfoInset; 34 | 35 | 36 | //the margin between infoline and chartView. default 10 37 | @property (nonatomic, assign) CGFloat infoLineMargin; 38 | 39 | //the margin between infoline and inner circle. default 10 40 | @property (nonatomic, assign) CGFloat infoLineInMargin; 41 | 42 | //distance from the turning point to the infoline. default 15 43 | @property (nonatomic, assign) CGFloat infoLineBreakMargin; 44 | 45 | //the margin between infoView and infoView. default 5 46 | @property (nonatomic, assign) CGFloat infoViewMargin; 47 | 48 | //infoline pointWidth default 5 49 | @property (nonatomic, assign) CGFloat pointWidth; 50 | 51 | //The duration of animation, If set to 0, there is no animation. default 1 52 | @property (nonatomic, assign) NSTimeInterval animateDuration; 53 | 54 | /* 55 | * if _dataSource responds To Selector 'viewForRingCenterOfChartView:' OR style != ORChartStyleRing. This value will be invalid 56 | */ 57 | @property (nonatomic, assign) CGFloat ringWidth; 58 | 59 | @end 60 | 61 | @class ORRingChartView; 62 | 63 | @protocol ORRingChartViewDatasource 64 | 65 | @required 66 | 67 | //return the number of values. 68 | - (NSInteger)numberOfRingsOfChartView:(ORRingChartView *)chartView; 69 | 70 | //return the value at index 71 | - (CGFloat)chartView:(ORRingChartView *)chartView valueAtRingIndex:(NSInteger)index; 72 | 73 | @optional 74 | 75 | //return the graident colors at index 76 | - (NSArray *)chartView:(ORRingChartView *)chartView graidentColorsAtRingIndex:(NSInteger)index; 77 | 78 | //return the ring line color at index 79 | - (UIColor *)chartView:(ORRingChartView *)chartView lineColorForRingAtRingIndex:(NSInteger)index; 80 | 81 | //return the info line color at index 82 | - (UIColor *)chartView:(ORRingChartView *)chartView lineColorForInfoLineAtRingIndex:(NSInteger)index; 83 | 84 | //return the centerView. The view will be displayed on the top layer, you need to set the bounds 85 | - (UIView *)viewForRingCenterOfChartView:(ORRingChartView *)chartView; 86 | 87 | //return the top info view. you need to set the bounds 88 | - (UIView *)chartView:(ORRingChartView *)chartView viewForTopInfoAtRingIndex:(NSInteger)index; 89 | 90 | //return the bottom info view. you need to set the bounds 91 | - (UIView *)chartView:(ORRingChartView *)chartView viewForBottomInfoAtRingIndex:(NSInteger)index; 92 | 93 | //return the ring info view. you need to set the bounds 94 | - (UIView *)chartView:(ORRingChartView *)chartView viewForRingInfoAtRingIndex:(NSInteger)index; 95 | 96 | 97 | @end 98 | 99 | 100 | 101 | 102 | NS_ASSUME_NONNULL_END 103 | -------------------------------------------------------------------------------- /ORCharts/Classes/ORChartUtilities/ORChartUtilities.m: -------------------------------------------------------------------------------- 1 | // 2 | // ORChartUtilities.m 3 | // ORAnimateTest 4 | // 5 | // Created by OrangesAL on 2019/4/24. 6 | // Copyright © 2019 OrangesAL. All rights reserved. 7 | // 8 | 9 | #import "ORChartUtilities.h" 10 | 11 | @implementation ORChartUtilities 12 | 13 | + (CAAnimation *)or_strokeAnimationWithDurantion:(NSTimeInterval)duration { 14 | CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"]; 15 | animation.fromValue = @(0.0); 16 | animation.toValue = @(1.0); 17 | animation.duration = duration; 18 | return animation; 19 | } 20 | 21 | + (CAGradientLayer *)or_grandientLayerWithColors:(NSArray *)colors leftToRight:(BOOL)leftToRight { 22 | 23 | CAGradientLayer *gradientLayer = [CAGradientLayer layer]; 24 | 25 | [self or_configGrandientLayer:gradientLayer withColors:colors leftToRight:leftToRight]; 26 | return gradientLayer; 27 | } 28 | 29 | + (void)or_configGrandientLayer:(CAGradientLayer *)gradientLayer withColors:(NSArray *)colors leftToRight:(BOOL)leftToRight { 30 | 31 | if (leftToRight) { 32 | gradientLayer.startPoint = CGPointMake(0, 0); 33 | gradientLayer.endPoint = CGPointMake(1, 1); 34 | }else { 35 | gradientLayer.startPoint = CGPointMake(1, 0); 36 | gradientLayer.endPoint = CGPointMake(0, 1); 37 | } 38 | 39 | if (colors.count > 0) { 40 | gradientLayer.colors = @[(__bridge id)colors.firstObject.CGColor, (__bridge id)colors.lastObject.CGColor]; 41 | } 42 | } 43 | 44 | + (CAShapeLayer *)or_shapelayerWithLineWidth:(CGFloat)lineWidth strokeColor:(UIColor *)color { 45 | 46 | CAShapeLayer *shapeLayer = [CAShapeLayer layer]; 47 | 48 | shapeLayer.lineWidth = lineWidth; 49 | shapeLayer.lineCap = kCALineCapRound; 50 | shapeLayer.lineJoin = kCALineJoinRound; 51 | if (color) { 52 | shapeLayer.strokeColor = color.CGColor; 53 | } 54 | shapeLayer.fillColor = [UIColor clearColor].CGColor; 55 | return shapeLayer; 56 | } 57 | 58 | 59 | + (UIBezierPath *)or_pathWithPoints:(NSArray *)points isCurve:(BOOL)isCurve { 60 | return [self or_closePathWithPoints:points isCurve:isCurve maxY:-10086]; 61 | } 62 | 63 | + (UIBezierPath *)or_closePathWithPoints:(NSArray *)points isCurve:(BOOL)isCurve maxY:(CGFloat)maxY { 64 | 65 | if (points.count <= 0) { 66 | return nil; 67 | } 68 | 69 | BOOL isClose = maxY != -10086; 70 | 71 | CGPoint p1 = [points.firstObject CGPointValue]; 72 | 73 | UIBezierPath *beizer = [UIBezierPath bezierPath]; 74 | 75 | if (isClose) { 76 | [beizer moveToPoint:CGPointMake(p1.x, maxY)]; 77 | [beizer addLineToPoint:p1]; 78 | }else { 79 | [beizer moveToPoint:p1]; 80 | } 81 | 82 | for (int i = 1;i *)values { 19 | self = [super init]; 20 | if (self) { 21 | 22 | if (values.count <= 1) { 23 | _separatedValues = values; 24 | _max = values.firstObject.doubleValue; 25 | _min = _max; 26 | _middle = _min; 27 | _isDecimal = YES; 28 | _isDecimal = _max < 10; 29 | return self; 30 | } 31 | 32 | BOOL bFinish = YES; //是否发生数据交换 33 | for (NSInteger i = 1; i<= values.count && bFinish; i++) { 34 | bFinish = NO; 35 | for (NSInteger y = values.count-1; y>=i; y--) { 36 | if ([values[y] doubleValue] < [values[y - 1] doubleValue]) { 37 | [values exchangeObjectAtIndex:y-1 withObjectAtIndex:y]; 38 | bFinish = YES; 39 | } 40 | } 41 | } 42 | _separatedValues = values.copy; 43 | _max = values.lastObject.doubleValue; 44 | _min = values.firstObject.doubleValue;; 45 | _middle = (_max - _min) / 2.0; 46 | _isDecimal = (_max - _min) < 10; 47 | } 48 | return self; 49 | } 50 | 51 | - (instancetype)initWithData:(NSArray *)values numberWithSeparate:(NSInteger)separate customMin:(CGFloat)min 52 | { 53 | self = [super init]; 54 | if (self) { 55 | _separate = separate; 56 | _min = min; 57 | self.ramValues = values; 58 | } 59 | return self; 60 | } 61 | 62 | - (instancetype)initWithData:(NSArray *)values numberWithSeparate:(NSInteger)separate { 63 | return [self initWithData:values numberWithSeparate:separate customMin:CGFLOAT_MAX]; 64 | } 65 | 66 | - (instancetype)init { 67 | self = [super init]; 68 | if (self) { 69 | _separate = 5; 70 | } 71 | return self; 72 | } 73 | 74 | - (void)setRamValues:(NSArray *)ramValues { 75 | _ramValues = ramValues; 76 | [self valueSortedWithRamData:ramValues numberWithSeparate:_separate]; 77 | } 78 | 79 | - (void)valueSortedWithRamData:(NSArray *)data numberWithSeparate:(NSInteger)separate { 80 | 81 | __block CGFloat max = [data.firstObject floatValue]; 82 | __block CGFloat min = [data.firstObject floatValue]; 83 | 84 | [data enumerateObjectsUsingBlock:^(NSNumber * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { 85 | if (obj.doubleValue > max) { 86 | max = obj.doubleValue; 87 | } 88 | if (obj.doubleValue < min) { 89 | min = obj.floatValue; 90 | } 91 | }]; 92 | 93 | _middle = (max - min) / 2.0; 94 | 95 | NSMutableArray *array = [NSMutableArray array]; 96 | CGFloat average = 0; 97 | 98 | if ((max - min) > 10) { 99 | _isDecimal = NO; 100 | min = floorf(min / 10.0) * 10; 101 | max = ceilf(max / 10.0) * 10; 102 | average = ceilf((max - min) / (separate - 1.0)); 103 | }else { 104 | average = (max - min) / (separate - 2.0); 105 | _isDecimal = YES; 106 | } 107 | 108 | for (int i = 0; i < separate; i ++) { 109 | [array addObject:@(min + i * average)]; 110 | } 111 | 112 | _min = min; 113 | _max = [array.lastObject floatValue]; 114 | _separatedValues = [array copy]; 115 | } 116 | 117 | - (instancetype)initWithHorizontalData:(NSArray *)horizontals numberWithSeparate:(NSInteger)separate { 118 | 119 | NSMutableArray *number = [NSMutableArray arrayWithCapacity:horizontals.count]; 120 | [horizontals enumerateObjectsUsingBlock:^(ORLineChartHorizontal * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { 121 | [number addObject:@(obj.value)]; 122 | }]; 123 | return [self initWithData:number numberWithSeparate:separate]; 124 | } 125 | 126 | @end 127 | -------------------------------------------------------------------------------- /Example/ORCharts.xcodeproj/xcshareddata/xcschemes/ORCharts-Example.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 64 | 66 | 72 | 73 | 74 | 75 | 76 | 77 | 83 | 85 | 91 | 92 | 93 | 94 | 96 | 97 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /Example/ORCharts/Controller/LineChartVC/ORLineViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ORLineChartViewController.m 3 | // ORChartView 4 | // 5 | // Created by OrangesAL on 2019/5/4. 6 | // Copyright © 2019年 OrangesAL. All rights reserved. 7 | // 8 | 9 | #import "ORLineViewController.h" 10 | #import "ORLineChartView.h" 11 | 12 | @interface ORLineViewController () 13 | 14 | @property (nonatomic, strong) NSArray *datas; 15 | @property (nonatomic, strong) ORLineChartView *lineChartView; 16 | 17 | @end 18 | 19 | @implementation ORLineViewController 20 | 21 | - (void)viewDidLoad { 22 | [super viewDidLoad]; 23 | // Do any additional setup after loading the view. 24 | 25 | self.view.backgroundColor = [UIColor blackColor]; 26 | 27 | _datas = @[@(0.12), @(0.2),@(0.497),@(0.274),@(0.37),@(0.22),@(0.297),@(0.274),@(0.358),@(0.235),@(0.18),@(0.8),@(0.5),@(0.12),@(0.163)]; 28 | // _datas = @[@(0.12)]; 29 | // _datas = @[@(0), @(2), @(3), @(14)]; 30 | 31 | 32 | _lineChartView = [[ORLineChartView alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, 350)]; 33 | _lineChartView.config.gradientLocations = @[@(0.8), @(0.9)]; 34 | 35 | _lineChartView.defaultSelectIndex = 1; 36 | 37 | _lineChartView.dataSource = self; 38 | _lineChartView.delegate = self; 39 | 40 | 41 | [self.view addSubview:_lineChartView]; 42 | _lineChartView.center = self.view.center; 43 | 44 | } 45 | 46 | - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 47 | 48 | // _lineChartView.config.style = _lineChartView.config.style == ORLineChartStyleSlider ? ORLineChartStyleControl : ORLineChartStyleSlider; 49 | [_lineChartView reloadData]; 50 | 51 | // [_lineChartView showDataAtIndex:arc4random() % _datas.count animated:YES]; 52 | 53 | return; 54 | 55 | /* 56 | 随机数据源 57 | 随机样式 58 | 随机颜色 59 | */ 60 | 61 | NSMutableArray *array = [NSMutableArray array]; 62 | 63 | for (int i = 0; i < 20; i ++) { 64 | NSInteger num = arc4random() % 1000; 65 | [array addObject:[NSString stringWithFormat:@"%ld",(long)num]]; 66 | } 67 | 68 | _datas = [array copy]; 69 | 70 | _lineChartView.config.style = _lineChartView.config.style == ORLineChartStyleSlider ? ORLineChartStyleControl : ORLineChartStyleSlider; 71 | _lineChartView.config.gradientColors = @[[[UIColor or_randomColor] colorWithAlphaComponent:0.3],[[UIColor or_randomColor] colorWithAlphaComponent:0.3]]; 72 | 73 | [_lineChartView reloadData]; 74 | } 75 | 76 | 77 | #pragma mark - ORLineChartViewDataSource 78 | - (NSInteger)numberOfHorizontalDataOfChartView:(ORLineChartView *)chartView { 79 | return _datas.count; 80 | } 81 | 82 | - (CGFloat)chartView:(ORLineChartView *)chartView valueForHorizontalAtIndex:(NSInteger)index { 83 | return [_datas[index] doubleValue]; 84 | } 85 | 86 | - (NSInteger)numberOfVerticalLinesOfChartView:(ORLineChartView *)chartView { 87 | return 6; 88 | } 89 | 90 | - (NSAttributedString *)chartView:(ORLineChartView *)chartView attributedStringForIndicaterAtIndex:(NSInteger)index { 91 | NSAttributedString *string = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"value: %g", [_datas[index] doubleValue]]]; 92 | return string; 93 | } 94 | 95 | - (NSDictionary *)labelAttrbutesForVerticalOfChartView:(ORLineChartView *)chartView { 96 | return @{NSFontAttributeName : [UIFont systemFontOfSize:12], NSForegroundColorAttributeName : [UIColor redColor]}; 97 | } 98 | 99 | - (NSDictionary *)labelAttrbutesForHorizontalOfChartView:(ORLineChartView *)chartView { 100 | return @{NSFontAttributeName : [UIFont systemFontOfSize:12], NSForegroundColorAttributeName : [UIColor blueColor]}; 101 | } 102 | 103 | ////custom left values 104 | //- (CGFloat)chartView:(ORLineChartView *)chartView valueOfVerticalSeparateAtIndex:(NSInteger)index { 105 | // NSArray *number1 = @[@(0),@(0.2),@(0.4),@(0.6),@(0.8),@(0.10)]; 106 | // return [number1[index] doubleValue]; 107 | //} 108 | 109 | #pragma mark - ORLineChartViewDelegate 110 | - (void)chartView:(ORLineChartView *)chartView didSelectValueAtIndex:(NSInteger)index { 111 | NSLog(@"did select index %ld and value is %g", index, [_datas[index] doubleValue]); 112 | } 113 | 114 | - (void)chartView:(ORLineChartView *)chartView indicatorDidChangeValueAtIndex:(NSInteger)index { 115 | NSLog(@"indicater did change index %ld and value is %g", index, [_datas[index] doubleValue]); 116 | } 117 | 118 | @end 119 | -------------------------------------------------------------------------------- /ORCharts/Classes/ORLineChart/ORLineChartConfig.h: -------------------------------------------------------------------------------- 1 | // 2 | // ORLineChartConfig.h 3 | // ORChartView 4 | // 5 | // Created by OrangesAL on 2019/5/4. 6 | // Copyright © 2019年 OrangesAL. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import "ORChartUtilities.h" 12 | 13 | NS_ASSUME_NONNULL_BEGIN 14 | 15 | typedef enum : NSUInteger { 16 | ORLineChartStyleSlider, 17 | ORLineChartStyleControl, 18 | } ORLineChartStyle; 19 | 20 | @interface ORLineChartConfig : NSObject 21 | 22 | @property (nonatomic, assign) ORLineChartStyle style; 23 | 24 | //chartLine,shadowLine width. default 3 25 | @property (nonatomic, assign) CGFloat chartLineWidth; 26 | 27 | //bgLine width. default 1 28 | @property (nonatomic, assign) CGFloat bglineWidth; 29 | 30 | //color of chartLine. default orange 31 | @property (nonatomic, copy) UIColor *chartLineColor; 32 | 33 | //color of shadowLine. default lightGray alpha 0.5 34 | @property (nonatomic, copy) UIColor *shadowLineColor; 35 | 36 | //color of shadowLine. default lightGray alpha 0.5 37 | @property (nonatomic, copy) UIColor *bgLineColor; 38 | 39 | //gradientColors of chart. default red alpha 0.3 and blue alpha 0.3 40 | @property (nonatomic, copy) NSArray *gradientColors; 41 | //locations of gradientColor. default nil 42 | @property (nonatomic, copy) NSArray *gradientLocations; 43 | @property (nonatomic, copy, readonly) NSArray *gradientCGColors; 44 | 45 | //bottom inset of chartView. default 10 46 | @property (nonatomic, assign) CGFloat bottomInset; 47 | 48 | //top inset of chartView. default 0 49 | @property (nonatomic, assign) CGFloat topInset; 50 | 51 | //margin of chart content. default 10 52 | @property (nonatomic, assign) CGFloat contentMargin; 53 | 54 | //left info width. default 40 55 | @property (nonatomic, assign) CGFloat leftWidth; 56 | 57 | //bottom label width. default 50 58 | @property (nonatomic, assign) CGFloat bottomLabelWidth; 59 | 60 | //inset of bottom label and chart content. default 10 61 | @property (nonatomic, assign) CGFloat bottomLabelInset; 62 | 63 | 64 | //show shadow line. default YES 65 | @property (nonatomic, assign) BOOL showShadowLine; 66 | //show vertical bgLine. default YES 67 | @property (nonatomic, assign) BOOL showVerticalBgline; 68 | //show horizontal bgLine. default YES 69 | @property (nonatomic, assign) BOOL showHorizontalBgline; 70 | //bgLine is dotted. default YES 71 | @property (nonatomic, assign) BOOL dottedBGLine; 72 | //bgLine is break. default NO 73 | @property (nonatomic, assign) BOOL isBreakLine; 74 | 75 | 76 | //indicator content inset. default 7 77 | @property (nonatomic, assign) CGFloat indicatorContentInset; 78 | //indicator circle width. default 13 79 | @property (nonatomic, assign) CGFloat indicatorCircleWidth; 80 | //indicator line width. default 0.8 81 | @property (nonatomic, assign) CGFloat indicatorLineWidth; 82 | //tint color of indicator. default chartLineColor 83 | @property (nonatomic, copy) UIColor * indicatorTintColor; 84 | //line color of indicator. default chartLineColor 85 | @property (nonatomic, copy) UIColor * indicatorLineColor; 86 | 87 | 88 | //The duration of animation, If set to 0, there is no animation. default 0 89 | @property (nonatomic, assign) NSTimeInterval animateDuration; 90 | 91 | 92 | //image of indicator control. only style == ORLineChartStyleControl. default nil 93 | @property (nonatomic, strong) UIImage *indicatorControlImage; 94 | //selected image of indicator control. only style == ORLineChartStyleControl. default nil 95 | @property (nonatomic, strong) UIImage *indicatorControlSelectedImage; 96 | 97 | @end 98 | 99 | @class ORLineChartView; 100 | 101 | @protocol ORLineChartViewDataSource 102 | 103 | @required 104 | 105 | //return the number of values. 106 | - (NSInteger)numberOfHorizontalDataOfChartView:(ORLineChartView *)chartView; 107 | 108 | //return the value at index 109 | - (CGFloat)chartView:(ORLineChartView *)chartView valueForHorizontalAtIndex:(NSInteger)index; 110 | 111 | @optional 112 | 113 | //return the number of lines. default 5 114 | - (NSInteger)numberOfVerticalLinesOfChartView:(ORLineChartView *)chartView; 115 | 116 | //return the verticalValue at index 117 | - (CGFloat)chartView:(ORLineChartView *)chartView valueOfVerticalSeparateAtIndex:(NSInteger)index; 118 | 119 | //return the title of horizontal label. 120 | - (NSString *)chartView:(ORLineChartView *)chartView titleForHorizontalAtIndex:(NSInteger)index; 121 | 122 | //return the horizontal label attrbutes. 123 | - (NSDictionary *)labelAttrbutesForHorizontalOfChartView:(ORLineChartView *)chartView; 124 | 125 | //return the vertical label attrbutes. 126 | - (NSDictionary *)labelAttrbutesForVerticalOfChartView:(ORLineChartView *)chartView; 127 | 128 | //return the attributed string of indicater. only style == ORLineChartStyleSlider 129 | - (NSAttributedString *)chartView:(ORLineChartView *)chartView attributedStringForIndicaterAtIndex:(NSInteger)index; 130 | 131 | @end 132 | 133 | 134 | @protocol ORLineChartViewDelegate 135 | 136 | @optional 137 | 138 | //Called after the user did select the value. only style == ORLineChartStyleControl 139 | - (void)chartView:(ORLineChartView *)chartView didSelectValueAtIndex:(NSInteger)index; 140 | 141 | //Called after the indicator did change the value. only style == ORLineChartStyleSlider 142 | - (void)chartView:(ORLineChartView *)chartView indicatorDidChangeValueAtIndex:(NSInteger)index; 143 | 144 | @end 145 | 146 | 147 | 148 | NS_ASSUME_NONNULL_END 149 | -------------------------------------------------------------------------------- /Example/ORCharts/Controller/RingChartVC/ORRingMoreViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ORRingMoreViewController.m 3 | // ORChartView 4 | // 5 | // Created by OrangesAL on 2019/6/3. 6 | // Copyright © 2019 OrangesAL. All rights reserved. 7 | // 8 | 9 | #import "ORRingMoreViewController.h" 10 | #import "ORRingChartView.h" 11 | 12 | @interface ORRingMoreViewController () 13 | 14 | @property (weak, nonatomic) IBOutlet ORRingChartView *ringChart; 15 | @property (nonatomic, strong) NSArray *datasource; 16 | @property (nonatomic, strong) NSArray *graidentColors; 17 | 18 | @property (weak, nonatomic) IBOutlet UILabel *startAngleLabel; 19 | @property (weak, nonatomic) IBOutlet UILabel *ringLineWidthLabel; 20 | @property (weak, nonatomic) IBOutlet UILabel *infoLineWidthLabel; 21 | @property (weak, nonatomic) IBOutlet UILabel *minInfoInsetLabel; 22 | @property (weak, nonatomic) IBOutlet UILabel *infoLineMarginLabel; 23 | @property (weak, nonatomic) IBOutlet UILabel *infoLineInMarginLabel; 24 | @property (weak, nonatomic) IBOutlet UILabel *infoLineBreakMarginLabel; 25 | @property (weak, nonatomic) IBOutlet UILabel *infoViewMarginLabel; 26 | @property (weak, nonatomic) IBOutlet UILabel *pointWidthLabel; 27 | @property (weak, nonatomic) IBOutlet UILabel *animateDurationLabel; 28 | 29 | @property (weak, nonatomic) IBOutlet NSLayoutConstraint *bottowLayout; 30 | 31 | @property (nonatomic, assign) BOOL clockwise; 32 | @property (nonatomic, assign) BOOL neatInfoLine; 33 | 34 | @property (nonatomic, assign) ORRingChartStyle style; 35 | 36 | @end 37 | 38 | @implementation ORRingMoreViewController 39 | 40 | - (void)viewDidLoad { 41 | [super viewDidLoad]; 42 | // Do any additional setup after loading the view. 43 | _datasource = @[@(12.4),@(23.1),@(37),@(12),@(18.6),@(8.7),@(12.2),@(16.5)]; 44 | _graidentColors = @[@[[UIColor redColor]], 45 | @[[UIColor orangeColor]], 46 | @[[UIColor yellowColor]], 47 | @[[UIColor greenColor]], 48 | @[[UIColor cyanColor]], 49 | @[[UIColor blueColor]], 50 | @[[UIColor purpleColor]], 51 | @[[UIColor brownColor]]]; 52 | 53 | 54 | [_ringChart reloadData]; 55 | 56 | 57 | _clockwise = YES; 58 | _bottowLayout.constant = -350; 59 | [self.view layoutIfNeeded]; 60 | } 61 | - (IBAction)action_showConfig:(id)sender { 62 | 63 | _bottowLayout.constant == 0 ? (_bottowLayout.constant = -350) : (_bottowLayout.constant = 0); 64 | [UIView animateWithDuration:0.25 animations:^{ 65 | [self.view layoutIfNeeded]; 66 | }]; 67 | } 68 | 69 | #pragma mark -- config 70 | - (IBAction)action_slider:(UISlider *)sender { 71 | 72 | switch (sender.tag - 100) { 73 | case 0: 74 | _startAngleLabel.text = [NSString stringWithFormat:@"%.0f",sender.value]; 75 | break; 76 | case 1: 77 | _ringLineWidthLabel.text = [NSString stringWithFormat:@"%.1f",sender.value]; 78 | break; 79 | case 2: 80 | _infoLineWidthLabel.text = [NSString stringWithFormat:@"%.1f",sender.value]; 81 | break; 82 | case 3: 83 | _minInfoInsetLabel.text = [NSString stringWithFormat:@"%.1f",sender.value]; 84 | break; 85 | case 4: 86 | _infoLineMarginLabel.text = [NSString stringWithFormat:@"%.1f",sender.value]; 87 | break; 88 | case 5: 89 | _infoLineInMarginLabel.text = [NSString stringWithFormat:@"%.1f",sender.value]; 90 | break; 91 | case 6: 92 | _infoLineBreakMarginLabel.text = [NSString stringWithFormat:@"%.1f",sender.value]; 93 | break; 94 | case 7: 95 | _infoViewMarginLabel.text = [NSString stringWithFormat:@"%.1f",sender.value]; 96 | break; 97 | case 8: 98 | _pointWidthLabel.text = [NSString stringWithFormat:@"%.1f",sender.value]; 99 | break; 100 | case 9: 101 | _animateDurationLabel.text = [NSString stringWithFormat:@"%.1f",sender.value]; 102 | break; 103 | default: 104 | break; 105 | } 106 | 107 | } 108 | 109 | 110 | - (IBAction)action_clockwise:(UISwitch *)sender { 111 | 112 | if (sender.tag == 200) { 113 | _clockwise = sender.isOn; 114 | return; 115 | } 116 | _neatInfoLine = sender.isOn; 117 | } 118 | 119 | - (IBAction)action_chartStyle:(UISegmentedControl *)sender { 120 | _style = sender.selectedSegmentIndex; 121 | } 122 | 123 | - (IBAction)action_cancel:(id)sender { 124 | _bottowLayout.constant = -350; 125 | [UIView animateWithDuration:0.25 animations:^{ 126 | [self.view layoutIfNeeded]; 127 | }]; 128 | } 129 | - (IBAction)action_config:(id)sender { 130 | 131 | _ringChart.style = _style; 132 | _ringChart.config.clockwise = _clockwise; 133 | _ringChart.config.neatInfoLine = _neatInfoLine; 134 | 135 | _ringChart.config.startAngle = [_startAngleLabel.text floatValue] * M_PI / 180.0; 136 | _ringChart.config.ringLineWidth = [_ringLineWidthLabel.text floatValue]; 137 | _ringChart.config.infoLineWidth = [_infoLineWidthLabel.text floatValue]; 138 | _ringChart.config.minInfoInset = [_minInfoInsetLabel.text floatValue]; 139 | 140 | _ringChart.config.infoLineMargin = [_infoLineMarginLabel.text floatValue]; 141 | _ringChart.config.infoLineInMargin = [_infoLineInMarginLabel.text floatValue]; 142 | _ringChart.config.infoLineBreakMargin = [_infoLineBreakMarginLabel.text floatValue]; 143 | _ringChart.config.infoViewMargin = [_infoViewMarginLabel.text floatValue]; 144 | _ringChart.config.pointWidth = [_pointWidthLabel.text floatValue]; 145 | 146 | _ringChart.config.animateDuration = [_animateDurationLabel.text floatValue]; 147 | 148 | [_ringChart reloadData]; 149 | 150 | } 151 | 152 | #pragma mark -- ORRingChartViewDatasource 153 | 154 | - (NSInteger)numberOfRingsOfChartView:(ORRingChartView *)chartView { 155 | return _datasource.count; 156 | } 157 | 158 | - (CGFloat)chartView:(ORRingChartView *)chartView valueAtRingIndex:(NSInteger)index { 159 | return [_datasource[index] floatValue]; 160 | } 161 | 162 | - (NSArray *)chartView:(ORRingChartView *)chartView graidentColorsAtRingIndex:(NSInteger)index { 163 | return _graidentColors[index]; 164 | } 165 | 166 | - (UIView *)viewForRingCenterOfChartView:(ORRingChartView *)chartView { 167 | UILabel *label = [chartView dequeueCenterView]; 168 | if (!label) { 169 | label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 90, 90)]; 170 | label.layer.cornerRadius = 45; 171 | label.clipsToBounds = YES; 172 | label.textAlignment = NSTextAlignmentCenter; 173 | label.font = [UIFont boldSystemFontOfSize:18]; 174 | label.textColor = [UIColor whiteColor]; 175 | label.text = @"140.50"; 176 | } 177 | return label; 178 | } 179 | 180 | - (UIView *)chartView:(ORRingChartView *)chartView viewForTopInfoAtRingIndex:(NSInteger)index { 181 | UILabel *label = [chartView dequeueTopInfoViewAtIndex:index]; 182 | if (!label) { 183 | label = [UILabel new]; 184 | label.font = [UIFont systemFontOfSize:11]; 185 | label.textColor = [UIColor redColor]; 186 | } 187 | label.text = [NSString stringWithFormat:@"%.02f", [_datasource[index] floatValue]]; 188 | [label sizeToFit]; 189 | return label; 190 | } 191 | 192 | - (UIView *)chartView:(ORRingChartView *)chartView viewForBottomInfoAtRingIndex:(NSInteger)index { 193 | UILabel *label = [chartView dequeueBottomInfoViewAtIndex:index]; 194 | if (!label) { 195 | label = [UILabel new]; 196 | label.font = [UIFont systemFontOfSize:11]; 197 | label.textColor = [UIColor lightGrayColor]; 198 | } 199 | label.text = [NSString stringWithFormat:@"Index:%zd", index]; 200 | [label sizeToFit]; 201 | return label; 202 | } 203 | 204 | 205 | 206 | 207 | @end 208 | -------------------------------------------------------------------------------- /ORCharts/Classes/ORRingChart/ORChartUtilities+ORRing.m: -------------------------------------------------------------------------------- 1 | // 2 | // ORChartUtilities+ORRing.m 3 | // ORCharts 4 | // 5 | // Created by OrangesAL on 2020/3/21. 6 | // 7 | 8 | #import "ORChartUtilities+ORRing.h" 9 | 10 | @implementation ORChartUtilities (ORRing) 11 | 12 | + (UIBezierPath *)or_breakLinePathWithRawRect:(CGRect)rawRect circleWidth:(CGFloat)circleWidth ringWidth:(CGFloat)ringWidth startAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle margin:(CGFloat)margin inMargin:(CGFloat)inMargin breakMargin:(CGFloat)breakMargin neatLine:(BOOL)neatLine clockWise:(BOOL)clockWise checkBlock:(CGFloat (^)(CGPoint))checkBlock detailInfoBlock:(void (^)(CGPoint, CGPoint))detailInfoBlock { 13 | 14 | CGRect rect = CGRectMake((rawRect.size.width - circleWidth) / 2.0, (rawRect.size.height - circleWidth) / 2.0, circleWidth, circleWidth); 15 | 16 | CGFloat middAngle = [self or_middleAngleWithStartAngle:startAngle endAngle:endAngle]; 17 | 18 | if (ringWidth > 0) { 19 | 20 | CGFloat insetAngle = (ringWidth / circleWidth) * M_PI_4; 21 | middAngle = clockWise ? [self or_angle:middAngle byAddAngle:insetAngle] : [self or_differAngleWithSubtractionAngle:middAngle subtractedAngle:insetAngle]; 22 | 23 | // CGFloat insetAngle = asin(ringWidth / circleWidth); 24 | // CGFloat inset = [self or_differAngleWithSubtractionAngle:endAngle subtractedAngle:startAngle] / (insetAngle * 3); 25 | // inset = MIN(inset, 1); 26 | // inset = clockWise ? inset : -inset; 27 | // middAngle = [self or_angle:middAngle byAddAngle:insetAngle * inset]; 28 | } 29 | 30 | CGRect inReck = CGRectMake(rect.origin.x - inMargin, rect.origin.y - inMargin, rect.size.width + 2 * inMargin, rect.size.height + 2 * inMargin); 31 | 32 | CGRect breakReck = CGRectMake(inReck.origin.x - breakMargin, inReck.origin.y - breakMargin, inReck.size.width + 2 * breakMargin, inReck.size.height + 2 * breakMargin); 33 | 34 | CGPoint inPoint = [self or_pointWithCircleRect:inReck angle:middAngle]; 35 | CGPoint breakPoint = [self or_pointWithCircleRect:breakReck angle:middAngle]; 36 | 37 | if (checkBlock) { 38 | breakPoint.y += checkBlock(breakPoint); 39 | } 40 | 41 | CGFloat centerX = CGRectGetMidX(rect); 42 | 43 | CGPoint edgePoint = CGPointZero; 44 | 45 | CGFloat width = (rawRect.size.width - breakReck.size.width) / 2.0 - margin; 46 | 47 | if (inPoint.x < centerX) { 48 | edgePoint = neatLine ? CGPointMake(margin, breakPoint.y) : CGPointMake(breakPoint.x - width, breakPoint.y); 49 | }else { 50 | edgePoint = neatLine ? CGPointMake(CGRectGetMaxX(rawRect) - margin, breakPoint.y) : CGPointMake(breakPoint.x + width, breakPoint.y); 51 | } 52 | 53 | if (detailInfoBlock) { 54 | detailInfoBlock(edgePoint,inPoint); 55 | } 56 | 57 | UIBezierPath *path = [UIBezierPath bezierPath]; 58 | [path moveToPoint:inPoint]; 59 | [path addLineToPoint:breakPoint]; 60 | [path addLineToPoint:edgePoint]; 61 | 62 | return path; 63 | } 64 | 65 | // 66 | + (UIBezierPath *)or_ringPathWithRect:(CGRect)rect startAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle ringWidth:(CGFloat)ringWidth closckWise:(BOOL)clockWidth isPie:(BOOL)isPie { 67 | 68 | 69 | if (startAngle == endAngle || startAngle == endAngle - M_PI * 2) { 70 | UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:rect.size.width / 2.0]; 71 | // if (!isPie) { 72 | CGRect inReck = CGRectMake(rect.origin.x + ringWidth, rect.origin.y + ringWidth, rect.size.width - 2 * ringWidth, rect.size.height - 2 * ringWidth); 73 | [path appendPath:[[UIBezierPath bezierPathWithRoundedRect:inReck cornerRadius:inReck.size.width / 2.0] bezierPathByReversingPath]]; 74 | // } 75 | return path; 76 | } 77 | 78 | UIBezierPath *path = [UIBezierPath bezierPath]; 79 | CGPoint center = CGPointMake(rect.origin.x + rect.size.width / 2.0, rect.origin.y + rect.size.height / 2.0); 80 | CGFloat radius = MIN(rect.size.width, rect.size.height) / 2.0; 81 | 82 | [path addArcWithCenter:center radius:radius startAngle:startAngle endAngle:endAngle clockwise:YES]; 83 | 84 | if (isPie) { 85 | CGRect inRect = CGRectMake(rect.origin.x + ringWidth, rect.origin.y + ringWidth, rect.size.width - 2 * ringWidth, rect.size.height - 2 * ringWidth); 86 | 87 | [path addLineToPoint:[self or_pointWithCircleRect:inRect angle:endAngle]]; 88 | [path addArcWithCenter:center radius:radius - ringWidth startAngle:endAngle endAngle:startAngle clockwise:NO]; 89 | [path addLineToPoint:[self or_pointWithCircleRect:rect angle:startAngle]]; 90 | return path; 91 | } 92 | 93 | CGPoint squreCenter = [self or_centerWithRect:rect angle:endAngle ringWidth:ringWidth]; 94 | [path addArcWithCenter:squreCenter radius:ringWidth / 2.0 startAngle:endAngle endAngle:[self or_opposingAngleWithAngle:endAngle] clockwise:clockWidth]; 95 | 96 | [path addArcWithCenter:center radius:radius - ringWidth startAngle:endAngle endAngle:startAngle clockwise:NO]; 97 | 98 | CGPoint squreCenter1 = [self or_centerWithRect:rect angle:startAngle ringWidth:ringWidth]; 99 | [path addArcWithCenter:squreCenter1 radius:ringWidth / 2.0 startAngle:[self or_opposingAngleWithAngle:startAngle] endAngle:startAngle clockwise:!clockWidth]; 100 | 101 | return path; 102 | } 103 | 104 | //任意角度的对角 105 | + (CGFloat)or_opposingAngleWithAngle:(CGFloat)angle { 106 | 107 | if (angle > M_PI) { 108 | return angle - M_PI; 109 | } 110 | return M_PI + angle; 111 | } 112 | 113 | //任意角度 加上 固定角度 114 | + (CGFloat)or_angle:(CGFloat)angle byAddAngle:(CGFloat)addAngle { 115 | 116 | if (addAngle < 0 && (angle + addAngle < 0)) { 117 | return angle + addAngle + M_PI * 2; 118 | }else if (angle + addAngle > M_PI * 2) { 119 | return angle + addAngle - M_PI * 2; 120 | } 121 | return angle + addAngle; 122 | } 123 | 124 | //减法 125 | + (CGFloat)or_differAngleWithSubtractionAngle:(CGFloat)subtractionAngle subtractedAngle:(CGFloat)subtractedAngle { 126 | 127 | if (subtractedAngle > subtractionAngle) { 128 | return subtractionAngle + M_PI * 2 - subtractedAngle; 129 | }else { 130 | return subtractionAngle - subtractedAngle; 131 | } 132 | } 133 | 134 | //任意角度间的中点角度 135 | + (CGFloat)or_middleAngleWithStartAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle { 136 | 137 | // if (!clockWidth) { 138 | // CGFloat temp = startAngle; 139 | // startAngle = endAngle; 140 | // endAngle = temp; 141 | // } 142 | 143 | if (endAngle < startAngle) { 144 | return ((startAngle + M_PI * 2) + endAngle) / 2.0; 145 | } 146 | return (startAngle + endAngle) / 2.0; 147 | } 148 | 149 | // 圆环 任意角度(与半径相切)的 中点 150 | + (CGPoint)or_centerWithRect:(CGRect)rect angle:(CGFloat)angle ringWidth:(CGFloat)ringWidth { 151 | 152 | CGPoint topPoint = [self or_pointWithCircleRect:rect angle:angle]; 153 | 154 | CGPoint inPoint = [self or_pointWithCircleRect:CGRectMake(rect.origin.x + ringWidth, rect.origin.y + ringWidth, rect.size.width - 2 * ringWidth, rect.size.height - 2 * ringWidth) angle:angle];; 155 | 156 | return CGPointMake((topPoint.x + inPoint.x) / 2.0, (topPoint.y + inPoint.y) / 2.0); 157 | } 158 | 159 | // 圆上 任意角度的 点 160 | + (CGPoint)or_pointWithCircleRect:(CGRect)rect angle:(CGFloat)angle { 161 | 162 | CGFloat aAngle = angle; 163 | if (angle >= M_PI * 3 / 2.0) { 164 | aAngle = angle - M_PI * 3 / 2.0; 165 | }else { 166 | aAngle = angle + M_PI / 2; 167 | } 168 | 169 | CGPoint center = CGPointMake(rect.origin.x + rect.size.width / 2.0, rect.origin.y + rect.size.height / 2.0); 170 | CGFloat radius = MIN(rect.size.width, rect.size.height) / 2.0; 171 | 172 | CGFloat pointY = center.y - cos(aAngle) * radius; 173 | CGFloat pointX = center.x + sin(aAngle) * radius; 174 | 175 | return CGPointMake(pointX, pointY); 176 | } 177 | 178 | 179 | @end 180 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-ORCharts_Example/Pods-ORCharts_Example-frameworks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | set -u 4 | set -o pipefail 5 | 6 | function on_error { 7 | echo "$(realpath -mq "${0}"):$1: error: Unexpected failure" 8 | } 9 | trap 'on_error $LINENO' ERR 10 | 11 | if [ -z ${FRAMEWORKS_FOLDER_PATH+x} ]; then 12 | # If FRAMEWORKS_FOLDER_PATH is not set, then there's nowhere for us to copy 13 | # frameworks to, so exit 0 (signalling the script phase was successful). 14 | exit 0 15 | fi 16 | 17 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 18 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 19 | 20 | COCOAPODS_PARALLEL_CODE_SIGN="${COCOAPODS_PARALLEL_CODE_SIGN:-false}" 21 | SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" 22 | 23 | # Used as a return value for each invocation of `strip_invalid_archs` function. 24 | STRIP_BINARY_RETVAL=0 25 | 26 | # This protects against multiple targets copying the same framework dependency at the same time. The solution 27 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html 28 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") 29 | 30 | # Copies and strips a vendored framework 31 | install_framework() 32 | { 33 | if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then 34 | local source="${BUILT_PRODUCTS_DIR}/$1" 35 | elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then 36 | local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" 37 | elif [ -r "$1" ]; then 38 | local source="$1" 39 | fi 40 | 41 | local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 42 | 43 | if [ -L "${source}" ]; then 44 | echo "Symlinked..." 45 | source="$(readlink "${source}")" 46 | fi 47 | 48 | # Use filter instead of exclude so missing patterns don't throw errors. 49 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" 50 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" 51 | 52 | local basename 53 | basename="$(basename -s .framework "$1")" 54 | binary="${destination}/${basename}.framework/${basename}" 55 | 56 | if ! [ -r "$binary" ]; then 57 | binary="${destination}/${basename}" 58 | elif [ -L "${binary}" ]; then 59 | echo "Destination binary is symlinked..." 60 | dirname="$(dirname "${binary}")" 61 | binary="${dirname}/$(readlink "${binary}")" 62 | fi 63 | 64 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 65 | if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then 66 | strip_invalid_archs "$binary" 67 | fi 68 | 69 | # Resign the code if required by the build settings to avoid unstable apps 70 | code_sign_if_enabled "${destination}/$(basename "$1")" 71 | 72 | # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. 73 | if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then 74 | local swift_runtime_libs 75 | swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u) 76 | for lib in $swift_runtime_libs; do 77 | echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" 78 | rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" 79 | code_sign_if_enabled "${destination}/${lib}" 80 | done 81 | fi 82 | } 83 | 84 | # Copies and strips a vendored dSYM 85 | install_dsym() { 86 | local source="$1" 87 | if [ -r "$source" ]; then 88 | # Copy the dSYM into a the targets temp dir. 89 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DERIVED_FILES_DIR}\"" 90 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DERIVED_FILES_DIR}" 91 | 92 | local basename 93 | basename="$(basename -s .framework.dSYM "$source")" 94 | binary="${DERIVED_FILES_DIR}/${basename}.framework.dSYM/Contents/Resources/DWARF/${basename}" 95 | 96 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 97 | if [[ "$(file "$binary")" == *"Mach-O "*"dSYM companion"* ]]; then 98 | strip_invalid_archs "$binary" 99 | fi 100 | 101 | if [[ $STRIP_BINARY_RETVAL == 1 ]]; then 102 | # Move the stripped file into its final destination. 103 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${DERIVED_FILES_DIR}/${basename}.framework.dSYM\" \"${DWARF_DSYM_FOLDER_PATH}\"" 104 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${DERIVED_FILES_DIR}/${basename}.framework.dSYM" "${DWARF_DSYM_FOLDER_PATH}" 105 | else 106 | # The dSYM was not stripped at all, in this case touch a fake folder so the input/output paths from Xcode do not reexecute this script because the file is missing. 107 | touch "${DWARF_DSYM_FOLDER_PATH}/${basename}.framework.dSYM" 108 | fi 109 | fi 110 | } 111 | 112 | # Copies the bcsymbolmap files of a vendored framework 113 | install_bcsymbolmap() { 114 | local bcsymbolmap_path="$1" 115 | local destination="${BUILT_PRODUCTS_DIR}" 116 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${bcsymbolmap_path}" "${destination}"" 117 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${bcsymbolmap_path}" "${destination}" 118 | } 119 | 120 | # Signs a framework with the provided identity 121 | code_sign_if_enabled() { 122 | if [ -n "${EXPANDED_CODE_SIGN_IDENTITY:-}" -a "${CODE_SIGNING_REQUIRED:-}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then 123 | # Use the current code_sign_identity 124 | echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" 125 | local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS:-} --preserve-metadata=identifier,entitlements '$1'" 126 | 127 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then 128 | code_sign_cmd="$code_sign_cmd &" 129 | fi 130 | echo "$code_sign_cmd" 131 | eval "$code_sign_cmd" 132 | fi 133 | } 134 | 135 | # Strip invalid architectures 136 | strip_invalid_archs() { 137 | binary="$1" 138 | # Get architectures for current target binary 139 | binary_archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | awk '{$1=$1;print}' | rev)" 140 | # Intersect them with the architectures we are building for 141 | intersected_archs="$(echo ${ARCHS[@]} ${binary_archs[@]} | tr ' ' '\n' | sort | uniq -d)" 142 | # If there are no archs supported by this binary then warn the user 143 | if [[ -z "$intersected_archs" ]]; then 144 | echo "warning: [CP] Vendored binary '$binary' contains architectures ($binary_archs) none of which match the current build architectures ($ARCHS)." 145 | STRIP_BINARY_RETVAL=0 146 | return 147 | fi 148 | stripped="" 149 | for arch in $binary_archs; do 150 | if ! [[ "${ARCHS}" == *"$arch"* ]]; then 151 | # Strip non-valid architectures in-place 152 | lipo -remove "$arch" -output "$binary" "$binary" 153 | stripped="$stripped $arch" 154 | fi 155 | done 156 | if [[ "$stripped" ]]; then 157 | echo "Stripped $binary of architectures:$stripped" 158 | fi 159 | STRIP_BINARY_RETVAL=1 160 | } 161 | 162 | 163 | if [[ "$CONFIGURATION" == "Debug" ]]; then 164 | install_framework "${BUILT_PRODUCTS_DIR}/ORCharts/ORCharts.framework" 165 | fi 166 | if [[ "$CONFIGURATION" == "Release" ]]; then 167 | install_framework "${BUILT_PRODUCTS_DIR}/ORCharts/ORCharts.framework" 168 | fi 169 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then 170 | wait 171 | fi 172 | -------------------------------------------------------------------------------- /Example/ORCharts/Controller/LineChartVC/ORLineMoreViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ORLineViewController.m 3 | // ORChartsDemo 4 | // 5 | // Created by 欧阳荣 on 2019/7/11. 6 | // Copyright © 2019 欧阳荣. All rights reserved. 7 | // 8 | 9 | #import "ORLineMoreViewController.h" 10 | #import "ORLineChartView.h" 11 | 12 | @interface ORLineMoreViewController () 13 | 14 | @property (weak, nonatomic) IBOutlet ORLineChartView *lineChart; 15 | @property (nonatomic, strong) NSArray *datasource; 16 | 17 | @property (weak, nonatomic) IBOutlet UILabel *chartLineWidthLabel; 18 | @property (weak, nonatomic) IBOutlet UILabel *bglineWidthLabel; 19 | @property (weak, nonatomic) IBOutlet UILabel *bottomInsetLabel; 20 | @property (weak, nonatomic) IBOutlet UILabel *topInsetLabel; 21 | @property (weak, nonatomic) IBOutlet UILabel *bottomLabelWidthLabel; 22 | @property (weak, nonatomic) IBOutlet UILabel *bottomLabelInsetLabel; 23 | @property (weak, nonatomic) IBOutlet UILabel *contentMarginLabel; 24 | @property (weak, nonatomic) IBOutlet UILabel *leftWidthLabel; 25 | @property (weak, nonatomic) IBOutlet UILabel *indicatorCircleWidthLabel; 26 | @property (weak, nonatomic) IBOutlet UILabel *indicatorLineWidthLabel; 27 | @property (weak, nonatomic) IBOutlet UILabel *animateDurationLabel; 28 | 29 | @property (weak, nonatomic) IBOutlet NSLayoutConstraint *bottowLayout; 30 | 31 | @property (nonatomic, assign) BOOL showShadowLine; 32 | @property (nonatomic, assign) BOOL showVerticalBgline; 33 | @property (nonatomic, assign) BOOL showHorizontalBgline; 34 | @property (nonatomic, assign) BOOL dottedBGLine; 35 | @property (nonatomic, assign) BOOL isBreakLine; 36 | 37 | @property (nonatomic, strong) UIColor *chartLineColor; 38 | @property (nonatomic, strong) UIColor *shadowLineColor; 39 | @property (nonatomic, strong) UIColor *bgLineColor; 40 | @property (nonatomic, strong) UIColor *indicatorTintColor; 41 | @property (nonatomic, strong) UIColor *indicatorLineColor; 42 | 43 | @property (nonatomic, assign) ORLineChartStyle style; 44 | 45 | @end 46 | 47 | @implementation ORLineMoreViewController 48 | 49 | - (void)viewDidLoad { 50 | [super viewDidLoad]; 51 | // Do any additional setup after loading the view. 52 | _datasource = @[@(12.4),@(23.1),@(37),@(12),@(18.6),@(8.7),@(12.2),@(16.5), @(58.6), @(36.3),@(18.6),@(8.7),@(12.2)]; 53 | 54 | 55 | 56 | // [_ringChart reloadData]; 57 | 58 | 59 | _showShadowLine = _lineChart.config.showShadowLine; 60 | _showVerticalBgline = _lineChart.config.showVerticalBgline; 61 | _showHorizontalBgline = _lineChart.config.showHorizontalBgline; 62 | _dottedBGLine = _lineChart.config.dottedBGLine; 63 | _isBreakLine = _lineChart.config.isBreakLine; 64 | _chartLineColor = _lineChart.config.chartLineColor; 65 | _shadowLineColor = _lineChart.config.shadowLineColor; 66 | _bgLineColor = _lineChart.config.bgLineColor; 67 | _indicatorTintColor = _lineChart.config.indicatorTintColor; 68 | _indicatorLineColor = _lineChart.config.indicatorLineColor; 69 | 70 | 71 | 72 | _lineChart.config.gradientColors = @[[[UIColor redColor] colorWithAlphaComponent:0.3], [[UIColor blueColor] colorWithAlphaComponent:0.3]]; 73 | 74 | [_lineChart reloadData]; 75 | 76 | 77 | _bottowLayout.constant = -350; 78 | [self.view layoutIfNeeded]; 79 | } 80 | - (IBAction)action_showConfig:(id)sender { 81 | 82 | _bottowLayout.constant == 0 ? (_bottowLayout.constant = -350) : (_bottowLayout.constant = 0); 83 | [UIView animateWithDuration:0.25 animations:^{ 84 | [self.view layoutIfNeeded]; 85 | }]; 86 | } 87 | 88 | #pragma mark -- config 89 | - (IBAction)action_slider:(UISlider *)sender { 90 | 91 | switch (sender.tag - 100) { 92 | case 0: 93 | _chartLineWidthLabel.text = [NSString stringWithFormat:@"%.1f",sender.value]; 94 | break; 95 | case 1: 96 | _bglineWidthLabel.text = [NSString stringWithFormat:@"%.1f",sender.value]; 97 | break; 98 | case 2: 99 | _bottomInsetLabel.text = [NSString stringWithFormat:@"%.1f",sender.value]; 100 | break; 101 | case 3: 102 | _topInsetLabel.text = [NSString stringWithFormat:@"%.1f",sender.value]; 103 | break; 104 | case 4: 105 | _bottomLabelWidthLabel.text = [NSString stringWithFormat:@"%.1f",sender.value]; 106 | break; 107 | case 5: 108 | _bottomLabelInsetLabel.text = [NSString stringWithFormat:@"%.1f",sender.value]; 109 | break; 110 | case 6: 111 | _contentMarginLabel.text = [NSString stringWithFormat:@"%.1f",sender.value]; 112 | break; 113 | case 7: 114 | _leftWidthLabel.text = [NSString stringWithFormat:@"%.1f",sender.value]; 115 | break; 116 | case 8: 117 | _indicatorCircleWidthLabel.text = [NSString stringWithFormat:@"%.1f",sender.value]; 118 | break; 119 | case 9: 120 | _indicatorLineWidthLabel.text = [NSString stringWithFormat:@"%.1f",sender.value]; 121 | break; 122 | case 10: 123 | _animateDurationLabel.text = [NSString stringWithFormat:@"%.1f",sender.value]; 124 | break; 125 | default: 126 | break; 127 | } 128 | 129 | } 130 | 131 | - (IBAction)action_chartStyle:(UISegmentedControl *)sender { 132 | _style = sender.selectedSegmentIndex; 133 | } 134 | 135 | 136 | - (IBAction)action_clockwise:(UISwitch *)sender { 137 | 138 | switch (sender.tag - 200) { 139 | case 0: 140 | _showVerticalBgline = sender.isOn; 141 | break; 142 | case 1: 143 | _showHorizontalBgline = sender.isOn; 144 | break; 145 | case 2: 146 | _dottedBGLine = sender.isOn; 147 | break; 148 | case 3: 149 | _isBreakLine = sender.isOn; 150 | break; 151 | case 4: 152 | _showShadowLine = sender.isOn; 153 | break; 154 | default: 155 | break; 156 | } 157 | } 158 | 159 | - (IBAction)action_randomColor:(UIButton *)sender { 160 | //300 161 | 162 | UIColor *color = [UIColor or_randomColor]; 163 | UIColor *alphaColor = [color colorWithAlphaComponent:0.5]; 164 | 165 | switch (sender.tag - 300) { 166 | case 0: { 167 | _chartLineColor = color; 168 | sender.backgroundColor = color; 169 | } 170 | break; 171 | case 1: { 172 | _shadowLineColor = alphaColor; 173 | sender.backgroundColor = alphaColor; 174 | } 175 | break; 176 | case 2: { 177 | _bgLineColor = alphaColor; 178 | sender.backgroundColor = alphaColor; 179 | } 180 | break; 181 | case 3: { 182 | _indicatorTintColor = color; 183 | sender.backgroundColor = color; 184 | } 185 | break; 186 | case 4: { 187 | _indicatorLineColor = color; 188 | sender.backgroundColor = color; 189 | } 190 | break; 191 | default: 192 | break; 193 | } 194 | } 195 | 196 | - (IBAction)action_cancel:(id)sender { 197 | _bottowLayout.constant = -350; 198 | [UIView animateWithDuration:0.25 animations:^{ 199 | [self.view layoutIfNeeded]; 200 | }]; 201 | } 202 | 203 | - (IBAction)action_config:(id)sender { 204 | 205 | _lineChart.config.style = _style; 206 | 207 | _lineChart.config.showShadowLine = _showShadowLine; 208 | _lineChart.config.showVerticalBgline = _showVerticalBgline; 209 | _lineChart.config.showHorizontalBgline = _showHorizontalBgline; 210 | _lineChart.config.dottedBGLine = _dottedBGLine; 211 | _lineChart.config.isBreakLine = _isBreakLine; 212 | 213 | _lineChart.config.chartLineColor = _chartLineColor; 214 | _lineChart.config.shadowLineColor = _shadowLineColor; 215 | _lineChart.config.bgLineColor = _bgLineColor; 216 | _lineChart.config.indicatorTintColor = _indicatorTintColor; 217 | _lineChart.config.indicatorLineColor = _indicatorLineColor; 218 | 219 | 220 | _lineChart.config.chartLineWidth = [_chartLineWidthLabel.text floatValue]; 221 | _lineChart.config.bglineWidth = [_bglineWidthLabel.text floatValue]; 222 | _lineChart.config.bottomInset = [_bottomInsetLabel.text floatValue]; 223 | _lineChart.config.topInset = [_topInsetLabel.text floatValue]; 224 | _lineChart.config.bottomLabelWidth = [_bottomLabelWidthLabel.text floatValue]; 225 | _lineChart.config.bottomLabelInset = [_bottomLabelInsetLabel.text floatValue]; 226 | _lineChart.config.contentMargin = [_contentMarginLabel.text floatValue]; 227 | _lineChart.config.leftWidth = [_leftWidthLabel.text floatValue]; 228 | _lineChart.config.indicatorCircleWidth = [_indicatorCircleWidthLabel.text floatValue]; 229 | _lineChart.config.indicatorLineWidth = [_indicatorLineWidthLabel.text floatValue]; 230 | _lineChart.config.animateDuration = [_animateDurationLabel.text floatValue]; 231 | 232 | [_lineChart reloadData]; 233 | 234 | } 235 | 236 | #pragma mark -- ORLineChartViewDataSource 237 | 238 | - (NSInteger)numberOfHorizontalDataOfChartView:(ORLineChartView *)chartView { 239 | return _datasource.count; 240 | } 241 | 242 | - (CGFloat)chartView:(ORLineChartView *)chartView valueForHorizontalAtIndex:(NSInteger)index { 243 | return [_datasource[index] doubleValue]; 244 | } 245 | 246 | - (NSAttributedString *)chartView:(ORLineChartView *)chartView attributedStringForIndicaterAtIndex:(NSInteger)index { 247 | NSAttributedString *string = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"value:%g", [_datasource[index] doubleValue]]]; 248 | return string; 249 | } 250 | 251 | #pragma mark - ORLineChartViewDataSource 252 | - (void)chartView:(ORLineChartView *)chartView didSelectValueAtIndex:(NSInteger)index { 253 | NSLog(@"did select index %ld and value is %g", index, [_datasource[index] doubleValue]); 254 | } 255 | 256 | - (void)chartView:(ORLineChartView *)chartView indicatorDidChangeValueAtIndex:(NSInteger)index { 257 | NSLog(@"indicater did change index %ld and value is %g", index, [_datasource[index] doubleValue]); 258 | } 259 | 260 | 261 | @end 262 | -------------------------------------------------------------------------------- /ORCharts/Classes/ORRingChart/ORRingChartView.m: -------------------------------------------------------------------------------- 1 | // 2 | // ORRingChartView.m 3 | // ORAnimateTest 4 | // 5 | // Created by OrangesAL on 2019/4/24. 6 | // Copyright © 2019 OrangesAL. All rights reserved. 7 | // 8 | 9 | #import "ORRingChartView.h" 10 | #import "ORChartUtilities+ORRing.h" 11 | 12 | @implementation NSObject (ORRingChartView) 13 | 14 | - (NSArray *)chartView:(ORRingChartView *)chartView graidentColorsAtRingIndex:(NSInteger)index {return @[[UIColor or_randomColor],[UIColor or_randomColor]];} 15 | - (UIColor *)chartView:(ORRingChartView *)chartView lineColorForRingAtRingIndex:(NSInteger)index {return [UIColor whiteColor];} 16 | - (UIColor *)chartView:(ORRingChartView *)chartView lineColorForInfoLineAtRingIndex:(NSInteger)index {return nil;} 17 | - (UIView *)viewForRingCenterOfChartView:(ORRingChartView *)chartView {return nil;} 18 | - (UIView *)chartView:(ORRingChartView *)chartView viewForTopInfoAtRingIndex:(NSInteger)index {return nil;} 19 | - (UIView *)chartView:(ORRingChartView *)chartView viewForBottomInfoAtRingIndex:(NSInteger)index {return nil;} 20 | - (UIView *)chartView:(ORRingChartView *)chartView viewForRingInfoAtRingIndex:(NSInteger)index {return nil;} 21 | 22 | @end 23 | 24 | @interface ORRingConfig : NSObject 25 | 26 | @property (nonatomic, assign) CGFloat value; 27 | 28 | @property (nonatomic, strong) NSArray *gradientColors; 29 | @property (nonatomic, strong) UIColor *ringLineColor; 30 | @property (nonatomic, strong) UIColor *ringInfoColor; 31 | 32 | @property (nonatomic, strong) CAGradientLayer *gradientLayer; 33 | @property (nonatomic, strong) CAShapeLayer *ringLineLayer; 34 | @property (nonatomic, strong) CAShapeLayer *infoLineLayer; 35 | @property (nonatomic, strong) CALayer *infoLinePointLayer; 36 | @property (nonatomic, strong) UIView *topInfoView; 37 | @property (nonatomic, strong) UIView *bottomInfoView; 38 | @property (nonatomic, strong) UIView *ringInfoView; 39 | 40 | @property (nonatomic, assign) CGFloat startAngle; 41 | @property (nonatomic, assign) CGFloat endAngle; 42 | @property (nonatomic, assign, readonly) BOOL leftToRight; 43 | 44 | @end 45 | 46 | @implementation ORRingConfig 47 | 48 | - (BOOL)leftToRight { 49 | 50 | CGFloat midAngle = [ORChartUtilities or_middleAngleWithStartAngle:self.startAngle endAngle:self.endAngle]; 51 | BOOL ltor = (midAngle >= M_PI * 3 / 2 && midAngle <= M_PI * 2.0) || (midAngle >= M_PI / 2 && midAngle <= M_PI); 52 | return ltor; 53 | } 54 | 55 | - (UIColor *)ringInfoColor { 56 | if (!_ringInfoColor) { 57 | _ringInfoColor = self.gradientColors.firstObject; 58 | } 59 | return _ringInfoColor; 60 | } 61 | 62 | @end 63 | 64 | @interface ORRingChartView () 65 | 66 | @property (nonatomic, strong) NSMutableArray * ringConfigs; 67 | 68 | @property (nonatomic, strong) UIView *centerInfoView; 69 | 70 | @property (nonatomic, assign) CGFloat maxMarginWidthSum; 71 | @property (nonatomic, assign) CGFloat maxMarginHeightSum; 72 | 73 | @end 74 | 75 | @implementation ORRingChartView 76 | 77 | - (instancetype)initWithCoder:(NSCoder *)coder 78 | { 79 | self = [super initWithCoder:coder]; 80 | if (self) { 81 | [self _or_initData]; 82 | } 83 | return self; 84 | } 85 | 86 | - (instancetype)initWithFrame:(CGRect)frame 87 | { 88 | self = [super initWithFrame:frame]; 89 | if (self) { 90 | [self _or_initData]; 91 | } 92 | return self; 93 | } 94 | 95 | - (void)layoutSubviews { 96 | [super layoutSubviews]; 97 | [self _or_layoutLayers]; 98 | } 99 | 100 | - (void)_or_initData { 101 | 102 | _ringConfigs = [NSMutableArray array]; 103 | _config = [ORRingChartConfig new]; 104 | } 105 | 106 | - (void)_or_layoutLayers { 107 | 108 | if (self.ringConfigs.count == 0) { 109 | return; 110 | } 111 | 112 | CGFloat centerX = self.bounds.size.width * 0.5; 113 | 114 | CGFloat width = MIN(self.bounds.size.width - (_maxMarginWidthSum + _config.minInfoInset + _config.infoLineBreakMargin + _config.infoLineInMargin + _config.infoLineMargin) * 2, self.bounds.size.height - (_maxMarginHeightSum + _config.minInfoInset + _config.infoLineWidth + _config.infoLineInMargin + _config.infoViewMargin * 2 + _config.infoLineBreakMargin) * 2); 115 | 116 | CGRect bounds = CGRectMake(0, 0, width, width); 117 | CGPoint position = CGPointMake(centerX, self.bounds.size.height * 0.5); 118 | 119 | CGFloat ringWidth = _config.ringWidth; 120 | 121 | if (self.centerInfoView) { 122 | self.centerInfoView.center = position; 123 | ringWidth = (width - MAX(self.centerInfoView.bounds.size.width, self.centerInfoView.bounds.size.height) - _config.ringLineWidth) / 2 ; 124 | } 125 | 126 | ringWidth = MAX(ringWidth, 10); 127 | ringWidth = MIN(ringWidth, width / 2.0); 128 | 129 | if (self.style == ORRingChartStyleFan) { 130 | ringWidth = width / 2.0; 131 | if (_centerInfoView) { 132 | [_centerInfoView removeFromSuperview]; 133 | } 134 | } 135 | 136 | if (self.style == ORRingChartStylePie && _centerInfoView == nil) { 137 | ringWidth = width / 2.0; 138 | } 139 | 140 | CGFloat insetRingWidth = self.style == ORRingChartStylePie ? 0 : ringWidth; 141 | 142 | [self.ringConfigs enumerateObjectsUsingBlock:^(ORRingConfig * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { 143 | 144 | obj.gradientLayer.bounds = bounds; 145 | obj.gradientLayer.position = position; 146 | CAShapeLayer *shapeLayer = obj.gradientLayer.mask; 147 | CGPathRef path = [ORChartUtilities or_ringPathWithRect:bounds startAngle:obj.startAngle endAngle:obj.endAngle ringWidth:ringWidth closckWise:self.config.clockwise isPie:self.style == ORRingChartStylePie].CGPath; 148 | shapeLayer.path = path; 149 | 150 | obj.ringLineLayer.bounds = bounds; 151 | obj.ringLineLayer.position = position; 152 | obj.ringLineLayer.path = path; 153 | 154 | if (obj.ringInfoView) { 155 | // CGFloat angle = obj.endAngle; 156 | CGFloat middAngle = [ORChartUtilities or_middleAngleWithStartAngle:obj.startAngle endAngle:obj.endAngle]; 157 | 158 | if (insetRingWidth > 0) { 159 | 160 | CGFloat insetAngle = (insetRingWidth / width) * M_PI_2; 161 | middAngle = self.config.clockwise ? [ORChartUtilities or_angle:middAngle byAddAngle:insetAngle] : [ORChartUtilities or_differAngleWithSubtractionAngle:middAngle subtractedAngle:insetAngle]; 162 | } 163 | 164 | CGPoint ringInfoCenter = [ORChartUtilities or_centerWithRect:bounds angle:middAngle ringWidth:ringWidth]; 165 | ringInfoCenter = [obj.ringLineLayer convertPoint:ringInfoCenter toLayer:self.layer]; 166 | obj.ringInfoView.center = ringInfoCenter; 167 | [self bringSubviewToFront:obj.ringInfoView]; 168 | } 169 | 170 | 171 | if (obj.bottomInfoView || obj.topInfoView) { 172 | CGPathRef linePath = [ORChartUtilities or_breakLinePathWithRawRect:self.bounds circleWidth:width ringWidth:insetRingWidth startAngle:obj.startAngle endAngle:obj.endAngle margin:self.config.infoLineMargin inMargin:self.config.infoLineInMargin breakMargin:self.config.infoLineBreakMargin neatLine:self.config.neatInfoLine clockWise:self.config.clockwise checkBlock:^CGFloat(CGPoint breakPoint) { 173 | 174 | if (idx > 0) { 175 | ORRingConfig *config = self.ringConfigs[idx - 1]; 176 | 177 | if (CGRectGetMinX(config.topInfoView.frame) > centerX && breakPoint.x > centerX) { 178 | 179 | CGFloat inset = obj.topInfoView.bounds.size.height + self.config.infoViewMargin - (breakPoint.y - CGRectGetMaxY(config.bottomInfoView.frame)); 180 | if (inset > 0) { 181 | return inset; 182 | } 183 | }else if (CGRectGetMinX(config.topInfoView.frame) < centerX && breakPoint.x < centerX) { 184 | 185 | CGFloat inset = obj.bottomInfoView.bounds.size.height + self.config.infoViewMargin - (CGRectGetMinY(config.topInfoView.frame) - breakPoint.y); 186 | if (inset > 0) { 187 | return -inset; 188 | } 189 | } 190 | } 191 | return 0; 192 | } detailInfoBlock:^(CGPoint edgePoint, CGPoint endPoint) { 193 | 194 | obj.infoLinePointLayer.frame = CGRectMake(endPoint.x - self.config.pointWidth / 2.0, endPoint.y - self.config.pointWidth / 2.0, self.config.pointWidth, self.config.pointWidth); 195 | obj.infoLinePointLayer.cornerRadius = self.config.pointWidth / 2.0; 196 | 197 | CGRect frame = obj.topInfoView.frame; 198 | CGFloat fx = edgePoint.x > self.bounds.size.width / 2.0 ? edgePoint.x - frame.size.width : edgePoint.x; 199 | frame.origin = CGPointMake(fx, edgePoint.y - self.config.infoViewMargin - frame.size.height); 200 | obj.topInfoView.frame = frame; 201 | 202 | CGRect bottomFrame = obj.bottomInfoView.frame; 203 | CGFloat bfx = edgePoint.x > self.bounds.size.width / 2.0 ? edgePoint.x - bottomFrame.size.width : edgePoint.x; 204 | bottomFrame.origin = CGPointMake(bfx, edgePoint.y + self.config.infoViewMargin); 205 | obj.bottomInfoView.frame = bottomFrame; 206 | 207 | }].CGPath; 208 | obj.infoLineLayer.path = linePath; 209 | } 210 | 211 | if (self.config.animateDuration > 0) { 212 | [shapeLayer addAnimation:[ORChartUtilities or_strokeAnimationWithDurantion:self.config.animateDuration] forKey:nil]; 213 | [obj.ringLineLayer addAnimation:[ORChartUtilities or_strokeAnimationWithDurantion:self.config.animateDuration] forKey:nil]; 214 | [obj.infoLineLayer addAnimation:[ORChartUtilities or_strokeAnimationWithDurantion:self.config.animateDuration] forKey:nil]; 215 | } 216 | }]; 217 | } 218 | 219 | - (void)_or_addLayerstWithconfig:(ORRingConfig *)config { 220 | 221 | if (config.gradientLayer) { 222 | [ORChartUtilities or_configGrandientLayer:config.gradientLayer withColors:config.gradientColors leftToRight:config.leftToRight]; 223 | 224 | config.ringLineLayer.lineWidth = self.config.ringLineWidth; 225 | config.ringLineLayer.strokeColor = config.ringLineColor.CGColor; 226 | 227 | config.infoLineLayer.lineWidth = self.config.infoLineWidth; 228 | config.infoLineLayer.strokeColor = config.ringInfoColor.CGColor; 229 | 230 | config.infoLinePointLayer.backgroundColor = config.ringInfoColor.CGColor; 231 | return; 232 | } 233 | 234 | CAGradientLayer *gradientLayer = [ORChartUtilities or_grandientLayerWithColors:config.gradientColors leftToRight:config.leftToRight]; 235 | gradientLayer.mask = [CAShapeLayer layer]; 236 | [self.layer addSublayer:gradientLayer]; 237 | 238 | CAShapeLayer *ringLineLayer = [ORChartUtilities or_shapelayerWithLineWidth:self.config.ringLineWidth strokeColor:config.ringLineColor]; 239 | [self.layer addSublayer:ringLineLayer]; 240 | 241 | CAShapeLayer *infoLineLayer = [ORChartUtilities or_shapelayerWithLineWidth:self.config.infoLineWidth strokeColor:config.ringInfoColor]; 242 | [self.layer addSublayer:infoLineLayer]; 243 | 244 | CALayer *infoLinePointLayer = [CALayer layer]; 245 | infoLinePointLayer.backgroundColor = config.ringInfoColor.CGColor; 246 | [self.layer addSublayer:infoLinePointLayer]; 247 | 248 | config.gradientLayer = gradientLayer; 249 | config.ringLineLayer = ringLineLayer; 250 | config.infoLineLayer = infoLineLayer; 251 | config.infoLinePointLayer = infoLinePointLayer; 252 | } 253 | 254 | - (void)_or_deleteConfig:(ORRingConfig *)config { 255 | 256 | if (config.gradientLayer && config.gradientLayer.superlayer) { 257 | [config.infoLineLayer removeFromSuperlayer]; 258 | [config.ringLineLayer removeFromSuperlayer]; 259 | [config.infoLinePointLayer removeFromSuperlayer]; 260 | [config.gradientLayer removeFromSuperlayer]; 261 | } 262 | [config.topInfoView removeFromSuperview]; 263 | [config.bottomInfoView removeFromSuperview]; 264 | 265 | [_ringConfigs removeObject:config]; 266 | } 267 | 268 | - (void)_or_replaceView:(UIView *)rawView withNewView:(UIView *)newView { 269 | if (!newView || [newView isEqual:rawView]) { 270 | return; 271 | } 272 | if (rawView) { 273 | [rawView removeFromSuperview]; 274 | } 275 | [self addSubview:newView]; 276 | } 277 | 278 | #pragma mark -- public 279 | - (void)reloadData { 280 | 281 | if (!_dataSource) { 282 | return; 283 | } 284 | 285 | 286 | NSInteger items = [_dataSource numberOfRingsOfChartView:self]; 287 | 288 | if (items == 0) { 289 | [self.layer.sublayers makeObjectsPerformSelector:@selector(removeFromSuperlayer)]; 290 | [self.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)]; 291 | 292 | return; 293 | } 294 | 295 | CGFloat maxValue = 0; 296 | 297 | 298 | for (int i = 0; i < items; i ++) { 299 | 300 | ORRingConfig *config; 301 | 302 | if (i < _ringConfigs.count) { 303 | config = _ringConfigs[i]; 304 | }else { 305 | config = [ORRingConfig new]; 306 | [_ringConfigs addObject:config]; 307 | } 308 | 309 | config.value = [_dataSource chartView:self valueAtRingIndex:i]; 310 | config.gradientColors = [_dataSource chartView:self graidentColorsAtRingIndex:i]; 311 | config.ringLineColor = [_dataSource chartView:self lineColorForRingAtRingIndex:i]; 312 | config.ringInfoColor = [_dataSource chartView:self lineColorForInfoLineAtRingIndex:i]; 313 | 314 | UIView *topInfoView = [_dataSource chartView:self viewForTopInfoAtRingIndex:i]; 315 | UIView *bottomInfoView = [_dataSource chartView:self viewForBottomInfoAtRingIndex:i]; 316 | UIView *ringInfoView = [_dataSource chartView:self viewForRingInfoAtRingIndex:i]; 317 | 318 | if (topInfoView && ![topInfoView isEqual:config.topInfoView]) { 319 | [config.topInfoView removeFromSuperview]; 320 | config.topInfoView = topInfoView; 321 | [self addSubview:config.topInfoView]; 322 | } 323 | 324 | if (bottomInfoView && ![bottomInfoView isEqual:config.bottomInfoView]) { 325 | [config.bottomInfoView removeFromSuperview]; 326 | config.bottomInfoView = bottomInfoView; 327 | [self addSubview:config.bottomInfoView]; 328 | } 329 | 330 | if (ringInfoView && ![ringInfoView isEqual:config.ringInfoView]) { 331 | [config.ringInfoView removeFromSuperview]; 332 | config.ringInfoView = ringInfoView; 333 | [self addSubview:config.ringInfoView]; 334 | } 335 | 336 | _maxMarginWidthSum = MAX(MAX(config.topInfoView.bounds.size.width, config.bottomInfoView.bounds.size.width), _maxMarginWidthSum); 337 | _maxMarginHeightSum = MAX(config.topInfoView.bounds.size.height + config.bottomInfoView.bounds.size.height, _maxMarginHeightSum); 338 | 339 | maxValue += config.value; 340 | 341 | } 342 | 343 | if (items != _ringConfigs.count) { 344 | for (NSInteger i = items; i < _ringConfigs.count; i ++) { 345 | [self _or_deleteConfig:_ringConfigs[i]]; 346 | i --; 347 | } 348 | } 349 | 350 | CGFloat startAngle = self.config.startAngle; 351 | for (int i = 0; i < _ringConfigs.count; i ++) { 352 | 353 | ORRingConfig *config = _ringConfigs[i]; 354 | 355 | if (config.value == 0) { 356 | [self _or_deleteConfig:config]; 357 | i --; 358 | continue; 359 | } 360 | 361 | CGFloat angle = [ORChartUtilities or_angle:startAngle byAddAngle:ORInterpolation(0, M_PI * 2, config.value / maxValue)]; 362 | config.startAngle = startAngle; 363 | config.endAngle = angle; 364 | 365 | startAngle = angle; 366 | [self _or_addLayerstWithconfig:config]; 367 | } 368 | 369 | 370 | UIView *centerView = [_dataSource viewForRingCenterOfChartView:self]; 371 | if (centerView && (![centerView isEqual:_centerInfoView] || !centerView.superview)) { 372 | [_centerInfoView removeFromSuperview]; 373 | _centerInfoView = centerView; 374 | [self addSubview:_centerInfoView]; 375 | } 376 | 377 | [self setNeedsLayout]; 378 | } 379 | 380 | - (UIView *)dequeueCenterView { 381 | return _centerInfoView; 382 | } 383 | 384 | - (UIView *)dequeueTopInfoViewAtIndex:(NSInteger)index { 385 | if (index < self.ringConfigs.count) { 386 | return self.ringConfigs[index].topInfoView; 387 | } 388 | return nil; 389 | } 390 | 391 | - (UIView *)dequeueBottomInfoViewAtIndex:(NSInteger)index { 392 | if (index < self.ringConfigs.count) { 393 | return self.ringConfigs[index].bottomInfoView; 394 | } 395 | return nil; 396 | } 397 | 398 | - (UIView *)dequeueRingInfoViewAtIndex:(NSInteger)index { 399 | if (index < self.ringConfigs.count) { 400 | return self.ringConfigs[index].ringInfoView; 401 | } 402 | return nil; 403 | } 404 | 405 | #pragma mark -- setter 406 | - (void)setDataSource:(id)dataSource { 407 | 408 | if (_dataSource != dataSource) { 409 | _dataSource = dataSource; 410 | if (_dataSource) { 411 | [self reloadData]; 412 | } 413 | } 414 | } 415 | 416 | - (void)setStyle:(ORRingChartStyle)style { 417 | _style = style; 418 | [self setNeedsLayout]; 419 | } 420 | 421 | @end 422 | 423 | 424 | 425 | -------------------------------------------------------------------------------- /ORCharts/Classes/ORLineChart/ORLineChartView.m: -------------------------------------------------------------------------------- 1 | // 2 | // ORLineChartView.m 3 | // ORChartView 4 | // 5 | // Created by OrangesAL on 2019/5/1. 6 | // Copyright © 2019年 OrangesAL. All rights reserved. 7 | // 8 | 9 | #import "ORLineChartView.h" 10 | #import "ORLineChartCell.h" 11 | #import "ORChartUtilities.h" 12 | #import "ORLineChartValue.h" 13 | #import "ORLineChartButton.h" 14 | 15 | @implementation NSObject (ORLineChartView) 16 | 17 | - (NSInteger)numberOfVerticalLinesOfChartView:(ORLineChartView *)chartView {return 5;}; 18 | 19 | - (id)chartView:(ORLineChartView *)chartView titleForHorizontalAtIndex:(NSInteger)index { 20 | NSDateFormatter *formatter = [NSDateFormatter new]; 21 | formatter.dateFormat = @"MM-dd"; 22 | NSDate *date = [[NSDate date] dateByAddingTimeInterval:index * 24 * 60 * 60]; 23 | return [formatter stringFromDate:date]; 24 | }; 25 | 26 | - (NSDictionary *)labelAttrbutesForHorizontalOfChartView:(ORLineChartView *)chartView { 27 | return @{NSFontAttributeName : [UIFont systemFontOfSize:12]}; 28 | } 29 | - (NSDictionary *)labelAttrbutesForVerticalOfChartView:(ORLineChartView *)chartView { 30 | return @{NSFontAttributeName : [UIFont systemFontOfSize:12]}; 31 | } 32 | 33 | - (NSAttributedString *)chartView:(ORLineChartView *)chartView attributedStringForIndicaterAtIndex:(NSInteger)index {return nil;} 34 | 35 | - (void)chartView:(ORLineChartView *)chartView didSelectValueAtIndex:(NSInteger)index {} 36 | - (void)chartView:(ORLineChartView *)chartView indicatorDidChangeValueAtIndex:(NSInteger)index {} 37 | 38 | @end 39 | 40 | @interface _ORIndicatorView : UIView 41 | @end 42 | 43 | @implementation _ORIndicatorView { 44 | UILabel *_label; 45 | CAShapeLayer *_backLayer; 46 | CALayer *_shadowLayer; 47 | } 48 | 49 | - (instancetype)initWithFrame:(CGRect)frame 50 | { 51 | self = [super initWithFrame:frame]; 52 | if (self) { 53 | [self _or_initailizeUI]; 54 | } 55 | return self; 56 | } 57 | 58 | - (void)_or_initailizeUI{ 59 | _label = ({ 60 | UILabel *label = [UILabel new]; 61 | label; 62 | }); 63 | [self addSubview:_label]; 64 | 65 | 66 | _backLayer = ({ 67 | CAShapeLayer *layer = [CAShapeLayer new]; 68 | layer.fillColor = [UIColor redColor].CGColor; 69 | layer; 70 | }); 71 | 72 | [self.layer insertSublayer:_backLayer atIndex:0]; 73 | 74 | _shadowLayer = ({ 75 | CALayer *layer = [CALayer new]; 76 | layer; 77 | }); 78 | [self.layer insertSublayer:_shadowLayer atIndex:0]; 79 | } 80 | 81 | - (void)or_setTitle:(NSAttributedString *)title inset:(CGFloat)inset { 82 | _label.attributedText = title; 83 | [_label sizeToFit]; 84 | CGFloat width = _label.bounds.size.width + inset * 2; 85 | CGFloat height = _label.bounds.size.height + inset * 2 + 3.78; 86 | self.bounds = CGRectMake(0, 0, width, height); 87 | _label.center = CGPointMake(width / 2.0, (height - 3.78) / 2.0); 88 | 89 | _backLayer.path = ({ 90 | UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, width, height - 3.78) cornerRadius:3]; 91 | UIBezierPath *anglePath = [UIBezierPath bezierPath]; 92 | [anglePath moveToPoint:CGPointMake(width / 2.0f, height)]; 93 | [anglePath addLineToPoint:CGPointMake(width / 2.0 - 3.5, height - 3.78)]; 94 | [anglePath addLineToPoint:CGPointMake(width / 2.0 + 3.5, height - 3.78)]; 95 | [anglePath addLineToPoint:CGPointMake(width / 2.0f, height)]; 96 | [path appendPath:anglePath]; 97 | path.CGPath; 98 | }); 99 | } 100 | 101 | - (void)setBackgroundColor:(UIColor *)backgroundColor { 102 | _backLayer.fillColor = backgroundColor.CGColor; 103 | } 104 | 105 | @end 106 | 107 | #pragma mark - ORLineChartView 108 | @interface ORLineChartView () { 109 | NSInteger _lastIndex; 110 | } 111 | 112 | @property (nonatomic, strong) UICollectionView *collectionView; 113 | @property (nonatomic, strong) NSMutableArray *leftLabels; 114 | 115 | @property (nonatomic, strong) NSMutableArray *horizontalDatas; 116 | 117 | @property (nonatomic, strong) ORLineChartConfig *config; 118 | @property (nonatomic, strong) ORLineChartValue *lineChartValue; 119 | @property (nonatomic, strong) CAShapeLayer *bottomLineLayer; 120 | @property (nonatomic, strong) CAShapeLayer *bgLineLayer; 121 | 122 | @property (nonatomic, strong) CAGradientLayer *gradientLayer; 123 | @property (nonatomic, strong) CAShapeLayer *closeLayer; 124 | 125 | @property (nonatomic, strong) CAShapeLayer *lineLayer; 126 | @property (nonatomic, strong) CAShapeLayer *shadowLineLayer; 127 | 128 | @property (nonatomic, strong) CAShapeLayer *circleLayer; 129 | 130 | @property (nonatomic, strong) CALayer *animationLayer; 131 | @property (nonatomic, strong) _ORIndicatorView *indicator; 132 | @property (nonatomic, strong) CALayer *indicatorLineLayer; 133 | 134 | @property (nonatomic, strong) CALayer *contenLayer; 135 | 136 | @property (nonatomic, assign) CGFloat bottomTextHeight; 137 | 138 | 139 | @property (nonatomic,strong)NSMutableArray *controls; 140 | 141 | 142 | @end 143 | 144 | @implementation ORLineChartView 145 | 146 | - (instancetype)initWithCoder:(NSCoder *)coder 147 | { 148 | self = [super initWithCoder:coder]; 149 | if (self) { 150 | [self _or_initData]; 151 | [self _or_initUI]; 152 | } 153 | return self; 154 | } 155 | 156 | - (instancetype)initWithFrame:(CGRect)frame 157 | { 158 | self = [super initWithFrame:frame]; 159 | if (self) { 160 | [self _or_initData]; 161 | [self _or_initUI]; 162 | } 163 | return self; 164 | } 165 | 166 | - (void)layoutSubviews { 167 | [super layoutSubviews]; 168 | [self _or_layoutSubviews]; 169 | } 170 | 171 | - (void)_or_initUI { 172 | 173 | self.backgroundColor = [UIColor whiteColor]; 174 | 175 | _collectionView = ({ 176 | UICollectionViewFlowLayout *layout = [UICollectionViewFlowLayout new]; 177 | layout.minimumInteritemSpacing = 0; 178 | layout.minimumLineSpacing = 0; 179 | layout.scrollDirection = UICollectionViewScrollDirectionHorizontal; 180 | UICollectionView *collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout]; 181 | collectionView.backgroundColor = [UIColor clearColor]; 182 | collectionView.showsHorizontalScrollIndicator = NO; 183 | collectionView.scrollsToTop = NO; 184 | [collectionView registerClass:[ORLineChartCell class] forCellWithReuseIdentifier:NSStringFromClass([ORLineChartCell class])]; 185 | collectionView.delegate = self; 186 | collectionView.dataSource = self; 187 | collectionView; 188 | }); 189 | [self addSubview:_collectionView]; 190 | 191 | _bgLineLayer = [CAShapeLayer layer]; 192 | [self.layer addSublayer:_bgLineLayer]; 193 | 194 | _bottomLineLayer = [CAShapeLayer layer]; 195 | [self.layer addSublayer:_bottomLineLayer]; 196 | 197 | _gradientLayer = ({ 198 | CAGradientLayer *gradientLayer = [CAGradientLayer layer]; 199 | gradientLayer.startPoint = CGPointMake(0, 0); 200 | gradientLayer.endPoint = CGPointMake(0, 1); 201 | gradientLayer.masksToBounds = YES; 202 | // gradientLayer.locations = @[@(0.5f)]; 203 | gradientLayer; 204 | }); 205 | _closeLayer = [ORChartUtilities or_shapelayerWithLineWidth:1 strokeColor:nil]; 206 | _closeLayer.fillColor = [UIColor blueColor].CGColor; 207 | 208 | CALayer *baseLayer = [CALayer layer]; 209 | [baseLayer addSublayer:_gradientLayer]; 210 | [baseLayer setMask:_closeLayer]; 211 | _contenLayer = baseLayer; 212 | [_collectionView.layer addSublayer:baseLayer]; 213 | 214 | 215 | 216 | _lineLayer = [ORChartUtilities or_shapelayerWithLineWidth:1 strokeColor:nil]; 217 | [_collectionView.layer addSublayer:_lineLayer]; 218 | 219 | _shadowLineLayer = [ORChartUtilities or_shapelayerWithLineWidth:1 strokeColor:nil]; 220 | [_collectionView.layer addSublayer:_shadowLineLayer]; 221 | 222 | _indicatorLineLayer = ({ 223 | CALayer *layer = [CALayer layer]; 224 | layer; 225 | }); 226 | 227 | [_collectionView.layer addSublayer:_indicatorLineLayer]; 228 | 229 | 230 | _circleLayer = ({ 231 | CAShapeLayer *layer = [ORChartUtilities or_shapelayerWithLineWidth:1 strokeColor:nil]; 232 | layer.fillColor = self.backgroundColor.CGColor; 233 | layer.speed = 0.0f; 234 | layer; 235 | }); 236 | [_collectionView.layer addSublayer:_circleLayer]; 237 | 238 | 239 | _animationLayer = ({ 240 | CALayer *layer = [CALayer new]; 241 | layer.backgroundColor = [UIColor clearColor].CGColor; 242 | layer.speed = 0.0f; 243 | layer; 244 | }); 245 | [_collectionView.layer addSublayer:_animationLayer]; 246 | 247 | _indicator = [_ORIndicatorView new];; 248 | [_collectionView addSubview:_indicator]; 249 | 250 | } 251 | 252 | - (void)_or_initData { 253 | _controls = [NSMutableArray array]; 254 | _leftLabels = [NSMutableArray array]; 255 | _horizontalDatas = [NSMutableArray array]; 256 | _config = [ORLineChartConfig new]; 257 | _defaultSelectIndex = 0; 258 | } 259 | 260 | - (void)_or_configChart { 261 | 262 | _lineLayer.strokeColor = _config.chartLineColor.CGColor; 263 | _shadowLineLayer.strokeColor = _config.shadowLineColor.CGColor; 264 | _lineLayer.lineWidth = _config.chartLineWidth; 265 | _shadowLineLayer.lineWidth = _config.chartLineWidth * 0.8; 266 | _shadowLineLayer.hidden = !_config.showShadowLine; 267 | 268 | CGFloat cirw = _config.indicatorCircleWidth - _config.chartLineWidth; 269 | _circleLayer.frame = (CGRect){{0,0},{cirw,cirw}}; 270 | _circleLayer.path = [UIBezierPath bezierPathWithOvalInRect:_circleLayer.frame].CGPath; 271 | _circleLayer.lineWidth = _config.chartLineWidth; 272 | _circleLayer.strokeColor = _config.chartLineColor.CGColor; 273 | 274 | _gradientLayer.colors = _config.gradientCGColors; 275 | _gradientLayer.locations = _config.gradientLocations; 276 | 277 | _bgLineLayer.strokeColor = _config.bgLineColor.CGColor; 278 | _bgLineLayer.lineDashPattern = @[@(1.5), @(_config.dottedBGLine ? 3 : 0)]; 279 | _bgLineLayer.lineWidth = _config.bglineWidth; 280 | 281 | _bgLineLayer.hidden = !_config.showHorizontalBgline; 282 | 283 | _bottomLineLayer.strokeColor = _config.bgLineColor.CGColor; 284 | _bottomLineLayer.lineWidth = _config.bglineWidth; 285 | 286 | if (self.horizontalDatas.count > 0) { 287 | _bottomTextHeight = [self.horizontalDatas.firstObject.title boundingRectWithSize:CGSizeMake(_config.bottomLabelWidth, CGFLOAT_MAX) options:NSStringDrawingUsesFontLeading context:nil].size.height + _config.bottomLabelInset; 288 | } 289 | 290 | _indicator.backgroundColor = _config.indicatorTintColor; 291 | _indicatorLineLayer.backgroundColor = _config.indicatorLineColor.CGColor; 292 | 293 | [_controls enumerateObjectsUsingBlock:^(ORLineChartButton * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { 294 | [obj or_setTintColor:self.config.indicatorTintColor backgroundColor:self.backgroundColor]; 295 | obj.layer.cornerRadius = self.config.indicatorCircleWidth / 2.0; 296 | 297 | if (self.config.indicatorControlImage) { 298 | [obj setImage:self.config.indicatorControlImage forState:UIControlStateNormal]; 299 | [obj setImage:self.config.indicatorControlSelectedImage forState:UIControlStateSelected]; 300 | obj.layer.borderWidth = 0; 301 | [obj or_setTintColor:[UIColor clearColor] backgroundColor:[UIColor clearColor]]; 302 | 303 | }else { 304 | obj.layer.borderWidth = self.config.chartLineWidth; 305 | [obj or_setTintColor:self.config.indicatorTintColor backgroundColor:self.backgroundColor]; 306 | } 307 | 308 | }]; 309 | 310 | 311 | [self.collectionView reloadData]; 312 | [self setNeedsLayout]; 313 | } 314 | 315 | - (void)_or_layoutSubviews { 316 | 317 | if (self.horizontalDatas.count == 0) { 318 | return; 319 | } 320 | 321 | _circleLayer.fillColor = self.backgroundColor.CGColor; 322 | 323 | self.collectionView.frame = CGRectMake(_config.leftWidth, 324 | _config.topInset, 325 | self.bounds.size.width - _config.leftWidth, 326 | self.bounds.size.height - _config.topInset - _config.bottomInset); 327 | 328 | _gradientLayer.frame = CGRectMake(0, 0, 0, self.collectionView.bounds.size.height); 329 | 330 | CGFloat indecaterHeight = _indicator.bounds.size.height; 331 | 332 | 333 | CGFloat topHeight = indecaterHeight * 2; 334 | 335 | CGFloat height = self.collectionView.bounds.size.height; 336 | 337 | CGFloat labelHeight = (height - topHeight - _bottomTextHeight) / (self.leftLabels.count - 1); 338 | 339 | CGFloat labelInset = 0; 340 | 341 | 342 | if (self.leftLabels.count > 0) { 343 | 344 | [self.leftLabels.firstObject sizeToFit]; 345 | labelInset = labelHeight - self.leftLabels.firstObject.bounds.size.height; 346 | labelHeight = self.leftLabels.firstObject.bounds.size.height; 347 | } 348 | 349 | UIBezierPath *path = [UIBezierPath bezierPath]; 350 | [self.leftLabels enumerateObjectsUsingBlock:^(UILabel * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { 351 | 352 | obj.frame = CGRectMake(0, self.bounds.size.height - self.bottomTextHeight - self.config.bottomInset - labelHeight * 0.5 - (labelHeight + labelInset) * idx, self.config.leftWidth, labelHeight); 353 | 354 | if (idx > 0) { 355 | [path moveToPoint:CGPointMake(self.config.leftWidth, obj.center.y)]; 356 | [path addLineToPoint:CGPointMake(self.bounds.size.width, obj.center.y)]; 357 | }else { 358 | UIBezierPath *path = [UIBezierPath bezierPath]; 359 | [path moveToPoint:CGPointMake(self.config.leftWidth, obj.center.y)]; 360 | [path addLineToPoint:CGPointMake(self.bounds.size.width, obj.center.y)]; 361 | self.bottomLineLayer.path = path.CGPath; 362 | } 363 | }]; 364 | 365 | _bgLineLayer.path = path.CGPath; 366 | 367 | CGFloat ratio = (self.lineChartValue.max == self.lineChartValue.min) ? (float)1 :(CGFloat)(self.lineChartValue.min - self.lineChartValue.max); 368 | 369 | NSMutableArray *points = [NSMutableArray array]; 370 | 371 | CGFloat maxX = _config.bottomLabelWidth * _horizontalDatas.count + _collectionView.contentInset.right; 372 | 373 | [self.horizontalDatas enumerateObjectsUsingBlock:^(ORLineChartHorizontal * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { 374 | 375 | 376 | CGFloat y = ORInterpolation(topHeight, height - self.bottomTextHeight, (obj.value - self.lineChartValue.max) / ratio); 377 | 378 | if (idx == 0) { 379 | [points addObject:[NSValue valueWithCGPoint:CGPointMake(-self.collectionView.contentInset.left, y)]]; 380 | } 381 | 382 | CGPoint center = CGPointMake(self.config.bottomLabelWidth * 0.5 + idx * self.config.bottomLabelWidth, y); 383 | 384 | [points addObject:[NSValue valueWithCGPoint:center]]; 385 | 386 | if (idx < self.controls.count) { 387 | CGFloat cirW = self.config.indicatorCircleWidth; 388 | self.controls[idx].frame = CGRectMake(center.x - cirW / 2.0, center.y - cirW / 2.0, cirW, cirW); 389 | } 390 | 391 | if (idx == self.horizontalDatas.count - 1) { 392 | [points addObject:[NSValue valueWithCGPoint:CGPointMake(maxX, y)]]; 393 | } 394 | }]; 395 | 396 | BOOL isCurve = !self.config.isBreakLine; 397 | 398 | UIBezierPath *linePath = [ORChartUtilities or_pathWithPoints:points isCurve:isCurve]; 399 | _lineLayer.path = [linePath.copy CGPath]; 400 | 401 | [linePath applyTransform:CGAffineTransformMakeTranslation(0, 8)]; 402 | _shadowLineLayer.path = [linePath.copy CGPath]; 403 | 404 | _closeLayer.path = [ORChartUtilities or_closePathWithPoints:points isCurve:isCurve maxY: height - self.bottomTextHeight].CGPath; 405 | 406 | 407 | [points removeLastObject]; 408 | [points removeObjectAtIndex:0]; 409 | 410 | _circleLayer.position = [points.lastObject CGPointValue]; 411 | 412 | UIBezierPath *ainmationPath = [ORChartUtilities or_pathWithPoints:points isCurve:isCurve]; 413 | 414 | _animationLayer.timeOffset = 0.0; 415 | _circleLayer.timeOffset = 0.0; 416 | 417 | [_circleLayer removeAnimationForKey:@"or_circleMove"]; 418 | [_circleLayer addAnimation:[self _or_positionAnimationWithPath:[ainmationPath.copy CGPath]] forKey:@"or_circleMove"]; 419 | 420 | [ainmationPath applyTransform:CGAffineTransformMakeTranslation(0, - indecaterHeight)]; 421 | [_animationLayer removeAnimationForKey:@"or_circleMove"]; 422 | [_animationLayer addAnimation:[self _or_positionAnimationWithPath:ainmationPath.CGPath] forKey:@"or_circleMove"]; 423 | 424 | 425 | if (_defaultSelectIndex == 0 || points.count <= 1) { 426 | CGPoint fistValue = [points.firstObject CGPointValue]; 427 | _indicator.center = CGPointMake(fistValue.x, fistValue.y - indecaterHeight); 428 | [self _or_updateIndcaterLineFrame]; 429 | } 430 | 431 | 432 | if (_config.animateDuration > 0) { 433 | [_lineLayer addAnimation:[ORChartUtilities or_strokeAnimationWithDurantion:_config.animateDuration] forKey:nil]; 434 | [_shadowLineLayer addAnimation:[ORChartUtilities or_strokeAnimationWithDurantion:_config.animateDuration] forKey:nil]; 435 | 436 | CABasicAnimation *anmi1 = [CABasicAnimation animation]; 437 | anmi1.keyPath = @"bounds.size.width"; 438 | anmi1.duration = _config.animateDuration; 439 | anmi1.toValue = @(maxX * 2); 440 | 441 | anmi1.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; 442 | anmi1.fillMode = kCAFillModeForwards; 443 | anmi1.autoreverses = NO; 444 | anmi1.removedOnCompletion = NO; 445 | [_gradientLayer addAnimation:anmi1 forKey:@"bw"]; 446 | }else { 447 | _gradientLayer.bounds = CGRectMake(0, 0, maxX * 2, self.collectionView.bounds.size.height); 448 | } 449 | 450 | } 451 | 452 | - (CAAnimation *)_or_positionAnimationWithPath:(CGPathRef)path { 453 | CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"position"]; 454 | animation.duration = 1.0f; 455 | animation.path = path; 456 | animation.removedOnCompletion = NO; 457 | animation.fillMode = kCAFillModeBoth; 458 | return animation; 459 | } 460 | 461 | - (void)_or_updateIndcaterLineFrame { 462 | 463 | [CATransaction begin]; 464 | [CATransaction setDisableActions:YES]; 465 | CGFloat midY = CGRectGetMidY(self.leftLabels.firstObject.frame); 466 | _indicatorLineLayer.frame = CGRectMake(_indicator.center.x - _config.indicatorLineWidth / 2.0, CGRectGetMaxY(_indicator.frame), _config.indicatorLineWidth, midY - CGRectGetMaxY(_indicator.frame)); 467 | [CATransaction commit]; 468 | } 469 | 470 | - (void)_or_action_circle:(ORLineChartButton *)sender { 471 | [self _or_action_circle:sender animated:YES]; 472 | } 473 | 474 | - (void)_or_action_circle:(ORLineChartButton *)sender animated:(BOOL)animated { 475 | 476 | for (UIButton*btn in _controls) { 477 | if ([sender isEqual:btn]) { 478 | btn.selected = YES; 479 | }else{ 480 | btn.selected = NO; 481 | } 482 | } 483 | 484 | NSInteger index = [_controls indexOfObject:sender]; 485 | 486 | if (animated) { 487 | [UIView animateWithDuration:0.2 animations:^{ 488 | self.indicator.center = CGPointMake(sender.center.x, sender.center.y - self.indicator.bounds.size.height); 489 | [self _or_setIndictorTitleWithIndex:index]; 490 | }]; 491 | }else { 492 | self.indicator.center = CGPointMake(sender.center.x, sender.center.y - self.indicator.bounds.size.height); 493 | [self _or_setIndictorTitleWithIndex:index]; 494 | } 495 | 496 | [_collectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:index inSection:0] atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:animated]; 497 | [_delegate chartView:self didSelectValueAtIndex:index]; 498 | } 499 | 500 | - (void)_or_setIndictorTitleWithIndex:(NSInteger)index { 501 | 502 | NSAttributedString *title = [_dataSource chartView:self attributedStringForIndicaterAtIndex:index]; 503 | if (!title) { 504 | title = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"%g", self.horizontalDatas[index].value]]; 505 | } 506 | [_indicator or_setTitle:title inset:_config.indicatorContentInset]; 507 | } 508 | 509 | - (void)reloadData { 510 | 511 | if (!_dataSource) { 512 | return; 513 | } 514 | 515 | _lastIndex = -1; 516 | 517 | NSInteger items = [_dataSource numberOfHorizontalDataOfChartView:self]; 518 | 519 | [self.horizontalDatas removeAllObjects]; 520 | 521 | BOOL isIndicator = _config.style == ORLineChartStyleSlider; 522 | 523 | [CATransaction begin]; 524 | [CATransaction setDisableActions:YES]; 525 | _circleLayer.hidden = !isIndicator; 526 | _indicatorLineLayer.hidden = !isIndicator; 527 | [CATransaction commit]; 528 | 529 | if (isIndicator) { 530 | [_controls makeObjectsPerformSelector:@selector(removeFromSuperview)]; 531 | [_controls removeAllObjects]; 532 | } 533 | 534 | if (items == 0) { 535 | [_collectionView reloadData]; 536 | return; 537 | } 538 | 539 | for (int i = 0; i < items; i ++) { 540 | 541 | ORLineChartHorizontal *horizontal = [ORLineChartHorizontal new]; 542 | horizontal.value = [_dataSource chartView:self valueForHorizontalAtIndex:i]; 543 | 544 | horizontal.title = [[NSAttributedString alloc] initWithString:[_dataSource chartView:self titleForHorizontalAtIndex:i] attributes:[_dataSource labelAttrbutesForHorizontalOfChartView:self]]; 545 | 546 | [self.horizontalDatas addObject:horizontal]; 547 | } 548 | 549 | 550 | if (_config.style == ORLineChartStyleControl) { 551 | 552 | if (_controls.count > items) { 553 | for (NSInteger i = items; i < _controls.count; i ++) { 554 | ORLineChartButton *btn = _controls[i]; 555 | [btn removeFromSuperview]; 556 | [_controls removeObject:btn]; 557 | } 558 | }else if (_controls.count < items) { 559 | for (NSInteger i = _controls.count; i < items; i ++) { 560 | ORLineChartButton *ctrl = [ORLineChartButton new]; 561 | [_collectionView addSubview:ctrl]; 562 | [ctrl addTarget:self action:@selector(_or_action_circle:) forControlEvents:UIControlEventTouchUpInside]; 563 | if (i == 0) { 564 | ctrl.selected = YES; 565 | } 566 | [_controls addObject:ctrl]; 567 | } 568 | } 569 | } 570 | 571 | NSInteger vertical = [_dataSource numberOfVerticalLinesOfChartView:self]; 572 | 573 | if ([self.dataSource respondsToSelector:@selector(chartView:valueOfVerticalSeparateAtIndex:)]) { 574 | 575 | NSMutableArray *values = [NSMutableArray arrayWithCapacity:vertical]; 576 | for (int i = 0; i < vertical; i ++) { 577 | [values addObject:@([self.dataSource chartView:self valueOfVerticalSeparateAtIndex:i])]; 578 | } 579 | _lineChartValue = [[ORLineChartValue alloc] initWithData:values]; 580 | }else { 581 | _lineChartValue = [[ORLineChartValue alloc] initWithHorizontalData:self.horizontalDatas numberWithSeparate:vertical]; 582 | } 583 | 584 | if (self.leftLabels.count > vertical) { 585 | for (NSInteger i = vertical; i < _leftLabels.count; i ++) { 586 | UILabel *label = _leftLabels[i]; 587 | [label removeFromSuperview]; 588 | [_leftLabels removeObject:label]; 589 | } 590 | }else if (self.leftLabels.count < vertical) { 591 | for (NSInteger i = self.leftLabels.count; i < vertical; i ++) { 592 | UILabel *label = [UILabel new]; 593 | label.textAlignment = NSTextAlignmentCenter; 594 | [_leftLabels addObject:label]; 595 | [self addSubview:label]; 596 | } 597 | } 598 | 599 | [self.leftLabels enumerateObjectsUsingBlock:^(UILabel * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { 600 | 601 | NSString *value = self.lineChartValue.isDecimal ? [NSString stringWithFormat:@"%.2lf", self.lineChartValue.separatedValues[idx].doubleValue] : [NSString stringWithFormat:@"%.0lf", self.lineChartValue.separatedValues[idx].doubleValue]; 602 | 603 | obj.attributedText = [[NSAttributedString alloc] initWithString:value attributes:[self.dataSource labelAttrbutesForVerticalOfChartView:self]]; 604 | }]; 605 | 606 | 607 | NSAttributedString *lastTitle = [_dataSource chartView:self attributedStringForIndicaterAtIndex:items - 1]; 608 | if (!lastTitle) { 609 | lastTitle = self.leftLabels.firstObject.attributedText; 610 | } 611 | [_indicator or_setTitle:lastTitle inset:_config.indicatorContentInset]; 612 | CGFloat rightInset = MAX((_indicator.bounds.size.width - _config.bottomLabelWidth) / 2.0 + _config.contentMargin, 0); 613 | 614 | NSAttributedString *title = [_dataSource chartView:self attributedStringForIndicaterAtIndex:0]; 615 | if (!title) { 616 | title = self.leftLabels.firstObject.attributedText; 617 | } 618 | [_indicator or_setTitle:title inset:_config.indicatorContentInset]; 619 | CGFloat leftInset = MAX((_indicator.bounds.size.width - _config.bottomLabelWidth) / 2.0 + _config.contentMargin, 0); 620 | 621 | self.collectionView.contentInset = UIEdgeInsetsMake(0, leftInset, 0, rightInset); 622 | 623 | if (self.collectionView.contentOffset.x != -leftInset) { 624 | [self.collectionView setContentOffset:CGPointMake(-leftInset, 0) animated:YES]; 625 | } 626 | 627 | 628 | [self _or_configChart]; 629 | 630 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.01 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 631 | [self showDataAtIndex:self.defaultSelectIndex animated:NO]; 632 | }); 633 | } 634 | 635 | - (void)showDataAtIndex:(NSInteger)index animated:(BOOL)animated { 636 | 637 | if (index >= self.horizontalDatas.count) { 638 | return; 639 | } 640 | 641 | NSIndexPath *indexPath = [NSIndexPath indexPathForItem:index inSection:0]; 642 | 643 | if (self.config.style == ORLineChartStyleSlider) { 644 | 645 | UICollectionViewLayoutAttributes *attr = [_collectionView layoutAttributesForItemAtIndexPath:indexPath]; 646 | 647 | if (_collectionView.contentSize.width < _collectionView.bounds.size.width) { 648 | 649 | CGFloat ratio = attr.frame.origin.x / (_collectionView.contentSize.width - attr.frame.size.width); 650 | ratio = fmin(fmax(0.0, ratio), 1.0); 651 | 652 | _circleLayer.timeOffset = ratio; 653 | _animationLayer.timeOffset = ratio; 654 | _indicator.center = _animationLayer.presentationLayer.position; 655 | [self _or_updateIndcaterLineFrame]; 656 | if (index != _lastIndex) { 657 | [self _or_setIndictorTitleWithIndex:index]; 658 | _lastIndex = index; 659 | [_delegate chartView:self indicatorDidChangeValueAtIndex:index]; 660 | } 661 | return; 662 | } 663 | 664 | if (_collectionView.contentSize.width - attr.frame.size.width == 0) { 665 | return; 666 | } 667 | 668 | CGFloat offset = (attr.center.x - attr.frame.size.width / 2.0) * (_collectionView.contentSize.width + _collectionView.contentInset.left + _collectionView.contentInset.right - _collectionView.bounds.size.width) / (_collectionView.contentSize.width - attr.frame.size.width)- _collectionView.contentInset.left; 669 | 670 | [_collectionView setContentOffset:CGPointMake(offset, 0) animated:animated]; 671 | }else { 672 | [self _or_action_circle:self.controls[index] animated:animated]; 673 | } 674 | 675 | } 676 | 677 | - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { 678 | return self.horizontalDatas.count; 679 | } 680 | 681 | - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { 682 | ORLineChartCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:NSStringFromClass([ORLineChartCell class]) forIndexPath:indexPath]; 683 | cell.title = self.horizontalDatas[indexPath.row].title; 684 | cell.config = self.config; 685 | return cell; 686 | } 687 | 688 | - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { 689 | return CGSizeMake(_config.bottomLabelWidth, collectionView.bounds.size.height);//collectionView.bounds.size.height 690 | } 691 | 692 | 693 | - (void)scrollViewDidScroll:(UIScrollView *)scrollView { 694 | 695 | if (_config.style != ORLineChartStyleSlider) { 696 | return; 697 | } 698 | 699 | CGFloat ratio = (scrollView.contentOffset.x + scrollView.contentInset.left) / (scrollView.contentSize.width + scrollView.contentInset.left + scrollView.contentInset.right - scrollView.bounds.size.width); 700 | ratio = fmin(fmax(0.0, ratio), 1.0); 701 | 702 | _circleLayer.timeOffset = ratio; 703 | _animationLayer.timeOffset = ratio; 704 | _indicator.center = _animationLayer.presentationLayer.position; 705 | [self _or_updateIndcaterLineFrame]; 706 | 707 | NSInteger index = floor(_indicator.center.x / _config.bottomLabelWidth); 708 | 709 | if (index == _lastIndex) { 710 | return; 711 | } 712 | [self _or_setIndictorTitleWithIndex:index]; 713 | _lastIndex = index; 714 | [_delegate chartView:self indicatorDidChangeValueAtIndex:index]; 715 | } 716 | 717 | - (void)setDataSource:(id)dataSource { 718 | if (_dataSource != dataSource) { 719 | _dataSource = dataSource; 720 | if (_dataSource) { 721 | [self reloadData]; 722 | } 723 | } 724 | } 725 | 726 | - (void)setConfig:(ORLineChartConfig *)config { 727 | if (_config != config) { 728 | _config = config; 729 | if (_dataSource) { 730 | [self _or_configChart]; 731 | } 732 | } 733 | } 734 | 735 | - (void)setDefaultSelectIndex:(NSInteger)defaultSelectIndex { 736 | if (_defaultSelectIndex != defaultSelectIndex) { 737 | _defaultSelectIndex = defaultSelectIndex; 738 | if (_dataSource) { 739 | [self reloadData]; 740 | } 741 | } 742 | } 743 | 744 | @end 745 | -------------------------------------------------------------------------------- /Example/ORCharts.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 381AC5762376605E3C565BA6 /* Pods_ORCharts_Example.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 08B3D0931BEADB0D872E24DE /* Pods_ORCharts_Example.framework */; }; 11 | 4D24657322DAE953008C7DC4 /* ORLineMoreViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4D24656B22DAE953008C7DC4 /* ORLineMoreViewController.m */; }; 12 | 4D24657422DAE953008C7DC4 /* ORLineViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4D24656C22DAE953008C7DC4 /* ORLineViewController.m */; }; 13 | 4D24657522DAE953008C7DC4 /* ORRingViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4D24657122DAE953008C7DC4 /* ORRingViewController.m */; }; 14 | 4D24657622DAE953008C7DC4 /* ORRingMoreViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4D24657222DAE953008C7DC4 /* ORRingMoreViewController.m */; }; 15 | 4D24657922DAE9F6008C7DC4 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4D24657722DAE9F6008C7DC4 /* Main.storyboard */; }; 16 | 6003F58E195388D20070C39A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F58D195388D20070C39A /* Foundation.framework */; }; 17 | 6003F590195388D20070C39A /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F58F195388D20070C39A /* CoreGraphics.framework */; }; 18 | 6003F592195388D20070C39A /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F591195388D20070C39A /* UIKit.framework */; }; 19 | 6003F598195388D20070C39A /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 6003F596195388D20070C39A /* InfoPlist.strings */; }; 20 | 6003F59A195388D20070C39A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6003F599195388D20070C39A /* main.m */; }; 21 | 6003F59E195388D20070C39A /* ORAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6003F59D195388D20070C39A /* ORAppDelegate.m */; }; 22 | 6003F5A9195388D20070C39A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6003F5A8195388D20070C39A /* Images.xcassets */; }; 23 | 6003F5B0195388D20070C39A /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F5AF195388D20070C39A /* XCTest.framework */; }; 24 | 6003F5B1195388D20070C39A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F58D195388D20070C39A /* Foundation.framework */; }; 25 | 6003F5B2195388D20070C39A /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F591195388D20070C39A /* UIKit.framework */; }; 26 | 6003F5BA195388D20070C39A /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 6003F5B8195388D20070C39A /* InfoPlist.strings */; }; 27 | 6003F5BC195388D20070C39A /* Tests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6003F5BB195388D20070C39A /* Tests.m */; }; 28 | 71719F9F1E33DC2100824A3D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 71719F9D1E33DC2100824A3D /* LaunchScreen.storyboard */; }; 29 | F5D55FA0C286EB73F1207796 /* Pods_ORCharts_Tests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 59C3436686D21FF2A9D678A0 /* Pods_ORCharts_Tests.framework */; }; 30 | /* End PBXBuildFile section */ 31 | 32 | /* Begin PBXContainerItemProxy section */ 33 | 6003F5B3195388D20070C39A /* PBXContainerItemProxy */ = { 34 | isa = PBXContainerItemProxy; 35 | containerPortal = 6003F582195388D10070C39A /* Project object */; 36 | proxyType = 1; 37 | remoteGlobalIDString = 6003F589195388D20070C39A; 38 | remoteInfo = ORCharts; 39 | }; 40 | /* End PBXContainerItemProxy section */ 41 | 42 | /* Begin PBXFileReference section */ 43 | 08B3D0931BEADB0D872E24DE /* Pods_ORCharts_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ORCharts_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 44 | 0BF8A334FA082B880AF3F9CA /* Pods-ORCharts_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ORCharts_Tests.release.xcconfig"; path = "Target Support Files/Pods-ORCharts_Tests/Pods-ORCharts_Tests.release.xcconfig"; sourceTree = ""; }; 45 | 2148E5AA6007CB0EF36E9958 /* Pods-ORCharts_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ORCharts_Example.release.xcconfig"; path = "Target Support Files/Pods-ORCharts_Example/Pods-ORCharts_Example.release.xcconfig"; sourceTree = ""; }; 46 | 2E09BAC07881ABC400C13EC8 /* ORCharts.podspec */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = ORCharts.podspec; path = ../ORCharts.podspec; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; 47 | 4D24656A22DAE953008C7DC4 /* ORLineViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ORLineViewController.h; sourceTree = ""; }; 48 | 4D24656B22DAE953008C7DC4 /* ORLineMoreViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ORLineMoreViewController.m; sourceTree = ""; }; 49 | 4D24656C22DAE953008C7DC4 /* ORLineViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ORLineViewController.m; sourceTree = ""; }; 50 | 4D24656D22DAE953008C7DC4 /* ORLineMoreViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ORLineMoreViewController.h; sourceTree = ""; }; 51 | 4D24656F22DAE953008C7DC4 /* ORRingViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ORRingViewController.h; sourceTree = ""; }; 52 | 4D24657022DAE953008C7DC4 /* ORRingMoreViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ORRingMoreViewController.h; sourceTree = ""; }; 53 | 4D24657122DAE953008C7DC4 /* ORRingViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ORRingViewController.m; sourceTree = ""; }; 54 | 4D24657222DAE953008C7DC4 /* ORRingMoreViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ORRingMoreViewController.m; sourceTree = ""; }; 55 | 4D24657822DAE9F6008C7DC4 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 56 | 59C3436686D21FF2A9D678A0 /* Pods_ORCharts_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ORCharts_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 57 | 6003F58A195388D20070C39A /* ORCharts_Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ORCharts_Example.app; sourceTree = BUILT_PRODUCTS_DIR; }; 58 | 6003F58D195388D20070C39A /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 59 | 6003F58F195388D20070C39A /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 60 | 6003F591195388D20070C39A /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 61 | 6003F595195388D20070C39A /* ORCharts-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "ORCharts-Info.plist"; sourceTree = ""; }; 62 | 6003F597195388D20070C39A /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 63 | 6003F599195388D20070C39A /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 64 | 6003F59B195388D20070C39A /* ORCharts-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ORCharts-Prefix.pch"; sourceTree = ""; }; 65 | 6003F59C195388D20070C39A /* ORAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ORAppDelegate.h; sourceTree = ""; }; 66 | 6003F59D195388D20070C39A /* ORAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ORAppDelegate.m; sourceTree = ""; }; 67 | 6003F5A8195388D20070C39A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 68 | 6003F5AE195388D20070C39A /* ORCharts_Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ORCharts_Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 69 | 6003F5AF195388D20070C39A /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; 70 | 6003F5B7195388D20070C39A /* Tests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Tests-Info.plist"; sourceTree = ""; }; 71 | 6003F5B9195388D20070C39A /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 72 | 6003F5BB195388D20070C39A /* Tests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Tests.m; sourceTree = ""; }; 73 | 606FC2411953D9B200FFA9A0 /* Tests-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Tests-Prefix.pch"; sourceTree = ""; }; 74 | 71719F9E1E33DC2100824A3D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 75 | 85CBC59FDA69D8E87BDF5115 /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = LICENSE; path = ../LICENSE; sourceTree = ""; }; 76 | A267DAA113F2828FB9C0D16E /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = ""; }; 77 | AA8485C4B46FB0D93BF161EC /* Pods-ORCharts_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ORCharts_Example.debug.xcconfig"; path = "Target Support Files/Pods-ORCharts_Example/Pods-ORCharts_Example.debug.xcconfig"; sourceTree = ""; }; 78 | E09E36CCE61BEA438DA88D15 /* Pods-ORCharts_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ORCharts_Tests.debug.xcconfig"; path = "Target Support Files/Pods-ORCharts_Tests/Pods-ORCharts_Tests.debug.xcconfig"; sourceTree = ""; }; 79 | /* End PBXFileReference section */ 80 | 81 | /* Begin PBXFrameworksBuildPhase section */ 82 | 6003F587195388D20070C39A /* Frameworks */ = { 83 | isa = PBXFrameworksBuildPhase; 84 | buildActionMask = 2147483647; 85 | files = ( 86 | 6003F590195388D20070C39A /* CoreGraphics.framework in Frameworks */, 87 | 6003F592195388D20070C39A /* UIKit.framework in Frameworks */, 88 | 6003F58E195388D20070C39A /* Foundation.framework in Frameworks */, 89 | 381AC5762376605E3C565BA6 /* Pods_ORCharts_Example.framework in Frameworks */, 90 | ); 91 | runOnlyForDeploymentPostprocessing = 0; 92 | }; 93 | 6003F5AB195388D20070C39A /* Frameworks */ = { 94 | isa = PBXFrameworksBuildPhase; 95 | buildActionMask = 2147483647; 96 | files = ( 97 | 6003F5B0195388D20070C39A /* XCTest.framework in Frameworks */, 98 | 6003F5B2195388D20070C39A /* UIKit.framework in Frameworks */, 99 | 6003F5B1195388D20070C39A /* Foundation.framework in Frameworks */, 100 | F5D55FA0C286EB73F1207796 /* Pods_ORCharts_Tests.framework in Frameworks */, 101 | ); 102 | runOnlyForDeploymentPostprocessing = 0; 103 | }; 104 | /* End PBXFrameworksBuildPhase section */ 105 | 106 | /* Begin PBXGroup section */ 107 | 4D24656822DAE953008C7DC4 /* Controller */ = { 108 | isa = PBXGroup; 109 | children = ( 110 | 4D24656922DAE953008C7DC4 /* LineChartVC */, 111 | 4D24656E22DAE953008C7DC4 /* RingChartVC */, 112 | ); 113 | path = Controller; 114 | sourceTree = ""; 115 | }; 116 | 4D24656922DAE953008C7DC4 /* LineChartVC */ = { 117 | isa = PBXGroup; 118 | children = ( 119 | 4D24656A22DAE953008C7DC4 /* ORLineViewController.h */, 120 | 4D24656C22DAE953008C7DC4 /* ORLineViewController.m */, 121 | 4D24656B22DAE953008C7DC4 /* ORLineMoreViewController.m */, 122 | 4D24656D22DAE953008C7DC4 /* ORLineMoreViewController.h */, 123 | ); 124 | path = LineChartVC; 125 | sourceTree = ""; 126 | }; 127 | 4D24656E22DAE953008C7DC4 /* RingChartVC */ = { 128 | isa = PBXGroup; 129 | children = ( 130 | 4D24656F22DAE953008C7DC4 /* ORRingViewController.h */, 131 | 4D24657122DAE953008C7DC4 /* ORRingViewController.m */, 132 | 4D24657022DAE953008C7DC4 /* ORRingMoreViewController.h */, 133 | 4D24657222DAE953008C7DC4 /* ORRingMoreViewController.m */, 134 | ); 135 | path = RingChartVC; 136 | sourceTree = ""; 137 | }; 138 | 6003F581195388D10070C39A = { 139 | isa = PBXGroup; 140 | children = ( 141 | 60FF7A9C1954A5C5007DD14C /* Podspec Metadata */, 142 | 6003F593195388D20070C39A /* Example for ORCharts */, 143 | 6003F5B5195388D20070C39A /* Tests */, 144 | 6003F58C195388D20070C39A /* Frameworks */, 145 | 6003F58B195388D20070C39A /* Products */, 146 | 621932F9DE820F1CAF50C3FE /* Pods */, 147 | ); 148 | sourceTree = ""; 149 | }; 150 | 6003F58B195388D20070C39A /* Products */ = { 151 | isa = PBXGroup; 152 | children = ( 153 | 6003F58A195388D20070C39A /* ORCharts_Example.app */, 154 | 6003F5AE195388D20070C39A /* ORCharts_Tests.xctest */, 155 | ); 156 | name = Products; 157 | sourceTree = ""; 158 | }; 159 | 6003F58C195388D20070C39A /* Frameworks */ = { 160 | isa = PBXGroup; 161 | children = ( 162 | 6003F58D195388D20070C39A /* Foundation.framework */, 163 | 6003F58F195388D20070C39A /* CoreGraphics.framework */, 164 | 6003F591195388D20070C39A /* UIKit.framework */, 165 | 6003F5AF195388D20070C39A /* XCTest.framework */, 166 | 08B3D0931BEADB0D872E24DE /* Pods_ORCharts_Example.framework */, 167 | 59C3436686D21FF2A9D678A0 /* Pods_ORCharts_Tests.framework */, 168 | ); 169 | name = Frameworks; 170 | sourceTree = ""; 171 | }; 172 | 6003F593195388D20070C39A /* Example for ORCharts */ = { 173 | isa = PBXGroup; 174 | children = ( 175 | 4D24656822DAE953008C7DC4 /* Controller */, 176 | 6003F59C195388D20070C39A /* ORAppDelegate.h */, 177 | 6003F59D195388D20070C39A /* ORAppDelegate.m */, 178 | 4D24657722DAE9F6008C7DC4 /* Main.storyboard */, 179 | 71719F9D1E33DC2100824A3D /* LaunchScreen.storyboard */, 180 | 6003F5A8195388D20070C39A /* Images.xcassets */, 181 | 6003F594195388D20070C39A /* Supporting Files */, 182 | ); 183 | name = "Example for ORCharts"; 184 | path = ORCharts; 185 | sourceTree = ""; 186 | }; 187 | 6003F594195388D20070C39A /* Supporting Files */ = { 188 | isa = PBXGroup; 189 | children = ( 190 | 6003F595195388D20070C39A /* ORCharts-Info.plist */, 191 | 6003F596195388D20070C39A /* InfoPlist.strings */, 192 | 6003F599195388D20070C39A /* main.m */, 193 | 6003F59B195388D20070C39A /* ORCharts-Prefix.pch */, 194 | ); 195 | name = "Supporting Files"; 196 | sourceTree = ""; 197 | }; 198 | 6003F5B5195388D20070C39A /* Tests */ = { 199 | isa = PBXGroup; 200 | children = ( 201 | 6003F5BB195388D20070C39A /* Tests.m */, 202 | 6003F5B6195388D20070C39A /* Supporting Files */, 203 | ); 204 | path = Tests; 205 | sourceTree = ""; 206 | }; 207 | 6003F5B6195388D20070C39A /* Supporting Files */ = { 208 | isa = PBXGroup; 209 | children = ( 210 | 6003F5B7195388D20070C39A /* Tests-Info.plist */, 211 | 6003F5B8195388D20070C39A /* InfoPlist.strings */, 212 | 606FC2411953D9B200FFA9A0 /* Tests-Prefix.pch */, 213 | ); 214 | name = "Supporting Files"; 215 | sourceTree = ""; 216 | }; 217 | 60FF7A9C1954A5C5007DD14C /* Podspec Metadata */ = { 218 | isa = PBXGroup; 219 | children = ( 220 | 2E09BAC07881ABC400C13EC8 /* ORCharts.podspec */, 221 | A267DAA113F2828FB9C0D16E /* README.md */, 222 | 85CBC59FDA69D8E87BDF5115 /* LICENSE */, 223 | ); 224 | name = "Podspec Metadata"; 225 | sourceTree = ""; 226 | }; 227 | 621932F9DE820F1CAF50C3FE /* Pods */ = { 228 | isa = PBXGroup; 229 | children = ( 230 | AA8485C4B46FB0D93BF161EC /* Pods-ORCharts_Example.debug.xcconfig */, 231 | 2148E5AA6007CB0EF36E9958 /* Pods-ORCharts_Example.release.xcconfig */, 232 | E09E36CCE61BEA438DA88D15 /* Pods-ORCharts_Tests.debug.xcconfig */, 233 | 0BF8A334FA082B880AF3F9CA /* Pods-ORCharts_Tests.release.xcconfig */, 234 | ); 235 | path = Pods; 236 | sourceTree = ""; 237 | }; 238 | /* End PBXGroup section */ 239 | 240 | /* Begin PBXNativeTarget section */ 241 | 6003F589195388D20070C39A /* ORCharts_Example */ = { 242 | isa = PBXNativeTarget; 243 | buildConfigurationList = 6003F5BF195388D20070C39A /* Build configuration list for PBXNativeTarget "ORCharts_Example" */; 244 | buildPhases = ( 245 | D834C0BE172EBCC43E0B493F /* [CP] Check Pods Manifest.lock */, 246 | 6003F586195388D20070C39A /* Sources */, 247 | 6003F587195388D20070C39A /* Frameworks */, 248 | 6003F588195388D20070C39A /* Resources */, 249 | E37EC9BC8A94169A8E948E58 /* [CP] Embed Pods Frameworks */, 250 | ); 251 | buildRules = ( 252 | ); 253 | dependencies = ( 254 | ); 255 | name = ORCharts_Example; 256 | productName = ORCharts; 257 | productReference = 6003F58A195388D20070C39A /* ORCharts_Example.app */; 258 | productType = "com.apple.product-type.application"; 259 | }; 260 | 6003F5AD195388D20070C39A /* ORCharts_Tests */ = { 261 | isa = PBXNativeTarget; 262 | buildConfigurationList = 6003F5C2195388D20070C39A /* Build configuration list for PBXNativeTarget "ORCharts_Tests" */; 263 | buildPhases = ( 264 | 3B13412C4A9B0D801979EAE7 /* [CP] Check Pods Manifest.lock */, 265 | 6003F5AA195388D20070C39A /* Sources */, 266 | 6003F5AB195388D20070C39A /* Frameworks */, 267 | 6003F5AC195388D20070C39A /* Resources */, 268 | ); 269 | buildRules = ( 270 | ); 271 | dependencies = ( 272 | 6003F5B4195388D20070C39A /* PBXTargetDependency */, 273 | ); 274 | name = ORCharts_Tests; 275 | productName = ORChartsTests; 276 | productReference = 6003F5AE195388D20070C39A /* ORCharts_Tests.xctest */; 277 | productType = "com.apple.product-type.bundle.unit-test"; 278 | }; 279 | /* End PBXNativeTarget section */ 280 | 281 | /* Begin PBXProject section */ 282 | 6003F582195388D10070C39A /* Project object */ = { 283 | isa = PBXProject; 284 | attributes = { 285 | CLASSPREFIX = OR; 286 | LastUpgradeCheck = 0720; 287 | ORGANIZATIONNAME = "sunrise_oy@163.com"; 288 | TargetAttributes = { 289 | 6003F589195388D20070C39A = { 290 | DevelopmentTeam = C5297CAY7Y; 291 | }; 292 | 6003F5AD195388D20070C39A = { 293 | TestTargetID = 6003F589195388D20070C39A; 294 | }; 295 | }; 296 | }; 297 | buildConfigurationList = 6003F585195388D10070C39A /* Build configuration list for PBXProject "ORCharts" */; 298 | compatibilityVersion = "Xcode 3.2"; 299 | developmentRegion = English; 300 | hasScannedForEncodings = 0; 301 | knownRegions = ( 302 | English, 303 | en, 304 | Base, 305 | ); 306 | mainGroup = 6003F581195388D10070C39A; 307 | productRefGroup = 6003F58B195388D20070C39A /* Products */; 308 | projectDirPath = ""; 309 | projectRoot = ""; 310 | targets = ( 311 | 6003F589195388D20070C39A /* ORCharts_Example */, 312 | 6003F5AD195388D20070C39A /* ORCharts_Tests */, 313 | ); 314 | }; 315 | /* End PBXProject section */ 316 | 317 | /* Begin PBXResourcesBuildPhase section */ 318 | 6003F588195388D20070C39A /* Resources */ = { 319 | isa = PBXResourcesBuildPhase; 320 | buildActionMask = 2147483647; 321 | files = ( 322 | 71719F9F1E33DC2100824A3D /* LaunchScreen.storyboard in Resources */, 323 | 6003F5A9195388D20070C39A /* Images.xcassets in Resources */, 324 | 6003F598195388D20070C39A /* InfoPlist.strings in Resources */, 325 | 4D24657922DAE9F6008C7DC4 /* Main.storyboard in Resources */, 326 | ); 327 | runOnlyForDeploymentPostprocessing = 0; 328 | }; 329 | 6003F5AC195388D20070C39A /* Resources */ = { 330 | isa = PBXResourcesBuildPhase; 331 | buildActionMask = 2147483647; 332 | files = ( 333 | 6003F5BA195388D20070C39A /* InfoPlist.strings in Resources */, 334 | ); 335 | runOnlyForDeploymentPostprocessing = 0; 336 | }; 337 | /* End PBXResourcesBuildPhase section */ 338 | 339 | /* Begin PBXShellScriptBuildPhase section */ 340 | 3B13412C4A9B0D801979EAE7 /* [CP] Check Pods Manifest.lock */ = { 341 | isa = PBXShellScriptBuildPhase; 342 | buildActionMask = 2147483647; 343 | files = ( 344 | ); 345 | inputFileListPaths = ( 346 | ); 347 | inputPaths = ( 348 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 349 | "${PODS_ROOT}/Manifest.lock", 350 | ); 351 | name = "[CP] Check Pods Manifest.lock"; 352 | outputFileListPaths = ( 353 | ); 354 | outputPaths = ( 355 | "$(DERIVED_FILE_DIR)/Pods-ORCharts_Tests-checkManifestLockResult.txt", 356 | ); 357 | runOnlyForDeploymentPostprocessing = 0; 358 | shellPath = /bin/sh; 359 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; 360 | showEnvVarsInLog = 0; 361 | }; 362 | D834C0BE172EBCC43E0B493F /* [CP] Check Pods Manifest.lock */ = { 363 | isa = PBXShellScriptBuildPhase; 364 | buildActionMask = 2147483647; 365 | files = ( 366 | ); 367 | inputFileListPaths = ( 368 | ); 369 | inputPaths = ( 370 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 371 | "${PODS_ROOT}/Manifest.lock", 372 | ); 373 | name = "[CP] Check Pods Manifest.lock"; 374 | outputFileListPaths = ( 375 | ); 376 | outputPaths = ( 377 | "$(DERIVED_FILE_DIR)/Pods-ORCharts_Example-checkManifestLockResult.txt", 378 | ); 379 | runOnlyForDeploymentPostprocessing = 0; 380 | shellPath = /bin/sh; 381 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; 382 | showEnvVarsInLog = 0; 383 | }; 384 | E37EC9BC8A94169A8E948E58 /* [CP] Embed Pods Frameworks */ = { 385 | isa = PBXShellScriptBuildPhase; 386 | buildActionMask = 2147483647; 387 | files = ( 388 | ); 389 | inputPaths = ( 390 | "${PODS_ROOT}/Target Support Files/Pods-ORCharts_Example/Pods-ORCharts_Example-frameworks.sh", 391 | "${BUILT_PRODUCTS_DIR}/ORCharts/ORCharts.framework", 392 | ); 393 | name = "[CP] Embed Pods Frameworks"; 394 | outputPaths = ( 395 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ORCharts.framework", 396 | ); 397 | runOnlyForDeploymentPostprocessing = 0; 398 | shellPath = /bin/sh; 399 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-ORCharts_Example/Pods-ORCharts_Example-frameworks.sh\"\n"; 400 | showEnvVarsInLog = 0; 401 | }; 402 | /* End PBXShellScriptBuildPhase section */ 403 | 404 | /* Begin PBXSourcesBuildPhase section */ 405 | 6003F586195388D20070C39A /* Sources */ = { 406 | isa = PBXSourcesBuildPhase; 407 | buildActionMask = 2147483647; 408 | files = ( 409 | 4D24657322DAE953008C7DC4 /* ORLineMoreViewController.m in Sources */, 410 | 4D24657622DAE953008C7DC4 /* ORRingMoreViewController.m in Sources */, 411 | 4D24657422DAE953008C7DC4 /* ORLineViewController.m in Sources */, 412 | 6003F59E195388D20070C39A /* ORAppDelegate.m in Sources */, 413 | 4D24657522DAE953008C7DC4 /* ORRingViewController.m in Sources */, 414 | 6003F59A195388D20070C39A /* main.m in Sources */, 415 | ); 416 | runOnlyForDeploymentPostprocessing = 0; 417 | }; 418 | 6003F5AA195388D20070C39A /* Sources */ = { 419 | isa = PBXSourcesBuildPhase; 420 | buildActionMask = 2147483647; 421 | files = ( 422 | 6003F5BC195388D20070C39A /* Tests.m in Sources */, 423 | ); 424 | runOnlyForDeploymentPostprocessing = 0; 425 | }; 426 | /* End PBXSourcesBuildPhase section */ 427 | 428 | /* Begin PBXTargetDependency section */ 429 | 6003F5B4195388D20070C39A /* PBXTargetDependency */ = { 430 | isa = PBXTargetDependency; 431 | target = 6003F589195388D20070C39A /* ORCharts_Example */; 432 | targetProxy = 6003F5B3195388D20070C39A /* PBXContainerItemProxy */; 433 | }; 434 | /* End PBXTargetDependency section */ 435 | 436 | /* Begin PBXVariantGroup section */ 437 | 4D24657722DAE9F6008C7DC4 /* Main.storyboard */ = { 438 | isa = PBXVariantGroup; 439 | children = ( 440 | 4D24657822DAE9F6008C7DC4 /* Base */, 441 | ); 442 | name = Main.storyboard; 443 | sourceTree = ""; 444 | }; 445 | 6003F596195388D20070C39A /* InfoPlist.strings */ = { 446 | isa = PBXVariantGroup; 447 | children = ( 448 | 6003F597195388D20070C39A /* en */, 449 | ); 450 | name = InfoPlist.strings; 451 | sourceTree = ""; 452 | }; 453 | 6003F5B8195388D20070C39A /* InfoPlist.strings */ = { 454 | isa = PBXVariantGroup; 455 | children = ( 456 | 6003F5B9195388D20070C39A /* en */, 457 | ); 458 | name = InfoPlist.strings; 459 | sourceTree = ""; 460 | }; 461 | 71719F9D1E33DC2100824A3D /* LaunchScreen.storyboard */ = { 462 | isa = PBXVariantGroup; 463 | children = ( 464 | 71719F9E1E33DC2100824A3D /* Base */, 465 | ); 466 | name = LaunchScreen.storyboard; 467 | sourceTree = ""; 468 | }; 469 | /* End PBXVariantGroup section */ 470 | 471 | /* Begin XCBuildConfiguration section */ 472 | 6003F5BD195388D20070C39A /* Debug */ = { 473 | isa = XCBuildConfiguration; 474 | buildSettings = { 475 | ALWAYS_SEARCH_USER_PATHS = NO; 476 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 477 | CLANG_CXX_LIBRARY = "libc++"; 478 | CLANG_ENABLE_MODULES = YES; 479 | CLANG_ENABLE_OBJC_ARC = YES; 480 | CLANG_WARN_BOOL_CONVERSION = YES; 481 | CLANG_WARN_CONSTANT_CONVERSION = YES; 482 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 483 | CLANG_WARN_EMPTY_BODY = YES; 484 | CLANG_WARN_ENUM_CONVERSION = YES; 485 | CLANG_WARN_INT_CONVERSION = YES; 486 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 487 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 488 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 489 | COPY_PHASE_STRIP = NO; 490 | ENABLE_TESTABILITY = YES; 491 | GCC_C_LANGUAGE_STANDARD = gnu99; 492 | GCC_DYNAMIC_NO_PIC = NO; 493 | GCC_OPTIMIZATION_LEVEL = 0; 494 | GCC_PREPROCESSOR_DEFINITIONS = ( 495 | "DEBUG=1", 496 | "$(inherited)", 497 | ); 498 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 499 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 500 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 501 | GCC_WARN_UNDECLARED_SELECTOR = YES; 502 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 503 | GCC_WARN_UNUSED_FUNCTION = YES; 504 | GCC_WARN_UNUSED_VARIABLE = YES; 505 | IPHONEOS_DEPLOYMENT_TARGET = 9.3; 506 | ONLY_ACTIVE_ARCH = YES; 507 | SDKROOT = iphoneos; 508 | TARGETED_DEVICE_FAMILY = "1,2"; 509 | }; 510 | name = Debug; 511 | }; 512 | 6003F5BE195388D20070C39A /* Release */ = { 513 | isa = XCBuildConfiguration; 514 | buildSettings = { 515 | ALWAYS_SEARCH_USER_PATHS = NO; 516 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 517 | CLANG_CXX_LIBRARY = "libc++"; 518 | CLANG_ENABLE_MODULES = YES; 519 | CLANG_ENABLE_OBJC_ARC = YES; 520 | CLANG_WARN_BOOL_CONVERSION = YES; 521 | CLANG_WARN_CONSTANT_CONVERSION = YES; 522 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 523 | CLANG_WARN_EMPTY_BODY = YES; 524 | CLANG_WARN_ENUM_CONVERSION = YES; 525 | CLANG_WARN_INT_CONVERSION = YES; 526 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 527 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 528 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 529 | COPY_PHASE_STRIP = YES; 530 | ENABLE_NS_ASSERTIONS = NO; 531 | GCC_C_LANGUAGE_STANDARD = gnu99; 532 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 533 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 534 | GCC_WARN_UNDECLARED_SELECTOR = YES; 535 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 536 | GCC_WARN_UNUSED_FUNCTION = YES; 537 | GCC_WARN_UNUSED_VARIABLE = YES; 538 | IPHONEOS_DEPLOYMENT_TARGET = 9.3; 539 | SDKROOT = iphoneos; 540 | TARGETED_DEVICE_FAMILY = "1,2"; 541 | VALIDATE_PRODUCT = YES; 542 | }; 543 | name = Release; 544 | }; 545 | 6003F5C0195388D20070C39A /* Debug */ = { 546 | isa = XCBuildConfiguration; 547 | baseConfigurationReference = AA8485C4B46FB0D93BF161EC /* Pods-ORCharts_Example.debug.xcconfig */; 548 | buildSettings = { 549 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 550 | DEVELOPMENT_TEAM = C5297CAY7Y; 551 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 552 | GCC_PREFIX_HEADER = "ORCharts/ORCharts-Prefix.pch"; 553 | INFOPLIST_FILE = "ORCharts/ORCharts-Info.plist"; 554 | MODULE_NAME = ExampleApp; 555 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.${PRODUCT_NAME:rfc1034identifier}"; 556 | PRODUCT_NAME = "$(TARGET_NAME)"; 557 | SWIFT_VERSION = 4.0; 558 | WRAPPER_EXTENSION = app; 559 | }; 560 | name = Debug; 561 | }; 562 | 6003F5C1195388D20070C39A /* Release */ = { 563 | isa = XCBuildConfiguration; 564 | baseConfigurationReference = 2148E5AA6007CB0EF36E9958 /* Pods-ORCharts_Example.release.xcconfig */; 565 | buildSettings = { 566 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 567 | DEVELOPMENT_TEAM = C5297CAY7Y; 568 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 569 | GCC_PREFIX_HEADER = "ORCharts/ORCharts-Prefix.pch"; 570 | INFOPLIST_FILE = "ORCharts/ORCharts-Info.plist"; 571 | MODULE_NAME = ExampleApp; 572 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.${PRODUCT_NAME:rfc1034identifier}"; 573 | PRODUCT_NAME = "$(TARGET_NAME)"; 574 | SWIFT_VERSION = 4.0; 575 | WRAPPER_EXTENSION = app; 576 | }; 577 | name = Release; 578 | }; 579 | 6003F5C3195388D20070C39A /* Debug */ = { 580 | isa = XCBuildConfiguration; 581 | baseConfigurationReference = E09E36CCE61BEA438DA88D15 /* Pods-ORCharts_Tests.debug.xcconfig */; 582 | buildSettings = { 583 | BUNDLE_LOADER = "$(TEST_HOST)"; 584 | FRAMEWORK_SEARCH_PATHS = ( 585 | "$(PLATFORM_DIR)/Developer/Library/Frameworks", 586 | "$(inherited)", 587 | "$(DEVELOPER_FRAMEWORKS_DIR)", 588 | ); 589 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 590 | GCC_PREFIX_HEADER = "Tests/Tests-Prefix.pch"; 591 | GCC_PREPROCESSOR_DEFINITIONS = ( 592 | "DEBUG=1", 593 | "$(inherited)", 594 | ); 595 | INFOPLIST_FILE = "Tests/Tests-Info.plist"; 596 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.${PRODUCT_NAME:rfc1034identifier}"; 597 | PRODUCT_NAME = "$(TARGET_NAME)"; 598 | SWIFT_VERSION = 4.0; 599 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ORCharts_Example.app/ORCharts_Example"; 600 | WRAPPER_EXTENSION = xctest; 601 | }; 602 | name = Debug; 603 | }; 604 | 6003F5C4195388D20070C39A /* Release */ = { 605 | isa = XCBuildConfiguration; 606 | baseConfigurationReference = 0BF8A334FA082B880AF3F9CA /* Pods-ORCharts_Tests.release.xcconfig */; 607 | buildSettings = { 608 | BUNDLE_LOADER = "$(TEST_HOST)"; 609 | FRAMEWORK_SEARCH_PATHS = ( 610 | "$(PLATFORM_DIR)/Developer/Library/Frameworks", 611 | "$(inherited)", 612 | "$(DEVELOPER_FRAMEWORKS_DIR)", 613 | ); 614 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 615 | GCC_PREFIX_HEADER = "Tests/Tests-Prefix.pch"; 616 | INFOPLIST_FILE = "Tests/Tests-Info.plist"; 617 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.${PRODUCT_NAME:rfc1034identifier}"; 618 | PRODUCT_NAME = "$(TARGET_NAME)"; 619 | SWIFT_VERSION = 4.0; 620 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ORCharts_Example.app/ORCharts_Example"; 621 | WRAPPER_EXTENSION = xctest; 622 | }; 623 | name = Release; 624 | }; 625 | /* End XCBuildConfiguration section */ 626 | 627 | /* Begin XCConfigurationList section */ 628 | 6003F585195388D10070C39A /* Build configuration list for PBXProject "ORCharts" */ = { 629 | isa = XCConfigurationList; 630 | buildConfigurations = ( 631 | 6003F5BD195388D20070C39A /* Debug */, 632 | 6003F5BE195388D20070C39A /* Release */, 633 | ); 634 | defaultConfigurationIsVisible = 0; 635 | defaultConfigurationName = Release; 636 | }; 637 | 6003F5BF195388D20070C39A /* Build configuration list for PBXNativeTarget "ORCharts_Example" */ = { 638 | isa = XCConfigurationList; 639 | buildConfigurations = ( 640 | 6003F5C0195388D20070C39A /* Debug */, 641 | 6003F5C1195388D20070C39A /* Release */, 642 | ); 643 | defaultConfigurationIsVisible = 0; 644 | defaultConfigurationName = Release; 645 | }; 646 | 6003F5C2195388D20070C39A /* Build configuration list for PBXNativeTarget "ORCharts_Tests" */ = { 647 | isa = XCConfigurationList; 648 | buildConfigurations = ( 649 | 6003F5C3195388D20070C39A /* Debug */, 650 | 6003F5C4195388D20070C39A /* Release */, 651 | ); 652 | defaultConfigurationIsVisible = 0; 653 | defaultConfigurationName = Release; 654 | }; 655 | /* End XCConfigurationList section */ 656 | }; 657 | rootObject = 6003F582195388D10070C39A /* Project object */; 658 | } 659 | --------------------------------------------------------------------------------