回答編集履歴

3

Animation GIFを追加

2020/09/17 09:00

投稿

TsukubaDepot
TsukubaDepot

スコア5086

test CHANGED
@@ -88,6 +88,12 @@
88
88
 
89
89
  ##描画完了した瞬間に、指定したデータに円弧を書かせる方法
90
90
 
91
+
92
+
93
+ ![イメージ説明](973b638f1f94c218e25972b7368dcc83.gif)
94
+
95
+
96
+
91
97
  [https://github.com/danielgindi/Charts/blob/master/ChartsDemo-iOS/Swift/DemoBaseViewController.swift
92
98
 
93
99
  ](https://github.com/danielgindi/Charts/blob/master/ChartsDemo-iOS/Swift/DemoBaseViewController.swift)

2

コメントを受けた問題の解決

2020/09/17 09:00

投稿

TsukubaDepot
TsukubaDepot

スコア5086

test CHANGED
@@ -86,19 +86,41 @@
86
86
 
87
87
 
88
88
 
89
- ##指定したポイントに円弧を描くためのコードの
89
+ ##描画完了した瞬間に、指定したデータに円弧を書かせる方法
90
+
91
+ [https://github.com/danielgindi/Charts/blob/master/ChartsDemo-iOS/Swift/DemoBaseViewController.swift
92
+
93
+ ](https://github.com/danielgindi/Charts/blob/master/ChartsDemo-iOS/Swift/DemoBaseViewController.swift)
94
+
95
+
96
+
97
+ github 上のサンプルに対して加えた変更なのでちょっと複雑な流れになっています。
98
+
99
+
100
+
101
+ このサンプルの場合、delegate が親クラスとなっているため、途中でダウンキャストを行なっていますが、そうでない場合にはもっとシンプルに記述できると思われます。
102
+
103
+
104
+
105
+ 解決のヒントになったissue:
106
+
107
+ - [(v3.0 + Swift3.0)ChartView highlightValueWithX not working #1495](https://github.com/danielgindi/Charts/issues/1495)
108
+
109
+
90
110
 
91
111
  ```Swift
92
112
 
93
113
  // 表示が完全に止まったら呼び出される delegate
94
114
 
115
+ // https://github.com/danielgindi/Charts/issues/1495
116
+
95
117
  func chartView(_ chartView: ChartViewBase, animatorDidStop animator: Animator) {
96
118
 
97
- print(#function)
98
-
99
- //chartView.highlightValue(Highlight(x: values[19].x, y: values[19].y, dataSetIndex: 0), callDelegate: true)
119
+ // chartView に保存されているデータセットのうち、1つ目を取り出す
100
120
 
101
121
  if let set1 = chartView.data?.getDataSetByIndex(0) {
122
+
123
+ // 取り出したデータセットのうち、19番目を取り出す
102
124
 
103
125
  if let val = set1.entryForIndex(19) {
104
126
 
@@ -108,55 +130,63 @@
108
130
 
109
131
 
110
132
 
111
- // ここで得られるハイライト座標には、View 内部での座標(xPx, yPx)が代入されないため、円弧を書くための座標を算出することができない
112
-
113
- let hightlight = Highlight(x: val.x, y: val.y, dataSetIndex: 0)
114
-
115
133
 
116
134
 
117
- // 点滅させ
135
+ // delegate が親クラスになっていため、view を一度子クラスの LineChartView にダウンキャストする
118
136
 
119
- // ** 以下のコードを実施しても、xPx, yPx が nan のため正しく表示されない
137
+ if let view = chartView as? LineChartView {
120
138
 
121
- // 以前アニメション消す
139
+ // 生データと画面上変換させる
122
140
 
123
- circleLayer?.removeFromSuperlayer()
141
+ let transformer = view.getTransformer(forAxis: view.leftAxis.axisDependency)
124
142
 
125
-
143
+ // ここで得られた値が生データ
126
144
 
127
- // 透明度のアニメーションを設定する。
145
+ let pt = transformer.pixelForValues(x: val.x, y: val.y)
128
146
 
129
- // alpha ではなく、opacity であることに注意。
147
+
130
148
 
131
- let animation = CAKeyframeAnimation(keyPath: "opacity")
149
+ // 以前のアニメーションを消す
132
150
 
133
- animation.duration = 1
151
+ circleLayer?.removeFromSuperlayer()
134
152
 
135
- animation.keyTimes = [0.0, 0.5, 1.0]
153
+
136
154
 
137
- animation.values = [1.0, 0.00, 1.0]
155
+ // 透明度のアニメーションを設定する。
138
156
 
139
- animation.repeatCount = .greatestFiniteMagnitude
157
+ // alpha ではなく、opacity であることに注意。
140
158
 
141
-
159
+ let animation = CAKeyframeAnimation(keyPath: "opacity")
142
160
 
143
- // タップされた座標を中心として円形を作る
161
+ animation.duration = 1
144
162
 
145
- circleLayer = CAShapeLayer()
163
+ animation.keyTimes = [0.0, 0.5, 1.0]
146
164
 
147
- let circlePath = UIBezierPath(arcCenter: CGPoint(x: highlight.xPx, y: highlight.yPx), radius: 20, startAngle: 0, endAngle: .pi*2, clockwise: true)
165
+ animation.values = [1.0, 0.00, 1.0]
148
166
 
149
- circleLayer?.path = circlePath.cgPath
167
+ animation.repeatCount = .greatestFiniteMagnitude
150
168
 
151
- circleLayer?.strokeColor = UIColor.red.cgColor
169
+
152
170
 
153
- circleLayer?.fillColor = UIColor.clear.cgColor
171
+ // タップされた座標を中心として円形を作る
154
172
 
155
- circleLayer?.lineWidth = 2.0
173
+ circleLayer = CAShapeLayer()
156
174
 
157
- circleLayer?.add(animation, forKey: nil)
175
+ let circlePath = UIBezierPath(arcCenter: CGPoint(x: pt.x, y: pt.y), radius: 20, startAngle: 0, endAngle: .pi*2, clockwise: true)
158
176
 
177
+ circleLayer?.path = circlePath.cgPath
178
+
179
+ circleLayer?.strokeColor = UIColor.red.cgColor
180
+
181
+ circleLayer?.fillColor = UIColor.clear.cgColor
182
+
183
+ circleLayer?.lineWidth = 2.0
184
+
185
+ circleLayer?.add(animation, forKey: nil)
186
+
159
- chartView.layer.addSublayer(circleLayer!)
187
+ chartView.layer.addSublayer(circleLayer!)
188
+
189
+ }
160
190
 
161
191
  }
162
192
 
@@ -164,4 +194,6 @@
164
194
 
165
195
  }
166
196
 
197
+
198
+
167
199
  ```

1

試行したコードを追記

2020/09/17 08:53

投稿

TsukubaDepot
TsukubaDepot

スコア5086

test CHANGED
@@ -83,3 +83,85 @@
83
83
 
84
84
 
85
85
  この実装はまだ中途半端で、たとえばスケールファクターを変更した場合には、赤丸が残ったまま追従しないなどの問題もありますが、それは追々解決していただければと思います。
86
+
87
+
88
+
89
+ ##指定したポイントに円弧を描くためのコードの書きかけ
90
+
91
+ ```Swift
92
+
93
+ // 表示が完全に止まったら呼び出される delegate
94
+
95
+ func chartView(_ chartView: ChartViewBase, animatorDidStop animator: Animator) {
96
+
97
+ print(#function)
98
+
99
+ //chartView.highlightValue(Highlight(x: values[19].x, y: values[19].y, dataSetIndex: 0), callDelegate: true)
100
+
101
+ if let set1 = chartView.data?.getDataSetByIndex(0) {
102
+
103
+ if let val = set1.entryForIndex(19) {
104
+
105
+ // ハイライトさせる
106
+
107
+ chartView.highlightValue(Highlight(x: val.x, y: val.y, dataSetIndex: 0), callDelegate: true)
108
+
109
+
110
+
111
+ // ここで得られるハイライト座標には、View 内部での座標(xPx, yPx)が代入されないため、円弧を書くための座標を算出することができない
112
+
113
+ let hightlight = Highlight(x: val.x, y: val.y, dataSetIndex: 0)
114
+
115
+
116
+
117
+ // 点滅させる
118
+
119
+ // ** 以下のコードを実施しても、xPx, yPx が nan のため正しく表示されない
120
+
121
+ // 以前のアニメーションを消す
122
+
123
+ circleLayer?.removeFromSuperlayer()
124
+
125
+
126
+
127
+ // 透明度のアニメーションを設定する。
128
+
129
+ // alpha ではなく、opacity であることに注意。
130
+
131
+ let animation = CAKeyframeAnimation(keyPath: "opacity")
132
+
133
+ animation.duration = 1
134
+
135
+ animation.keyTimes = [0.0, 0.5, 1.0]
136
+
137
+ animation.values = [1.0, 0.00, 1.0]
138
+
139
+ animation.repeatCount = .greatestFiniteMagnitude
140
+
141
+
142
+
143
+ // タップされた座標を中心として円形を作る
144
+
145
+ circleLayer = CAShapeLayer()
146
+
147
+ let circlePath = UIBezierPath(arcCenter: CGPoint(x: highlight.xPx, y: highlight.yPx), radius: 20, startAngle: 0, endAngle: .pi*2, clockwise: true)
148
+
149
+ circleLayer?.path = circlePath.cgPath
150
+
151
+ circleLayer?.strokeColor = UIColor.red.cgColor
152
+
153
+ circleLayer?.fillColor = UIColor.clear.cgColor
154
+
155
+ circleLayer?.lineWidth = 2.0
156
+
157
+ circleLayer?.add(animation, forKey: nil)
158
+
159
+ chartView.layer.addSublayer(circleLayer!)
160
+
161
+ }
162
+
163
+ }
164
+
165
+ }
166
+
167
+ ```