ChartsのPieChartでグラフ内のvalueを表示しない方法はありますか?
PieChartのvalueは以下の様に追加しますが,実際に表示するときその値を表示しないで円だけを表示する事は可能でしょうか?
Swift
1PieChartDataEntry(value: 5, label: "")
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答1件
0
ベストアンサー
前回書いたコードの流用ですが
swift
1 let entries = someArray.map{ element -> PieChartDataEntry in 2 let value = Double(element) 3 return PieChartDataEntry(value: value) 4 } 5 //entriesは[PieChartDataEntry] 6 let dataSet = PieChartDataSet(values: entries, label: "") 7 8 dataSet.drawValuesEnabled = false //←こいつ
これでOKです。
iOS-Chartsって割となんでも出来ちゃうので大好きなのですが、どの段階(entry -> dataSet -> data)でどのプロパティをセットできるのかがちょっと分かりにくいですよね。
あとは力業でIValueFormatter
とNSObject
を継承したクラスを作ってその中でstringForValue(_:entry:dataSetIndex:viewPortHandler:) -> String
を実装する時に返り値を全部""
にしちゃって、そのクラスをdataSet.valueFormatter
に放り込むなんてのもいけます。前の質問でPieChartに空欄があるということだったのでこっちも使える可能性があるかと思い紹介してみました。
swift
1class CustomFormatter: NSObject, IValueFormatter { 2 func stringForValue(_ value: Double, 3 entry: ChartDataEntry, 4 dataSetIndex: Int, 5 viewPortHandler: ViewPortHandler?) -> String { 6 return "" 7 } 8} 9 10func setupPieChart() { 11 let entries = someArray.map{ element -> PieChartDataEntry in 12 let value = Double(element) 13 return PieChartDataEntry(value: value) 14 } 15 //entriesは[PieChartDataEntry] 16 let dataSet = PieChartDataSet(values: entries, label: "") 17 dataSet.valueFormatter = CustomFormatter() //<-ここ 18}
また、このやり方を応用すれば任意のEntryだけ好きな文字列を表示させたりも出来ます。
(追記および修正)
ご要望にお応えしてみました。
丸々コピペしても動きます(動作確認済み)。Outlet接続はちゃんと再設定してください。あとコンソールに色々printした結果が出てくるのでその結果とコードを見比べるといいでしょう。
swift
1import UIKit 2import Charts 3 4class ViewController: UIViewController { 5 6 @IBOutlet weak var pieChart: PieChartView! 7 8 //UIButtonをタップすることで下記の追記した二つの関数を呼び出しチャートを書き換えます。 9 //追記 10 @IBAction func tap(_ sender: UIButton) { 11 let hourValues = [9, 3, 5, 7.0] 12 let set = makeSet(values: hourValues) 13 change(types: set.types, values: set.values) 14 } 15 16 override func viewDidLoad() { 17 super.viewDidLoad() 18 makePieChart() 19 } 20 21 override func didReceiveMemoryWarning() { 22 super.didReceiveMemoryWarning() 23 } 24 25 26 27 //追記 だいたいこういう感じでvaluesを元にしたり他の引数を入れたりしてFormatterに入れる引数を作ったりします 28 func makeSet(values: [Double]) -> (types: [ActivityType], values: [Double]) { 29 let minutesValues = values.map{$0 * 60} // 分表記 30 let types: [ActivityType] = [.sleeping, .blank, .training, .blank] 31 return (types, minutesValues) 32 } 33 34 //追記 ここではすでに作られたpieChartの一部分だけを修正して、それをpieChartに通知します。そうすることで画面に表示されているチャートの情報が書き換わります。 35 func change(types: [ActivityType], values: [Double]) { 36 guard let dataSet = pieChart.data?.dataSets.first as? PieChartDataSet else { 37 fatalError() 38 } 39 let entries = values.map{PieChartDataEntry(value: Double($0))} 40 dataSet.values = entries 41 dataSet.valueFormatter = CustomLabelFomatter(types: types, values: values) 42 pieChart.notifyDataSetChanged() 43 } 44 45 func makePieChart() { 46 let hourValues = [8, 4, 2, 9.6, 0.4] // <=24時間、時間表記 47 let minutesValues = hourValues.map{$0 * 60} // 分表記 48 let types: [ActivityType] = [.sleeping, .blank, .training, .blank, .training] 49 50 let entries = minutesValues.map{ element -> PieChartDataEntry in 51 let value = Double(element) 52 return PieChartDataEntry(value: value) 53 } 54 //entriesは[PieChartDataEntry] 55 let dataSet = PieChartDataSet(values: entries, label: "") 56 57 dataSet.colors = [.purple, .gray, .blue, .gray, .blue] 58 dataSet.valueFormatter = CustomLabelFomatter(types: types, values: minutesValues) //<=ここでFormatterを設定 59 60 let data = PieChartData(dataSet: dataSet) 61 pieChart.data = data 62 } 63} 64 65//下記にもありますが[String]を用意せずにtype.rawValueという形でlabelを表示していきます。ここはそのための下準備 66enum ActivityType: String { 67 case sleeping = "睡眠" 68 case training = "トレーニング" 69 case blank = "空白" 70} 71 72class CustomLabelFomatter: NSObject, IValueFormatter { 73 74 let types: [ActivityType] //最初は[String]でやっていましたがTypeを作ってやる方法に興味がありそうなのでそちらでやっています 75 let values: [Double] 76 77 init(types: [ActivityType], values: [Double]) { 78 self.types = types 79 self.values = values 80 } 81 82 func convert(value: Double) -> String { 83 guard let convertedString = values 84 .enumerated() 85 .filter({$0.element == value}) 86 .map({ tuple -> String in 87 88 let index = tuple.offset 89 let type = types[index] 90 91 //例えがvalueが5.0より少ないときは何も表示しないとの事でしたが5.0だと扱いにくいので条件を変えています。具体的にはvalueの中身を分表記にして30分未満の場合は何も表示しないとしています。なので最後のPieChartDataEntryにはlabelがありません。 92 //ちなみにこんな風に処理の途中でreturnするのを早期リターンと言います。早期リターンを行うとそこより下の処理はせずとっとと次の処理に行くのでいろんな面で優しいです。 93 if value < 0.5 * 60 { 94 print("早期リターン") 95 return "" 96 //ちなみにこんな風に処理の途中でreturnするのを早期リターンと言います。早期リターンを行うとそこより下の処理はせずとっとと次の処理に行くのでいろんな面で優しいです。 97 } 98 99 print("処理継続中") 100 101 switch type { //今回はあまりメリットがありませんがswitch + enumはかなり強力です。漏れがあるとXcodeからお叱りが飛んできます。単純な処理だけど場合分けの量が多い時なんかはif文よりswitch文 + enumの方が楽でしょうね。 102 case .blank: 103 return "" //.blankの場合は何も表示しません 104 default: 105 return type.rawValue //が、そのほかのtypeだった場合enumのrawValueを呼び出します。こいつはActivityTypeを見れば分かりますがStringを返しています。 106 } 107 108 }).first else {fatalError()} 109 110 return convertedString 111 } 112 113 func stringForValue(_ value: Double, entry: ChartDataEntry, dataSetIndex: Int, viewPortHandler: ViewPortHandler?) -> String { 114 print(value) //ここでのvalueは各々のPieChartDataEntryのvalueです 115 return convert(value: value) 116 } 117} 118
投稿2018/09/19 15:12
編集2018/09/21 03:48総合スコア1349
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/09/20 01:59
2018/09/20 03:12
2018/09/20 13:29 編集
2018/09/20 13:34 編集
2018/09/20 13:48
2018/09/20 14:53
2018/09/21 00:59
2018/09/21 03:53 編集
2018/09/21 03:55
2018/09/21 10:57
2018/09/21 11:02 編集
2018/10/12 03:48
2018/10/12 05:00