├── .gitignore ├── .swift-version ├── DemoImage ├── row.png ├── step.png ├── example.png ├── origin.png └── section.png ├── .travis.yml ├── TKRadarChart.xcodeproj ├── xcuserdata │ └── Tbxark.xcuserdatad │ │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ │ └── xcschemes │ │ ├── xcschememanagement.plist │ │ └── TKRadarChartDemo.xcscheme ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcuserdata │ │ └── Tbxark.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── xcshareddata │ └── xcschemes │ │ └── TKRadarChart.xcscheme └── project.pbxproj ├── TKRadarChart.podspec ├── TKRadarChart ├── TKRadarChart.h ├── Info.plist └── TKRadarChart.swift ├── LICENSE ├── TKRadarChartDemo ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── Info.plist ├── Base.lproj │ ├── Main.storyboard │ └── LaunchScreen.storyboard ├── AppDelegate.swift └── ViewController.swift └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | Carthage/ -------------------------------------------------------------------------------- /.swift-version: -------------------------------------------------------------------------------- 1 | 4.0 2 | -------------------------------------------------------------------------------- /DemoImage/row.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TBXark/TKRadarChart/HEAD/DemoImage/row.png -------------------------------------------------------------------------------- /DemoImage/step.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TBXark/TKRadarChart/HEAD/DemoImage/step.png -------------------------------------------------------------------------------- /DemoImage/example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TBXark/TKRadarChart/HEAD/DemoImage/example.png -------------------------------------------------------------------------------- /DemoImage/origin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TBXark/TKRadarChart/HEAD/DemoImage/origin.png -------------------------------------------------------------------------------- /DemoImage/section.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TBXark/TKRadarChart/HEAD/DemoImage/section.png -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | osx_image: xcode7.3 2 | language: swift 3 | 4 | xcode_project: TKRadarChart.xcodeproj 5 | xcode_scheme: TKRadarChart 6 | xcode_sdk: iphonesimulator -------------------------------------------------------------------------------- /TKRadarChart.xcodeproj/xcuserdata/Tbxark.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /TKRadarChart.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /TKRadarChart.xcodeproj/project.xcworkspace/xcuserdata/Tbxark.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TBXark/TKRadarChart/HEAD/TKRadarChart.xcodeproj/project.xcworkspace/xcuserdata/Tbxark.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /TKRadarChart.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /TKRadarChart.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "TKRadarChart" 3 | s.version = "1.4.3" 4 | s.summary = "TKRadarChart is a customizable radar chart " 5 | s.license = { :type => 'MIT License', :file => 'LICENSE' } 6 | s.homepage = "https://github.com/TBXark/TKRadarChart" 7 | s.author = { "TBXark" => "https://github.com/TBXark" } 8 | s.platform = :ios, "8.0" 9 | s.source = { :git => "https://github.com/TBXark/TKRadarChart.git", :tag => s.version } 10 | s.source_files = "TKRadarChart/TKRadarChart.swift" 11 | s.requires_arc = true 12 | end 13 | -------------------------------------------------------------------------------- /TKRadarChart/TKRadarChart.h: -------------------------------------------------------------------------------- 1 | // 2 | // TKRadarChart.h 3 | // TKRadarChart 4 | // 5 | // Created by Tbxark on 27/11/2016. 6 | // Copyright © 2016 Tbxark. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for TKRadarChart. 12 | FOUNDATION_EXPORT double TKRadarChartVersionNumber; 13 | 14 | //! Project version string for TKRadarChart. 15 | FOUNDATION_EXPORT const unsigned char TKRadarChartVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | 20 | -------------------------------------------------------------------------------- /TKRadarChart/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.3.1 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | NSPrincipalClass 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 TBXark 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /TKRadarChart.xcodeproj/xcuserdata/Tbxark.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | TKRadarChart.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 1 11 | 12 | TKRadarChartDemo.xcscheme 13 | 14 | orderHint 15 | 0 16 | 17 | 18 | SuppressBuildableAutocreation 19 | 20 | 6A3F39B41DEB1E1A0067576C 21 | 22 | primary 23 | 24 | 25 | 6A415EEF1DEB1DAC001DBF69 26 | 27 | primary 28 | 29 | 30 | 6A9103D41D538B560009451B 31 | 32 | primary 33 | 34 | 35 | 6A9103E21D538CA30009451B 36 | 37 | primary 38 | 39 | 40 | 6AA47F0E1D35FD3100C5D61F 41 | 42 | primary 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /TKRadarChartDemo/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /TKRadarChartDemo/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 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /TKRadarChartDemo/Base.lproj/Main.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 | -------------------------------------------------------------------------------- /TKRadarChartDemo/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 | -------------------------------------------------------------------------------- /TKRadarChartDemo/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // TKRadarChartDemo 4 | // 5 | // Created by Tbxark on 27/11/2016. 6 | // Copyright © 2016 Tbxark. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | #if swift( >=4.2) 12 | typealias UIApplicationLaunchOptionsKey = UIApplication.LaunchOptionsKey 13 | #endif 14 | 15 | @UIApplicationMain 16 | class AppDelegate: UIResponder, UIApplicationDelegate { 17 | 18 | var window: UIWindow? 19 | 20 | 21 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 22 | // Override point for customization after application launch. 23 | return true 24 | } 25 | 26 | func applicationWillResignActive(_ application: UIApplication) { 27 | // 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. 28 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 29 | } 30 | 31 | func applicationDidEnterBackground(_ application: UIApplication) { 32 | // 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. 33 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 34 | } 35 | 36 | func applicationWillEnterForeground(_ application: UIApplication) { 37 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 38 | } 39 | 40 | func applicationDidBecomeActive(_ application: UIApplication) { 41 | // 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. 42 | } 43 | 44 | func applicationWillTerminate(_ application: UIApplication) { 45 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 46 | } 47 | 48 | 49 | } 50 | 51 | -------------------------------------------------------------------------------- /TKRadarChartDemo/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // TKRadarChartDemo 4 | // 5 | // Created by Tbxark on 27/11/2016. 6 | // Copyright © 2016 Tbxark. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import TKRadarChart 11 | 12 | class ViewController: UIViewController, TKRadarChartDataSource, TKRadarChartDelegate, UITableViewDelegate { 13 | 14 | override func viewDidLoad() { 15 | super.viewDidLoad() 16 | 17 | let w = view.bounds.width 18 | let chart = TKRadarChart(frame: CGRect(x: 0, y: 0, width: w, height: w)) 19 | chart.configuration.radius = w/3 20 | chart.dataSource = self 21 | chart.delegate = self 22 | chart.center = view.center 23 | chart.reloadData() 24 | view.addSubview(chart) 25 | } 26 | 27 | func numberOfStepForRadarChart(_ radarChart: TKRadarChart) -> Int { 28 | return 5 29 | } 30 | func numberOfRowForRadarChart(_ radarChart: TKRadarChart) -> Int { 31 | return 6 32 | } 33 | func numberOfSectionForRadarChart(_ radarChart: TKRadarChart) -> Int { 34 | return 2 35 | } 36 | 37 | func titleOfRowForRadarChart(_ radarChart: TKRadarChart, row: Int) -> String { 38 | return "NO.\(row + 1)" 39 | } 40 | 41 | func valueOfSectionForRadarChart(withRow row: Int, section: Int) -> CGFloat { 42 | if section == 0 { 43 | return CGFloat(max(min(row + 1, 4), 3)) 44 | } else { 45 | return 3 46 | } 47 | } 48 | 49 | 50 | func colorOfLineForRadarChart(_ radarChart: TKRadarChart) -> UIColor { 51 | return UIColor(red:0.337, green:0.847, blue:0.976, alpha:1) 52 | } 53 | 54 | func colorOfFillStepForRadarChart(_ radarChart: TKRadarChart, step: Int) -> UIColor { 55 | switch step { 56 | case 1: 57 | return UIColor(red:0.545, green:0.906, blue:0.996, alpha:1) 58 | case 2: 59 | return UIColor(red:0.706, green:0.929, blue:0.988, alpha:1) 60 | case 3: 61 | return UIColor(red:0.831, green:0.949, blue:0.984, alpha:1) 62 | case 4: 63 | return UIColor(red:0.922, green:0.976, blue:0.988, alpha:1) 64 | default: 65 | return UIColor.white 66 | } 67 | } 68 | 69 | func colorOfSectionFillForRadarChart(_ radarChart: TKRadarChart, section: Int) -> UIColor { 70 | if section == 0 { 71 | return UIColor(red:1, green:0.867, blue:0.012, alpha:0.4) 72 | } else { 73 | return UIColor(red:0, green:0.788, blue:0.543, alpha:0.4) 74 | } 75 | } 76 | 77 | func colorOfSectionBorderForRadarChart(_ radarChart: TKRadarChart, section: Int) -> UIColor { 78 | if section == 0 { 79 | return UIColor(red:1, green:0.867, blue:0.012, alpha:1) 80 | } else { 81 | return UIColor(red:0, green:0.788, blue:0.543, alpha:1) 82 | } 83 | } 84 | 85 | func fontOfTitleForRadarChart(_ radarChart: TKRadarChart) -> UIFont { 86 | return UIFont.systemFont(ofSize: 10) 87 | } 88 | 89 | 90 | 91 | } 92 | -------------------------------------------------------------------------------- /TKRadarChart.xcodeproj/xcshareddata/xcschemes/TKRadarChart.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 33 | 34 | 35 | 36 | 47 | 48 | 54 | 55 | 56 | 57 | 58 | 59 | 65 | 66 | 72 | 73 | 74 | 75 | 77 | 78 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /TKRadarChart.xcodeproj/xcuserdata/Tbxark.xcuserdatad/xcschemes/TKRadarChartDemo.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 33 | 34 | 40 | 41 | 42 | 43 | 44 | 45 | 56 | 58 | 64 | 65 | 66 | 67 | 68 | 69 | 75 | 77 | 83 | 84 | 85 | 86 | 88 | 89 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TKRadarChart 2 | > A customizable radar chart in Swift 3 | 4 | ![Xcode 9.0+](https://img.shields.io/badge/Xcode-9.0%2B-blue.svg) 5 | ![iOS 8.0+](https://img.shields.io/badge/iOS-8.0%2B-blue.svg) 6 | ![Swift 4.0+](https://img.shields.io/badge/Swift-4.0%2B-orange.svg) 7 | [![Build Status](https://travis-ci.org/TBXark/TKRadarChart.svg?branch=master)](https://travis-ci.org/TBXark/TKRadarChart) 8 | [![CocoaPods](http://img.shields.io/cocoapods/v/TKRadarChart.svg?style=flat)](http://cocoapods.org/?q=TKRadarChart) 9 | [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) 10 | [![License MIT](https://img.shields.io/badge/license-MIT-green.svg?style=flat)](https://raw.githubusercontent.com/TBXark/TKRadarChart/master/LICENSE) 11 | 12 | 13 | ![](DemoImage/example.png) 14 | 15 | ## Requirements 16 | 17 | - iOS 8.0+ 18 | - Xcode 9.0 19 | - Swift 4.0 20 | 21 | ## Installation 22 | 23 | #### CocoaPods 24 | You can use [CocoaPods](http://cocoapods.org/) to install `TKRadarChart` by adding it to your `Podfile`: 25 | 26 | ```ruby 27 | platform :ios, '8.0' 28 | use_frameworks! 29 | pod 'TKRadarChart' 30 | ``` 31 | 32 | To get the full benefits import `TKRadarChart` wherever you import UIKit 33 | 34 | ``` swift 35 | import UIKit 36 | import TKRadarChart 37 | ``` 38 | #### Carthage 39 | Create a `Cartfile` that lists the framework and run `carthage update`. Follow the [instructions](https://github.com/Carthage/Carthage#if-youre-building-for-ios) to add `$(SRCROOT)/Carthage/Build/iOS/TKRadarChart.framework` to an iOS project. 40 | 41 | ```ruby 42 | github "tbxark/TKRadarChart" 43 | ``` 44 | #### Manually 45 | 1. Download and drop ```TKRadarChart.swift``` in your project. 46 | 2. Congratulations! 47 | 48 | ## Usage example 49 | 50 | ### Base 51 | 52 | |Base|Description|Demo| 53 | |---|---|---| 54 | |Step|Background polygon laps(min 1)|![image](DemoImage/origin.png) ![image](DemoImage/step.png)| 55 | |Row|Number of edges of polygon (min 3)|![image](DemoImage/origin.png) ![image](DemoImage/row.png)| 56 | |Section|At the same time show the number of data|![image](DemoImage/origin.png) ![image](DemoImage/section.png)| 57 | 58 | ### TKRadarChartConfig 59 | 60 | This structure is used for custom charts 61 | 62 | ```swift 63 | var radius: CGFloat 64 | var minValue: CGFloat 65 | var maxValue: CGFloat 66 | 67 | var showPoint: Bool 68 | var showBorder: Bool 69 | var fillArea: Bool 70 | var clockwise: Bool 71 | var autoCenterPoint: Bool 72 | ``` 73 | 74 | ### TKRadarChartDataSource 75 | 76 | This protocol represents the data model object. as such, it supplies no information about appearance 77 | 78 | ```swift 79 | protocol TKRadarChartDataSource: class { 80 | func numberOfStepForRadarChart(_ radarChart: TKRadarChart) -> Int 81 | func numberOfRowForRadarChart(_ radarChart: TKRadarChart) -> Int 82 | func numberOfSectionForRadarChart(_ radarChart: TKRadarChart) -> Int 83 | 84 | func titleOfRowForRadarChart(_ radarChart: TKRadarChart, row: Int) -> String 85 | func valueOfSectionForRadarChart(withRow row: Int, section: Int) -> CGFloat 86 | } 87 | ``` 88 | 89 | ### TKRadarChartDelegate 90 | 91 | This represents the display and behaviour of the TKRadarChart. 92 | 93 | ```swift 94 | protocol TKRadarChartDelegate: class { 95 | func colorOfTitleForRadarChart(_ radarChart: TKRadarChart) -> UIColor 96 | func colorOfLineForRadarChart(_ radarChart: TKRadarChart) -> UIColor 97 | func colorOfFillStepForRadarChart(_ radarChart: TKRadarChart, step: Int) -> UIColor 98 | 99 | func colorOfSectionFillForRadarChart(_ radarChart: TKRadarChart, section: Int) -> UIColor 100 | func colorOfSectionBorderForRadarChart(_ radarChart: TKRadarChart, section: Int) -> UIColor 101 | } 102 | ``` 103 | 104 | 105 | ## Release History 106 | 107 | * 1.4.3 108 | Upgrade to swift 4.2 109 | 110 | * 1.4.2 111 | Fix bugs that can not change the title font 112 | 113 | * 1.4.1 114 | Fix warnign 115 | 116 | * 1.4.0 117 | Upgrade to swift 4.0 118 | 119 | * 1.3.1 120 | Upgrade framework config 121 | 122 | * 1.3.0 123 | Support swift 3.0 124 | 125 | * 1.0.1 126 | Complete basic functions, add Cocoapod and Carthage support 127 | 128 | ## Contribute 129 | 130 | We would love for you to contribute to **TKRadarChart**, check the ``LICENSE`` file for more info. 131 | 132 | ## Meta 133 | 134 | TBXark – [@tbxark](https://twitter.com/tbxark) – tbxark@outlook.com 135 | 136 | Distributed under the MIT license. See ``LICENSE`` for more information. 137 | 138 | [https://github.com/TBXark](https://github.com/TBXark) 139 | 140 | [swift-image]:https://img.shields.io/badge/swift-3.0-orange.svg 141 | [swift-url]: https://swift.org/ 142 | [license-image]: https://img.shields.io/badge/License-MIT-blue.svg 143 | [license-url]: LICENSE 144 | [travis-image]: https://img.shields.io/travis/dbader/node-datadog-metrics/master.svg?style=flat-square 145 | [travis-url]: https://travis-ci.org/dbader/node-datadog-metrics 146 | [codebeat-image]: https://codebeat.co/badges/c19b47ea-2f9d-45df-8458-b2d952fe9dad 147 | [codebeat-url]: https://codebeat.co/projects/github-com-vsouza-awesomeios-com 148 | -------------------------------------------------------------------------------- /TKRadarChart/TKRadarChart.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TKRadarChart.swift 3 | // TKRadarChart 4 | // 5 | // Created by Tbxark on 16/7/13. 6 | // Copyright © 2016年 Tbxark. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | #if swift( >=4.2) 12 | typealias NSAttributedStringKey = NSAttributedString.Key 13 | #endif 14 | 15 | 16 | 17 | /// You can set data chart by `TKRadarChartDataSource` 18 | public protocol TKRadarChartDataSource: class { 19 | func numberOfStepForRadarChart(_ radarChart: TKRadarChart) -> Int 20 | func numberOfRowForRadarChart(_ radarChart: TKRadarChart) -> Int 21 | func numberOfSectionForRadarChart(_ radarChart: TKRadarChart) -> Int 22 | 23 | func titleOfRowForRadarChart(_ radarChart: TKRadarChart, row: Int) -> String 24 | func valueOfSectionForRadarChart(withRow row: Int, section: Int) -> CGFloat 25 | } 26 | 27 | /// You can custom chart by `TKRadarChartDelegate` 28 | public protocol TKRadarChartDelegate: class { 29 | 30 | func colorOfLineForRadarChart(_ radarChart: TKRadarChart) -> UIColor 31 | func colorOfFillStepForRadarChart(_ radarChart: TKRadarChart, step: Int) -> UIColor 32 | 33 | func colorOfSectionFillForRadarChart(_ radarChart: TKRadarChart, section: Int) -> UIColor 34 | func colorOfSectionBorderForRadarChart(_ radarChart: TKRadarChart, section: Int) -> UIColor 35 | 36 | func fontOfTitleForRadarChart(_ radarChart: TKRadarChart) -> UIFont 37 | func colorOfTitleForRadarChart(_ radarChart: TKRadarChart) -> UIColor 38 | 39 | } 40 | 41 | 42 | extension TKRadarChartDelegate { 43 | public func fontOfTitleForRadarChart(_ radarChart: TKRadarChart) -> UIFont { 44 | return UIFont.boldSystemFont(ofSize: 12) 45 | } 46 | public func colorOfTitleForRadarChart(_ radarChart: TKRadarChart) -> UIColor { 47 | return UIColor.gray 48 | } 49 | 50 | public func colorOfLineForRadarChart(_ radarChart: TKRadarChart) -> UIColor { 51 | return UIColor(red:0.937, green:0.925, blue:0.902, alpha:1) 52 | } 53 | 54 | public func colorOfFillStepForRadarChart(_ radarChart: TKRadarChart, step: Int) -> UIColor { 55 | return UIColor.clear 56 | } 57 | 58 | public func colorOfSectionFillForRadarChart(_ radarChart: TKRadarChart, section: Int) -> UIColor { 59 | return UIColor(red:0.561, green:0.753, blue:0.996, alpha:0.6) 60 | } 61 | 62 | public func colorOfSectionBorderForRadarChart(_ radarChart: TKRadarChart, section: Int) -> UIColor { 63 | return UIColor(red:1, green:0.867, blue:0.012, alpha:1) 64 | } 65 | 66 | 67 | } 68 | 69 | ///Configuration 70 | public struct TKRadarChartConfig { 71 | 72 | public static func defaultConfig() -> TKRadarChartConfig { 73 | return TKRadarChartConfig(radius: 80, 74 | minValue: 0, 75 | maxValue: 5, 76 | borderWidth: 4, 77 | lineWidth: 1, 78 | showPoint: false, 79 | showBorder: false, 80 | showBgLine: true, 81 | showBgBorder: true, 82 | fillArea: true, 83 | clockwise: false, 84 | autoCenterPoint: true) 85 | } 86 | 87 | 88 | public var radius: CGFloat 89 | public var minValue: CGFloat 90 | public var maxValue: CGFloat 91 | 92 | public var borderWidth: CGFloat 93 | public var lineWidth: CGFloat 94 | 95 | public var showPoint: Bool 96 | public var showBorder: Bool 97 | public var showBgLine: Bool 98 | public var showBgBorder: Bool 99 | public var fillArea: Bool 100 | public var clockwise: Bool 101 | public var autoCenterPoint: Bool 102 | 103 | 104 | public init(radius: CGFloat, 105 | minValue: CGFloat, 106 | maxValue: CGFloat, 107 | borderWidth: CGFloat, 108 | lineWidth: CGFloat, 109 | showPoint: Bool, 110 | showBorder: Bool, 111 | showBgLine: Bool, 112 | showBgBorder: Bool, 113 | fillArea: Bool, 114 | clockwise: Bool, 115 | autoCenterPoint: Bool) { 116 | self.radius = radius 117 | self.minValue = minValue 118 | self.maxValue = maxValue 119 | self.borderWidth = borderWidth 120 | self.lineWidth = lineWidth 121 | self.showPoint = showPoint 122 | self.showBorder = showBorder 123 | self.showBgLine = showBgLine 124 | self.showBgBorder = showBgBorder 125 | self.fillArea = fillArea 126 | self.clockwise = clockwise 127 | self.autoCenterPoint = autoCenterPoint 128 | } 129 | } 130 | 131 | 132 | 133 | public class TKRadarChart: UIView, TKRadarChartDelegate { 134 | 135 | public var centerPoint: CGPoint 136 | public var configuration: TKRadarChartConfig { 137 | didSet { 138 | reloadData() 139 | } 140 | } 141 | 142 | public override var frame: CGRect { 143 | didSet { 144 | if configuration.autoCenterPoint { 145 | centerPoint = CGPoint(x: frame.width/2, y: frame.height/2) 146 | } 147 | if min(frame.width, frame.height) < configuration.radius * 2 { 148 | configuration.radius = min(frame.width, frame.height)/2 149 | } 150 | setNeedsDisplay() 151 | } 152 | } 153 | 154 | 155 | public weak var dataSource: TKRadarChartDataSource? 156 | public weak var delegate: TKRadarChartDelegate? 157 | 158 | public override convenience init(frame: CGRect) { 159 | self.init(frame: frame, config: TKRadarChartConfig.defaultConfig()) 160 | } 161 | 162 | public init(frame: CGRect, config: TKRadarChartConfig) { 163 | centerPoint = CGPoint(x: frame.width/2, y: frame.height/2) 164 | configuration = config 165 | super.init(frame: frame) 166 | backgroundColor = UIColor.clear 167 | } 168 | 169 | public required init?(coder aDecoder: NSCoder) { 170 | centerPoint = CGPoint.zero 171 | configuration = TKRadarChartConfig.defaultConfig() 172 | super.init(coder: aDecoder) 173 | centerPoint = CGPoint(x: frame.width/2, y: frame.height/2) 174 | backgroundColor = UIColor.clear 175 | } 176 | 177 | 178 | public func reloadData() { 179 | setNeedsDisplay() 180 | } 181 | 182 | 183 | public override func draw(_ rect: CGRect) { 184 | 185 | guard let dataSource = dataSource, 186 | let context = UIGraphicsGetCurrentContext() else { return } 187 | 188 | 189 | let delegate = self.delegate ?? self 190 | let numOfRow = dataSource.numberOfRowForRadarChart(self) 191 | 192 | guard numOfRow > 0 else { return } 193 | 194 | let textFont = delegate.fontOfTitleForRadarChart(self) 195 | let numOfSetp = max(dataSource.numberOfStepForRadarChart(self), 1) 196 | let numOfSection = dataSource.numberOfSectionForRadarChart(self) 197 | let perAngle = CGFloat.pi * 2 / CGFloat(numOfRow) * CGFloat(configuration.clockwise ? 1 : -1) 198 | let padding = CGFloat(2) 199 | let height = textFont.lineHeight 200 | let radius = configuration.radius 201 | let minValue = configuration.minValue 202 | let maxValue = configuration.maxValue 203 | 204 | let lineColor = delegate.colorOfLineForRadarChart(self) 205 | 206 | /// Create titles 207 | let titleColor = delegate.colorOfTitleForRadarChart(self) 208 | for index in 0..= centerPoint .x ? width / 2.0 + padding : -width / 2.0 - padding 217 | let yOffset = pointOnEdge.y >= centerPoint .y ? height / 2.0 + padding : -height / 2.0 - padding 218 | var legendCenter = CGPoint(x: pointOnEdge.x + xOffset, y: pointOnEdge.y + yOffset) 219 | 220 | let paragraphStyle = NSParagraphStyle.default.mutableCopy() as! NSMutableParagraphStyle 221 | paragraphStyle.alignment = .center 222 | paragraphStyle.lineBreakMode = .byClipping 223 | let attributes = [NSAttributedStringKey.font: textFont, 224 | NSAttributedStringKey.paragraphStyle: paragraphStyle, 225 | NSAttributedStringKey.foregroundColor: titleColor] 226 | 227 | /// Fix title offset 228 | if index == 0 || (numOfRow%2 == 0 && index == numOfRow/2){ 229 | legendCenter.x = centerPoint.x 230 | legendCenter.y = centerPoint.y + (radius + padding + height / 2.0) * CGFloat(index == 0 ? -1 : 1) 231 | } 232 | let rect = CGRect(x: legendCenter.x - width / 2.0, y: legendCenter.y - height / 2.0, width: width, height: height) 233 | (title as NSString).draw(in: rect, withAttributes: attributes) 234 | } 235 | 236 | 237 | /// Draw the background rectangle 238 | context.saveGState() 239 | lineColor.setStroke() 240 | for stepTemp in 1...numOfSetp { 241 | let step = numOfSetp - stepTemp + 1 242 | let fillColor = delegate.colorOfFillStepForRadarChart(self, step: step) 243 | 244 | let scale = CGFloat(step)/CGFloat(numOfSetp) 245 | let innserRadius = scale * radius 246 | let path = UIBezierPath() 247 | for index in 0...numOfRow { 248 | let i = CGFloat(index) 249 | if index == 0 { 250 | let x = centerPoint.x 251 | let y = centerPoint.y - innserRadius 252 | path.move(to: CGPoint(x: x, y: y)) 253 | } else if index == numOfRow { 254 | let x = centerPoint.x 255 | let y = centerPoint.y - innserRadius 256 | path.addLine(to: CGPoint(x: x, y: y)) 257 | }else { 258 | let x = centerPoint.x - innserRadius * sin(i * perAngle) 259 | let y = centerPoint.y - innserRadius * cos(i * perAngle) 260 | path.addLine(to: CGPoint(x: x, y: y)) 261 | } 262 | } 263 | 264 | path.close() 265 | fillColor.setFill() 266 | 267 | path.lineWidth = configuration.borderWidth 268 | path.fill() 269 | if configuration.showBgBorder { 270 | path.stroke() 271 | } 272 | } 273 | context.restoreGState() 274 | 275 | 276 | /// Draw the background line 277 | lineColor.setStroke() 278 | if configuration.showBgLine { 279 | for index in 0.. 0 { 295 | for section in 0..