LoginSignup
46

More than 5 years have passed since last update.

Core Plotでグラフをアニメーションさせる(Swiftで)

Last updated at Posted at 2015-02-27

Core Plot、良い

Mac/iOSでグラフを作成するためのライブラリ、Core Plot。とても良いですね。
思うようなグラフができるよう、多くの設定項目があります。それゆえ、巷では「難しい」「複雑」などと散々に言われている気がしますが、ドキュメントもちゃんとあるし、それほど直感的でないわけでもなく、そんな敷居高くないと思います。

ただしアニメーション、テメーはダメだ

なんつーか、デザイン的にそれはどうなん? みたいなアニメーションは、ググって組めないことはないんですよね。
でも綺麗でそれっぽいアニメーションをするの、ちょっとね、たいへんよね。ググっても、「そのアニメーションはちょっと…」みたいなね、そういうの出てきてね、うん。

グラフって、ぐぐーんと伸びてきて、「結果どうなるのかなー、ワクワク」みたいにアニメーションしてほしいじゃないですか。
間違っても、アルファ値を弄って、もやーんとフェードインしてほしいわけじゃないんですよ。あと圧縮とかね。横に圧縮されてる折れ線をみょーんと横に伸ばされても、もう最初からどういう線を描いているか分かってるわけで、ネタバレ感半端ないわけですよ。そういうの求めてないんですよ。

というわけで、それっぽいアニメーションをします。Core Plotでグラフは描けているものとしますので、そのあたりの説明は省きます。
あと、1つずつアニメーションのgifをつけようと思ったんですが、思ったより面倒だったのでつけませんでした。ごめんね。

円グラフ

一番簡単なのは円グラフですね。
Core PlotにはCPTAnimationというクラスがあり、これを使ってアニメーションさせます。
Pie Chartには、どの角度まで描画するかを決めるendAngleがあるので、これをテキトーに変化させればOKです。

func addAnimation(plot:CPTPieChart) {
    let duration = CGFloat(1.5) // アニメーションの時間
    let curve = CPTAnimationCurve.ExponentialInOut // アニメーションカーブ
    CPTAnimation.animate(plot,
        property: "endAngle",
        from:CGFloat(M_PI / 2.0) + CGFloat(M_PI * 2.0),
        to: CGFloat(M_PI / 2.0),
        duration: CGFloat(1.5),
        animationCurve: curve,
        delegate: nil)
}

折れ線グラフ

前提として、円グラフのCPTPieChartような「どこからどこまで描画するのか」という都合の良いパラメータは、CPTScatterPlot自体にはありません。

まず、CPTScatterPlotをのせるグラフ、CPTGraphは目盛りをどこからどこまでにするか決めることができます。
そういったパラメータをうねうねして、CPTGraph自体をアニメーションさせることは可能ですが、やると目盛りなどまでアニメーションしてしまうので、カッコ悪いです。デザインとしても、コードとしてもカッコ悪いです。なんとかしてGraphでなくPlotをアニメーションさせたい。

そういう心持ちで、ドキュメントを眺めます。
スクリーンショット 2015-02-27 21.32.57.png
CPTScatterPlotにもいろいろと祖先がありますね。
…ん?
…あなた様はまさか…!

スクリーンショット 2015-02-27 21.34.28.png

CALayer様じゃないですか…!!!!

CALayerは、画像をこねこねするためのクラスです。変形させたり、影をつけたり、色々とできます。
そして、まさにcontentsRectというどこからどこまで描画するかを決めるプロパティがあるのです。最高です。
よって以下のように書けます。

func addAnimation(plot:CPTPlot) {
    let duration = CGFloat(1.5) // アニメーションの時間
    let curve = CPTAnimationCurve.ExponentialInOut // アニメーションカーブ
    plot.contentsGravity = kCAGravityLeft // contentsRectで切り取ったものを左寄せする
    CPTAnimation.animate(plot,
        property: "contentsRect", // どこからどこまで描画するかをCGRectで指定する
        fromRect: CGRect(x: 0, y: 0, width: 0, height: 1),
        toRect: CGRect(x: 1, y: 0, width: -1, height: 1),
        duration: duration,
        animationCurve: curve,
        delegate: nil)
}

詳しくはCALayerのドキュメントなどを参照してほしいのですが、contentsRectは、x軸、y軸ともに0〜1までの空間になっています。そのあたり注意して頂ければと。
これで、右方向に伸びていくグラフが描けました。

棒グラフ

折れ線と全く同じ理屈で書けます。今度はy軸に沿って伸びるようにしてます。

func addAnimation(plot:CPTPlot) {
    let duration = CGFloat(1.5)
    let curve = CPTAnimationCurve.ExponentialInOut
    plot.contentsGravity = kCAGravityBottom
    CPTAnimation.animate(plot,
        property: "contentsRect",
        fromRect: CGRect(x: 0, y: 0, width: 1, height: 0),
        toRect: CGRect(x: 0, y: 1, width: 1, height: -1),
        duration: duration,
        animationCurve: curve,
        delegate: nil)
}

結論

Core Plot最高。
あと、一緒に使うならデータをこねこねするためにExSwiftが最高です。ExSwiftについても、いつか書きたい。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
46