前言
CorePlot是一个适用于Mac OS X和iOS的2D绘图开源框架。它是一个高度可定制的,并且可以绘制多种类型的图形(饼图、柱状图、折线图)。目前CorePlot的下载地址已经移动到https://github.com/core-plot/core-plot/releases
配置
第一种配置方式(Dependent Project Install)
- a、将
CorePlot-CocoaTouch.xcodeproj
工程文件拖拽到项目中。解压后目录结构如下: - b、点击项目Target下的“Build Phases”选项卡,展开“Target Dependencies”,添加CorePlot-CocoaTouch库。这将确保CorePlot库在应用中建立。
- c、点击项目Target下的“Build Phases”选项卡,展开“Link Binaries With Libraries”,添加libCorePlot-CocoaTouch.a库。
- d、点击项目Target下的“Build Settings”选项卡,搜索“Header Search Paths”设置现,双击该设置现,添加CorePlot的全路径(CorePlot-CocoaTouch.h的路径),并确保选中“recursive”选项框
- e、点击项目Target下的“Build Settings”选项卡,搜索“Other Linker Flags”设置现,双击该设置现,添加
-ObjC
,Xcode4.2及以后不需要添加-all_load
- f、添加QuartzCore
- g、在使用CorePlot框架的类中导入文件:
#import"CorePlot-CocoaTouch.h"
第二种配置方式(Static Library Install)
- a、拷贝CorePlotHeaders和CorePlot库到项目中,目录结构如下:
- b、点击项目Target下的“Build Settings”选项卡,搜索“Other Linker Flags”设置现,双击该设置现,添加“-ObjC”,Xcode4.2及以后不需要添加“-all_load”
- c、添加QuartzCore
- d、在使用CorePlot框架的类中导入文件:
#import "CorePlot-CocoaTouch.h"
ps: 第一种配置比较麻烦,不推荐。建议使用第二种配置方式
CorePlot 设计概述
设计思想(Design Considerations)
在钻研构造CorePlot类之前,有必要了解这个框架的设计目标。CorePlot已被开发运行于Mac OS X和iOS上。这在技术的使用方面有一些限制:AppKit不能被运用于绘图、像NSView和UIView的视图类只能被用作宿主试图。绘图使用底层的Quartz 2D API,Core Animation Layers被用来建立一个图表的各个不同方面。
并不是只有坏消息,因为使用Core Animation大大方便了引入“eye-candy”。图表可以有各种动画,CorePlot的目标是不仅可以生产印刷质量的静止图片,而且也可以生产出色的图片效果和交互性。
CorePlot另一个有影响力的设计目标是从开发者的角度看,它能尽可能表现的像一个内置框架。CorePlot支持在Apple自己的框架中使用到的设计模式和技术,如数据源模式、委托和绑定。
图表剖析(Anatomy of a Graph)
下面的图显示了两组数据标绘的标准柱状图。再下面,这个图表已经加了注释,以显示这个图片的不同组件,并且用CorePlot中的命名方案去辨别他们。
类图(Class Diagram)
下面这个标准的UML类图给出了CorePlot框架中主要类的静态视图。关系的基数通过标签指定,用“1”表示“对一”的关系,用星号(*)表示“对多”的关系。
对象和层(Objects And Layers)
下面的图表显示了在对象(右)和Core Animation layer树(左)中层的运行时间关系。颜色编码表明了对象和相应层之间的对应关系。
图层(Layers)
Core Animation的图层类,CALayer,不是很适合生产矢量图,也无法满足生产印刷质量图片的需求,并且无法提供事件处理。因为这些原因,CorePlot的层从一个叫作CPTLayer的类中派生出来,CPTLayer本身是CALayer的一个子类。CPTLayer包括绘图方法,它能够生产出高质量的矢量图,同时也包括事件处理方法以便于交互。
当从CPTLayer中派生子类时,有一点很重要,你不能够重载标准的drawInContext方法,而是要重载renderAsVactorInContext方法。这样,这个图层才会正确的生成并显示到屏幕上。
图表(Graphs)
CorePlot的核心类是CPTGraph。在CorePlot中,“graph”一词是指完整的图表,包括坐标轴、标签、标题和一或多个的平面图(如:直方图,线性图)。CPTGraph是一个抽象类,所有的图形类都从它派生。
一个图表类从根本上说是一个工厂。它负责创建构成图表的各种对象,并且建立合适的关系。CPTGraph持有引用其他高层次类的对象,如:CPTAxisSet、CPTPlotArea和CPTPlotSpace。它也保存在图表上显示的图块(CPTPlot实例)的引用。
CPTGraph是一个抽象的父类;像CPTXYGraph这样的子类实际上负责大部分图表组件的创建和组织。每个CPTGraph子类通常与构成图表的各种图层的特定子类相关联。例如,CPTGraph创建CPTXYAxisSet和CPTXYPlotSpace实例。这是一个工厂设计模式的经典案例,在GoF设计模式一书中有详细说明。
绘图区域(Plot Area)
这个绘图区域是图表数据绘制的部分。它通常有坐标轴,也可以显示网格线。每一个图表只有一个绘图区域,由CPTPlotArea这个类来表现。这个绘图区域被一个CPTPlotAreaFrame环绕,CPTPlotAreaFrame可以给这个绘图区域添加边框。
绘图空间(Plot Spaces)
绘图空间定义了坐标空间和绘制空间的映射关系,坐标空间存放了一套数据,绘制空间则在绘图区域中。
例如,如果你要绘制一列火车的速度与时间关系表,数据空间将存放时间于横坐标,速度于纵坐标。数据空间的速度可能在0到150km/hr范围内,时间在0到180分钟内。另一方面,绘制空间是受绘图区域的边界控制的。一个绘图空间代表CPTPlotSpace类的一个子类,定义了数据空间中的坐标与绘图区域中相应点的映射关系。
使用内置的支持仿射变换去执行数据和绘制空间的映射关系是很有吸引力的,但这会非常受限制,因为映射不一定是线性的。例如,在数据空间中使用对数比例坐标并不少见。 为了尽可能的方便使用数据集,数据空间中的值可以在内部存储为NSDecimalNumber实例。在绘制空间中用这种方式存储值是没有意义的,因为在Cocoa中绘制坐标使用浮点数(CGFloat)表示的,任何额外的精度都会被丢失掉。
一个CPTPlotSpace子类必须实现从绘制坐标到数据坐标的转换方法,以及反过来从数据坐标到绘制坐标的转换方法。
数据坐标——在这里代表一个“绘制点”——一个NSDecimal结构体或double类型的C数组传递。绘制坐标——在这里代表“试图点”——一个标准的CGPoint结构体传递。
每当一个对象执行从数据坐标到绘制坐标的转换,它需要查询相对应的绘图空间,反之亦然。例如,每个CPTPlot(下面讨论)实例与一个特定的绘图空间相关联,并且利用绘图空间来确定绘图区域应该绘制的位置。
认识到一个单一的图表可能包含多个平面图是非常重要的,并且这些平面图可能在不同的刻度上绘制。例如,一个平面图可能需要用对数刻度去绘制,而另一个可能需要用线性刻度去绘制。这无法阻止在一个图表中出现两种平面图。
由于这个原因,一个单一的CPTGraph实例可以有多个CPTPlotSpace实例。在大部分情况下,只会有一个单一的CPTPlotSpace实例,但是这个框架拥有这种灵活性以支持在一个单一的图表中出现多个绘图空间的。
平面图(Plots)
在一个图表中数据的特定的表现方式被称为平面图。例如,数据可以被显示为一个线性或散点图,用一个符号表示每一个数据点。相同的数据可能被条形图/直方图表示。
一个图表可能有多个平面图。每一个平面图可能来源于一个单一的数据集,也可以是不同的数据集:他们完全是互相独立的。
平面图是类似与表视图的,虽然初看起来不像。例如,表示一个火车速度与时间的简单线性图,你需要知道在不同时间点上的速度值。这些数据被保存在表视图的两列上,或描绘为一个散点图。实际上,平面图和表视图只是同一个模型数据的不同视图。
这意味着,用于将数据填充给表视图的设计方案也可以提供数据给平面图。特别是,你可以使用数据源设计模式,也可以使用绑定。通过数据源途径提供数据给平面图,你需要设置CPTPlot对象的数据源出口,并且要实现数据源方法。
你可以把这个字段(field)认为是类似于表视图中的一个列的标识符,记录索引(record index)类似于表视图中的行索引(row index)。每种平面图都有固定数量的字段(fields)。例如,散点图有两个:横坐标(x)的值和纵坐标(y)的值。在CPTScatterPlot类中的枚举定义了这些字段(field)。
一个记录类似于表视图中的一行。对于散点图,它相对应于图表中的一个点。
Plot类不仅支持数据源设计模式,同样支持Cocoa绑定。这个再一次非常类似于表视图:每个Plot中的字段——类似于表的列——通过一个NSArrayController赋值给key path。
所有plot类的父类都是CPTPlot。CPTPlot是一个抽象类:每种CPTPlot子类代表一种平面图。例如,CPTScatterPlot类用于绘制线性和散点图,而CPTPatPlot类用于绘制条形图和直方图。
在前面提到过plot对象与CPTPlotSpace关系非常紧密。为了绘制自己,plot类需要把数据源处接收到的值转换为绘制坐标。绘制空间为这个目的提供支持。
坐标轴(Axes)
坐标轴把平面图坐标空间的刻度显示给观众。一个基本的图表仅仅有两个坐标轴,一个水平方向(x),一个垂直方向(y),但是在CorePlot中是没有强制限制的——你可以根据你的需要添加尽可能多的坐标轴。坐标轴可以出现在绘制区域的边上,也可以出现在顶部。坐标轴可以有不同的刻度,可以包含主要和次要的刻度,也可以有标签和标题。
在图表中的每一个坐标轴都代表一个CPTAxis派生类的对象。CPTAxis负责绘制自己以及像刻度和标签这样的附属。为了这个它需要知道如何使数据坐标映射为绘制坐标,因此,每个坐标轴都是与一个单一的CPTPlotSpace实例相关联的。
一个图表可能有多个坐标轴,但是所有的坐标轴都分组在CPTAxisSet对象中。一个坐标轴集是一个包含图表所有坐标轴的容器,也是创建坐标轴集的工厂(例如,CPTAxisSet创建两个坐标轴,一个x轴,一个y轴)。
坐标轴标签通常是文本,但是在CorePlot中以支持自定义标签:任何被CPTAxisLabel实例包装的Core Animation layer可以被用作坐标轴标签。
动画(Animations)
CorePlot一个独特的方面是对动画的整合,这有助于动态效果和交互性。Core Animation框架提供了及时定位和转换图层的机制。一般而言,你可以直接访问图层来应用动画。需要注意的是,一些图层的转换,诸如平面图和绘图区域,可能使数据和坐标轴的一致性失效。
ps: 大部分内容翻译自https://github.com/core-plot/core-plot/wiki/High-Level-Design-Overview