如何在 Swift 语言下使用 iOS Charts API 制作漂亮图表?
【编者按】本文作者 Joyce Echessa 是渥合数位服务创办人,毕业于台湾大学,近年来专注于协助客户进行 App 软体以及网站开发。文中作者通过示例介绍用 ios-charts 库创建简易美观的图表,有助于开发者在应用中生动形象地向用户展示数据。本文系 OneAPM 工程师编译整理:
呈现大量数据时,比起表格中一行行枯燥的数据,使用图表来形象地表示数据可以帮助用户更好地理解。在图表中,不需要通读所有数据资料,便能很容易地了解数据模式,从而获取关键信息。图表的使用在商业 App 和健身 App 中非常常见。
本篇文章中,我们主要介绍由 Daniel Cohen Gindi 开发的 ios-charts library。ios-charts 是由 Philipp Jahoda 建立的,是非常流行的 Android 库 MPAndroidChart 的 iOS 端口。有了这个库,你可以方便快捷地在应用中添加不同类型的图表。仅需寥寥几行代码,就可以制作出功能齐备、交互性强的图表,并且高度可定制。
函数库的主要特征:
- 8种不同的图表类型;
- 两个轴的缩放(用触控手势、分轴缩放或捏拉缩放);
- 拖拽/平移(用触控手势);
- 图表结合(线形图、柱形图、离散图、K 线图、气泡图);
- 双(分开的)Y 轴;
- 手指画图(用触控手势将数值画入图表);
- 数值突出显示(自定义弹出视图);
- 多个/分离的轴;
- 储存图表到相册/以 PNG/JPEG 格式输出;
- 预定义颜色模板;
- 图例(可自动生成,可自定义);
- 自定义轴(包括 X 和Y 轴);
- 动画(在 X 轴和 Y 轴上建立动画);
- 界限(提供额外信息,比如最大值等);
- 全方位自定义(上色、字体、图例、颜色、背景、手势、虚线等)。
开始吧!
首先、下载本篇文章将会用到的初始示例——名为 iOSChartsDemo 的简易应用。应用运行时,你会看到有两个项目的表格:条形图和其他图表。当点击项目时,会得到空白的视图。在本例中,笔者已创建了要用的两个视图控制器:BarChartViewController 和 ChartsViewController。
接着,我们添加函数库到项目中。你可以用 CocoaPods 安装该库,这里我们直接手动安装。
下载 ios-charts 项目,这个 zip 文件包含了函数库(名为 Charts 的文件夹)和一个示例项目(名为 ChartsDemo)。如果你想了解更多关于函数库的知识,示例项目是很棒的资源。
解压缩已下载的文件,并将 Charts 文件复制粘贴到你项目(iOSChartsDemo)的根目录下。在 Finder 中打开Charts文件,并将 Charts.xcodeproj 拖拽到 Xcode 项目中。结构如下图所示。
接着从项目导航中选择你的项目,并确保该 iOSChartsDemo 目标被选中。在右边的常规选项卡中找到 Embedded Binaries 部分,点击该部分的+
号添加图表框架。从列表中选择 Charts.framework 并点击 Add。
如果你想在 Objective-C 中使用函数库,请参考使用说明。
用 Command-B 或选择 Product > Build 来生成项目。如果不这样做,当你导入 Charts 框架到你的项目时,Xcode 会报错——无法加载 Charts 底层模块。
现在开始创建第一个图表。
创建一个柱形图
打开 BarChartViewController.swift 文件,添加以下声明。
import Charts
打开故事板文件。我们需要添加用来显示图表的视图。从文档纲要中选择 Bar Chart View Controller,并在属性检查器中取消 Extend Edges 的 Under Top Barsin 选项。我们不希望图表自动延伸至导航栏下方。
接着拖拽一个视图到 Bar Chart View Controller 中,并按下图定位边界。该视图为控制器中主视图的子视图。
视图被选中后,在识别检查器中将它的类设为 BarChartView。再使用助理编辑器,加入视图的 outlet 到 BarChartViewController 类,并命名为 outletbarChartView。在 BarChartViewController 类中添加下列代码。
@IBOutlet weak var barChartView: BarChartView!
运行项目,并从表格中选择柱形图,你可能会得到视图提示信息:无可用的图表数据。
如果在没有数据来产生图表时,你想在空白状态显示其他的信息,这时候可以自定义这个提示信息。在 viewDidLoad()函数底部,加入下列代码。
运行该项目,可以看到自定义的提示信息。
你可以为下面信息进一步添加描述。这可以用来向用户解释,为什么图表是空的,他们需要获取数据来生成图表。例如:健身 App 应该让用户知道在整理图表分析之前,他们需要先记录跑步数据。
barChartView.noDataTextDescription = "GIVE REASON"
添加下面的属性到该类。我们用它来存储一些图表的模拟数据。
var months: [String]!
将下面的函数添加到该类,用以建立图表。
func setChart(dataPoints: [String], values: [Double]) {
barChartView.noDataText = "You need to provide data for the chart."
}
请注意,我曾经在 viewDidLoad()函数中添加了声明。现在从 viewDidLoad()中移除该声明。我们将用 setChart()来自定义图表。
在 viewDidLoad()中,添加以下内容到函数底部。
months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
let unitsSold = [20.0, 4.0, 6.0, 3.0, 12.0, 16.0, 4.0, 18.0, 2.0, 4.0, 5.0, 4.0]
setChart(months, values: unitsSold)
我们设置一些模拟数据,给出一些产品一年中每个月售出的单位数。然后,我们将数据传给 setChart()。
让一个图表显示数据,我们还需创建一个 BarChartData 对象,并将其设置为 barChartView 的数据属性。添加下面的代码到 setChart()函数底部。
var dataEntries: [BarChartDataEntry] = []
for i in 0..<dataPoints.count {
let dataEntry = BarChartDataEntry(value: values[i], xIndex: i)
dataEntries.append(dataEntry)
}
let chartDataSet = BarChartDataSet(yVals: dataEntries, label: "Units Sold")
let chartData = BarChartData(xVals: months, dataSet: chartDataSet)
barChartView.data = chartData
以上代码中,我们创建了一个 BarChartDataEntry 对象的数组。BarChartDataEntry 初始化需要每个数据项的值、其对应的项目索引以及一个任意的标签。
随后,我们使用这个对象创建 BarChartDataSet,主要用来传递 BarChartDataEntry 对象的数组,以及描述数据的标签。
最后,我们用它来创建一个 BarChartData 对象,用来设定我们图表视图的数据。
运行该应用,可以看到如下图所示有数据的柱形图。
你可以为出现在视图右下方的图表设置说明。默认情况下,文本可用来设置「说明」,该说明会出现在图片上。参考 ofMPAndroidChart 文档,你可以更改描述的位置,但看一下 iOS 的 API,这并没有包括在内。函数库仍在维护,所以可能会在之后添加。如果你想改变描述的位置,你可以修改 ChartViewBase 类(是 BarChartView 类的子类)中的 drawDescription(上下文)函数。
针对本应用,我们移除描述文本。在 setChart()函数的底部添加下列内容,将描述文本设为空字符串。
barChartView.descriptionText = ""
自定义图表
你可以修改一些属性来自定义图表视图的外观。下面我们来具体介绍,你也可以浏览文档看看哪些可以自定义。
首先,我们修改柱形图的默认颜色。添加下列设置到 setChart()函数的底部。
chartDataSet.colors = [UIColor(red: 230/255, green: 126/255, blue: 34/255, alpha: 1)]
以上代码设置了与数据相关的颜色。将该设定给 UIColor 对象数组。因此只要数组中有一种颜色,所有的实体均可用。
如果你想给每一个数据对象设置不同的颜色,那么你需要提供更多的颜色,本例中需要12种。如果你的颜色数量少于实体总数,那么从坐到右将不同的颜色分配给柱形图,直到颜色用完后重新开始分配。
API 中也自带一些预定义颜色模板,你可以用它来为数据项设定不同颜色,它们包括:
- ChartColorTemplates.liberty()
- ChartColorTemplates.joyful()
- ChartColorTemplates.pastel()
- ChartColorTemplates.colorful()
- ChartColorTemplates.vordiplom()
如下所示,使用 ChartColorTemplates.colorful()模板。
chartDataSet.colors = ChartColorTemplates.colorful()
如下所示修改 X 轴标签的位置。
barChartView.xAxis.labelPosition = .Bottom
现在标签在图表底部。
按照以下办法可以修改图表的背景色。
barChartView.backgroundColor = UIColor(red: 189/255, green: 195/255, blue: 199/255, alpha: 1)
根据上述设定,你会看到如下所示的界面。
动画
你可以为图表设定一些动画,使之更加生动活泼。你可以使用三种主要的动画类型方法,可以同时让 XY 轴或者分别某个轴产生动画。
- animate(xAxisDuration: NSTimeInterval, yAxisDuration: NSTimeInterval)
- animate(xAxisDuration: NSTimeInterval)
- animate(yAxisDuration: NSTimeInterval)
你可以加入任意的 ChartEasingOption 到以上函数。选项如下:
- Linear
- EaseInQuad
- EaseOutQuad
- EaseInOutQuad
- EaseInCubic
- EaseOutCubic
- EaseInOutCubic
- EaseInQuart
- EaseOutQuart
- EaseInOutQuart
- EaseInQuint
- EaseOutQuint
- EaseInOutQuint
- EaseInSine
- EaseOutSine
- EaseInOutSine
- EaseInExpo
- EaseOutExpo
- EaseInOutExpo
- EaseInCirc
- EaseOutCirc
- EaseInOutCirc
- EaseInElastic
- EaseOutElastic
- EaseInOutElastic
- EaseInBack
- EaseOutBack
- EaseInOutBack
- EaseInBounce
- EaseOutBounce
- EaseInOutBounce
添加下行内容到 setChart()函数。
运行应用,柱形图以动画的形式加入视图。我们同时为两个轴都设置2秒的动画。
修改上述状态为:
barChartView.animate(xAxisDuration: 2.0, yAxisDuration: 2.0, easingOption: .EaseInBounce)
你会看到这行的特效如下。
界限
界限是针对所有线形图、柱形图和离散图的附加功能。它允许在图表中显示额外的线条为特定轴(X 或 Y 轴)加限制。这额外的线用来设定数据的目标值,帮助用户更容易了解是否达到界限。
要在图表中加入界限,可以添加以下代码到 setData()函数中。
let ll = ChartLimitLine(limit: 10.0, label: "Target")
barChartView.rightAxis.addLimitLine(ll)
运行该应用,你可以看到一条红线,标记在单位10左右。上面的代码中,我们在界限上添加了一个标签。但是 ChartLimitLine 有另一个没有添加标签的初始化函数,如果不想加的话可以省略。
触控事件
如果运行应用,你会发现通过默认的捏拉缩放和双击来进行缩放。此外,如果某个柱形条被单击,该柱形条会突出显示。很棒的是无需自己再编代码就能使用该功能,除非你想添加更多的功能,比如当用户单击柱形条时有其他响应。
为了检测图表内的选择,我们将使用 ChartViewDelegate 协议。
修改该类的声明如下。
class BarChartViewController: UIViewController, ChartViewDelegate {
在调用 super.viewDidLoad()后面添加下列代码到 viewDidLoad()。
barChartView.delegate = self
添加下面的函数到该类。
func chartValueSelected(chartView: ChartViewBase, entry: ChartDataEntry, dataSetIndex: Int, highlight: ChartHighlight) {
println("\(entry.value) in \(months[entry.xIndex])")
}
当图表视图中的值被选中时,会调用上述函数。这里我们打印出被选中的月份和值。
保存图表
你可以将图表的当前状态保存为图像。可以选择将它保存到相机胶卷或者重新设置一个保存路径。
首先,我们将添加一个保存按钮到图表视图。打开故事板文件,并找到柱形图表视图控制器。拖动导航项目到视图控制器的导航栏,然后拖动柱形按钮项,并将其放置于导航项目的右上角。删除属性检查器中的导航项目的标题属性中的「标题」文本。选择柱形按钮项,并设置其标识便于保存到属性检查器。可以看到如下界面。
接着为按钮创建一个消息响应,命名为 saveChart,添加以下代码到 BarChartViewController 类中。
@IBAction func saveChart(sender: UIBarButtonItem) {
}
按照下列代码修改上面的方法。
@IBAction func saveChart(sender: UIBarButtonItem) {
barChartView.saveToCameraRoll()
}
执行该程序后,当点击保存按钮时,图表图像讲保存到相册,可用 Photos 应用浏览。
下列代码可以重新设置保存路径。
barChartView.saveToPath(path: String, format: ChartViewBase.ImageFormat, compressionQuality: Double)
图片格式可能是 .JPEG或 .PNG,该 compressionQuality 是一种无损格式(JPEG)的压缩质量。
更多图表
现在我们看一下其他几个图表。大部分我们都看过了,所以不再过多赘述。
首先,在故事板文件中找到图表视图控制器,在识别检查器中,设定视图的标签为 Pie Chart View 的类为 PieChartView。
如下所示修改 ChartsViewController 类。
import UIKit
import Charts
class ChartsViewController: UIViewController {
@IBOutlet weak var lineChartView: LineChartView!
@IBOutlet weak var pieChartView: PieChartView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
let months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun"]
let unitsSold = [20.0, 4.0, 6.0, 3.0, 12.0, 16.0]
setChart(months, values: unitsSold)
}
func setChart(dataPoints: [String], values: [Double]) {
var dataEntries: [ChartDataEntry] = []
for i in 0..<dataPoints.count {
let dataEntry = ChartDataEntry(value: values[i], xIndex: i)
dataEntries.append(dataEntry)
}
let pieChartDataSet = PieChartDataSet(yVals: dataEntries, label: "Units Sold")
let pieChartData = PieChartData(xVals: dataPoints, dataSet: pieChartDataSet)
pieChartView.data = pieChartData
var colors: [UIColor] = []
for i in 0..<dataPoints.count {
let red = Double(arc4random_uniform(256))
let green = Double(arc4random_uniform(256))
let blue = Double(arc4random_uniform(256))
let color = UIColor(red: CGFloat(red/255), green: CGFloat(green/255), blue: CGFloat(blue/255), alpha: 1)
colors.append(color)
}
pieChartDataSet.colors = colors
let lineChartDataSet = LineChartDataSet(yVals: dataEntries, label: "Units Sold")
let lineChartData = LineChartData(xVals: dataPoints, dataSet: lineChartDataSet)
lineChartView.data = lineChartData
}
}
以上代码中,我们将 Charts 框架导入类中,像之前创建柱形图那样,创建一个饼状图和一个线形图。但需要注意的是,在柱形图表例中我们使用的是 BarChartDataEntry,而现在使用父类 ChartDataEntry 创建数据项。
运行应用,选择表格视图中的其他图表,可以看见一个线形图和有颜色的饼状图。你的应用可能跟下图不完全相同,因为饼状图的颜色是随机的。
结束语
本篇文章大致介绍了使用 ios-charts 库创建的一些图表类型,大概涉及了自定义图表的一些内容。如果你想知道这个库的其他功能,你可以参考这个下载库自带的 ChartsDemo 项目的代码,也可以看看该项目的维基百科。这个链接到 Wiki 页面会引导至 MPAndroidChart 项目文档。作者在写这篇文章时,还没有库的 iOS 版本的文档说明,但其实 API 跟 Android 版本约95%都相同,当你百思不得其解时,Android 文档仍然可以派上用场。
你可以在这里下载完整项目。
下面列出可创建的图表类型。
线形图(图例、简单的设计)
线形图(图例、简单的设计)
线图(立方线)
线图(单数据组)
复合图(柱形图和线图)
柱形图(图例、简单设计)
柱形图(分组数据集)
水平柱形图
饼状图(有选取)
散点图(以方形、三角形、圆形等图例)
K线图(针对财经数据)
气泡图(由气泡区域覆盖来表示值)
雷达图(蛛网图)
本文系 OneAPM 工程师编译整理。想阅读更多技术文章,请访问 OneAPM 官方博客。
如何在 Swift 语言下使用 iOS Charts API 制作漂亮图表?的更多相关文章
- 学习swift语言的快速入门教程推荐
随着苹果产品越来越火爆,苹果新推出的swift必定将在很大程度上代替oc语言.学好swift语言,对于IOS工程师来讲,已经是一门必备技能. 有一些比较好的英文版教程,值得学习. 1. Swift T ...
- IOS系列swift语言之课时二
今天我们要讲的就是函数[对于函数,在最后面还有几道题,喜欢的博友可以看了自己做一下,和我交流一下] 当然这与我们的c语言还是有一定的共同之处的,对于有一些c语言或者是java基础的童鞋,我觉得是很容易 ...
- IOS入门之Swift语言(一)
经过不断的努力,小哥也买了台苹果设备,终于可以开始我的IOS之旅了,说来确实令人苦恼,为了学习IOS我这着贫农阶级,省了几个月的零花钱,外加向亲朋好友求救,最终痛下心扉,卖了台MAC pro128G版 ...
- swift语言注册非免费苹果账号iOS游戏框架Sprite Kit基础教程
swift语言注册非免费苹果账号iOS游戏框架Sprite Kit基础教程 1.2.3 注册非免费苹果账号swift语言注册非免费苹果账号iOS游戏框架Sprite Kit基础教程 免费的苹果账号在 ...
- iOS - Swift Swift 语言新特性
1.Swift 2.0 带来哪些新变化 常规变化: 1.OS X 10.11.iOS 9 和 watchOS 2 SDK 采纳了一些 Objective-C 的特性用来提高 Swift 的编程体验, ...
- iOS之Swift语言的学习
好久都没有来这个熟悉而又陌生的地方啦, 想想已经有两三个月了吧,不过我相信以后还是会经常来的啦,因为忙碌的学习已经过去啦,剩下的就是要好好的总结好好的复习了,好好的熟悉下我们之前学习的知识点,将他们有 ...
- iOS新的旅程之Swift语言的学习
好久都没有来这个熟悉而又陌生的地方啦, 想想已经有两三个月了吧,不过我相信以后还是会经常来的啦,因为忙碌的学习已经过去啦,剩下的就是要好好的总结好好的复习了,好好的熟悉下我们之前学习的知识点,将他们有 ...
- Swift语言iOS开发:CALayer十则示例
如你所知,我们在iOS应用中看到的都是视图(view),包括按钮视图.表视图.滑动条视图,还有可以容纳其他视图的父视图等. AD:[活动]Web和APP兼容性实战 Win10训练营免费报名 如你所知, ...
- 【iOS开发】如何用 Swift 语言进行LBS应用的开发?
本文分为三部分,第一部分详解用Swift语言开发LBS应用,并给出完整的示例与源代码:第二部分介绍如何申请LBS密钥,第三部分是综合示例查看,扫描二维码即可查看示例demo. 第一部分 使用Swift ...
随机推荐
- 在EF的code frist下写稳健的权限管理系统:数据库模型(二)
先从数据库开始,因为是用EF的code frist,所以所有的设计都在解决项目中进行. 先是数据模型开始 我已经建立了四个模型,user,role,action,actiongroup user里面有 ...
- C开发 中原子性操作 , 除了快什么都不剩下了
题外话 今天,听歌曲听到一首缅怀迈克尔·杰克逊的歌曲 如下: http://music.163.com/#/song?id=1696048 Breaking News 每次听迈克尔 音乐,特别有战斗 ...
- C语言中进制知识总结
1.什么是进制 进制是一种计数的方式,常用的有二进制.八进制.十进制.十六进制.任何数据在计算机内存中都是以二进制的形式存放的. 我对进制的个人理解,二进制数是以2为计算单元,满2进1位的数:八进制数 ...
- jQuery的筛选选择器
基本筛选选择器 很多时候我们不能直接通过基本选择器与层级选择器找到我们想要的元素,为此jQuery提供了一系列的筛选选择器用来更快捷的找到所需的DOM元素.筛选选择器很多都不是CSS的规范,而是jQu ...
- R Tools for Visual Studio
https://www.visualstudio.com/en-us/features/rtvs-vs.aspx https://www.microsoft.com/en-us/cloud-platf ...
- golang没有条件表达式?:
详见The Go Programming Language Specification中Expressions一章中未提及此表达式, 故其不支持. 再强调一次, GO不支持条件表达式 conditio ...
- UITextField 属性详解
//初始化textfield并设置位置及大小 UITextField *text = [[UITextField alloc]initWithFrame:CGRectMake(20, 20, 13 ...
- Effective Objective-C 2.0之Note.01
1.在类的头文件中尽量少引入其他头文件 除非确有必要,否则不要引入头文件.一般来说,应在某个类的头文件中使用向前声明来提及别的类,并在实现文件中引入那些类的头文件.这样做可以尽量降低类之间的耦合(co ...
- iOS 各种系统文件目录 临时,缓存,document,lib,归档,序列化
/** 1:Documents:应用中用户数据可以放在这里,iTunes备份和恢复的时候会包括此目录 2:tmp:存放临时文件,iTunes不会备份和恢复此目录,此目录下文件可能会在应用退出后删除 3 ...
- 从零开始学ios开发(四):IOS控件(1),Image View、Text Field、Keyboard
长话短说,谢谢大家的关注,这篇写了好长时间,下面继续学习ios.我将用2到3篇的篇幅来学习iphone上的一些常用控件,包括Image View.Text Field.Keyboard.Slider等 ...