回答編集履歴
3
Animation GIFを追加
answer
CHANGED
@@ -43,6 +43,9 @@
|
|
43
43
|
この実装はまだ中途半端で、たとえばスケールファクターを変更した場合には、赤丸が残ったまま追従しないなどの問題もありますが、それは追々解決していただければと思います。
|
44
44
|
|
45
45
|
##描画完了した瞬間に、指定したデータに円弧を書かせる方法
|
46
|
+
|
47
|
+

|
48
|
+
|
46
49
|
[https://github.com/danielgindi/Charts/blob/master/ChartsDemo-iOS/Swift/DemoBaseViewController.swift
|
47
50
|
](https://github.com/danielgindi/Charts/blob/master/ChartsDemo-iOS/Swift/DemoBaseViewController.swift)
|
48
51
|
|
2
コメントを受けた問題の解決
answer
CHANGED
@@ -42,43 +42,59 @@
|
|
42
42
|
|
43
43
|
この実装はまだ中途半端で、たとえばスケールファクターを変更した場合には、赤丸が残ったまま追従しないなどの問題もありますが、それは追々解決していただければと思います。
|
44
44
|
|
45
|
-
##指定した
|
45
|
+
##描画完了した瞬間に、指定したデータに円弧を書かせる方法
|
46
|
+
[https://github.com/danielgindi/Charts/blob/master/ChartsDemo-iOS/Swift/DemoBaseViewController.swift
|
47
|
+
](https://github.com/danielgindi/Charts/blob/master/ChartsDemo-iOS/Swift/DemoBaseViewController.swift)
|
48
|
+
|
49
|
+
github 上のサンプルに対して加えた変更なのでちょっと複雑な流れになっています。
|
50
|
+
|
51
|
+
このサンプルの場合、delegate が親クラスとなっているため、途中でダウンキャストを行なっていますが、そうでない場合にはもっとシンプルに記述できると思われます。
|
52
|
+
|
53
|
+
解決のヒントになったissue:
|
54
|
+
- [(v3.0 + Swift3.0)ChartView highlightValueWithX not working #1495](https://github.com/danielgindi/Charts/issues/1495)
|
55
|
+
|
46
56
|
```Swift
|
47
57
|
// 表示が完全に止まったら呼び出される delegate
|
58
|
+
// https://github.com/danielgindi/Charts/issues/1495
|
48
59
|
func chartView(_ chartView: ChartViewBase, animatorDidStop animator: Animator) {
|
49
|
-
print(#function)
|
50
|
-
//chartView
|
60
|
+
// chartView に保存されているデータセットのうち、1つ目を取り出す
|
51
61
|
if let set1 = chartView.data?.getDataSetByIndex(0) {
|
62
|
+
// 取り出したデータセットのうち、19番目を取り出す
|
52
63
|
if let val = set1.entryForIndex(19) {
|
53
64
|
// ハイライトさせる
|
54
65
|
chartView.highlightValue(Highlight(x: val.x, y: val.y, dataSetIndex: 0), callDelegate: true)
|
55
66
|
|
56
|
-
// ここで得られるハイライト座標には、View 内部での座標(xPx, yPx)が代入されないため、円弧を書くための座標を算出することができない
|
57
|
-
let hightlight = Highlight(x: val.x, y: val.y, dataSetIndex: 0)
|
58
67
|
|
68
|
+
// delegate が親クラスになっているため、view を一度子クラスの LineChartView にダウンキャストする
|
69
|
+
if let view = chartView as? LineChartView {
|
70
|
+
// 生データと画面上のデータを変換させる
|
71
|
+
let transformer = view.getTransformer(forAxis: view.leftAxis.axisDependency)
|
59
|
-
|
72
|
+
// ここで得られた値が生データ
|
60
|
-
|
73
|
+
let pt = transformer.pixelForValues(x: val.x, y: val.y)
|
74
|
+
|
61
|
-
|
75
|
+
// 以前のアニメーションを消す
|
62
|
-
|
76
|
+
circleLayer?.removeFromSuperlayer()
|
63
|
-
|
77
|
+
|
64
|
-
|
78
|
+
// 透明度のアニメーションを設定する。
|
65
|
-
|
79
|
+
// alpha ではなく、opacity であることに注意。
|
66
|
-
|
80
|
+
let animation = CAKeyframeAnimation(keyPath: "opacity")
|
67
|
-
|
81
|
+
animation.duration = 1
|
68
|
-
|
82
|
+
animation.keyTimes = [0.0, 0.5, 1.0]
|
69
|
-
|
83
|
+
animation.values = [1.0, 0.00, 1.0]
|
70
|
-
|
84
|
+
animation.repeatCount = .greatestFiniteMagnitude
|
71
|
-
|
85
|
+
|
72
|
-
|
86
|
+
// タップされた座標を中心として円形を作る
|
73
|
-
|
87
|
+
circleLayer = CAShapeLayer()
|
74
|
-
|
88
|
+
let circlePath = UIBezierPath(arcCenter: CGPoint(x: pt.x, y: pt.y), radius: 20, startAngle: 0, endAngle: .pi*2, clockwise: true)
|
75
|
-
|
89
|
+
circleLayer?.path = circlePath.cgPath
|
76
|
-
|
90
|
+
circleLayer?.strokeColor = UIColor.red.cgColor
|
77
|
-
|
91
|
+
circleLayer?.fillColor = UIColor.clear.cgColor
|
78
|
-
|
92
|
+
circleLayer?.lineWidth = 2.0
|
79
|
-
|
93
|
+
circleLayer?.add(animation, forKey: nil)
|
80
|
-
|
94
|
+
chartView.layer.addSublayer(circleLayer!)
|
95
|
+
}
|
81
96
|
}
|
82
97
|
}
|
83
98
|
}
|
99
|
+
|
84
100
|
```
|
1
試行したコードを追記
answer
CHANGED
@@ -40,4 +40,45 @@
|
|
40
40
|
|
41
41
|
本当は、アニメーションに対して適切な keyPath を設定し、次回以降はそれを使って削除できれば見通しが良いのですが、なぜかうまくいかなかったので、 ViewController のプロパティとして `CAShapeLayer` のプロパティを持たせ、2回目以降はそれを使ってアニメーションを消すようにしています。
|
42
42
|
|
43
|
-
この実装はまだ中途半端で、たとえばスケールファクターを変更した場合には、赤丸が残ったまま追従しないなどの問題もありますが、それは追々解決していただければと思います。
|
43
|
+
この実装はまだ中途半端で、たとえばスケールファクターを変更した場合には、赤丸が残ったまま追従しないなどの問題もありますが、それは追々解決していただければと思います。
|
44
|
+
|
45
|
+
##指定したポイントに円弧を描くためのコードの書きかけ
|
46
|
+
```Swift
|
47
|
+
// 表示が完全に止まったら呼び出される delegate
|
48
|
+
func chartView(_ chartView: ChartViewBase, animatorDidStop animator: Animator) {
|
49
|
+
print(#function)
|
50
|
+
//chartView.highlightValue(Highlight(x: values[19].x, y: values[19].y, dataSetIndex: 0), callDelegate: true)
|
51
|
+
if let set1 = chartView.data?.getDataSetByIndex(0) {
|
52
|
+
if let val = set1.entryForIndex(19) {
|
53
|
+
// ハイライトさせる
|
54
|
+
chartView.highlightValue(Highlight(x: val.x, y: val.y, dataSetIndex: 0), callDelegate: true)
|
55
|
+
|
56
|
+
// ここで得られるハイライト座標には、View 内部での座標(xPx, yPx)が代入されないため、円弧を書くための座標を算出することができない
|
57
|
+
let hightlight = Highlight(x: val.x, y: val.y, dataSetIndex: 0)
|
58
|
+
|
59
|
+
// 点滅させる
|
60
|
+
// ** 以下のコードを実施しても、xPx, yPx が nan のため正しく表示されない
|
61
|
+
// 以前のアニメーションを消す
|
62
|
+
circleLayer?.removeFromSuperlayer()
|
63
|
+
|
64
|
+
// 透明度のアニメーションを設定する。
|
65
|
+
// alpha ではなく、opacity であることに注意。
|
66
|
+
let animation = CAKeyframeAnimation(keyPath: "opacity")
|
67
|
+
animation.duration = 1
|
68
|
+
animation.keyTimes = [0.0, 0.5, 1.0]
|
69
|
+
animation.values = [1.0, 0.00, 1.0]
|
70
|
+
animation.repeatCount = .greatestFiniteMagnitude
|
71
|
+
|
72
|
+
// タップされた座標を中心として円形を作る
|
73
|
+
circleLayer = CAShapeLayer()
|
74
|
+
let circlePath = UIBezierPath(arcCenter: CGPoint(x: highlight.xPx, y: highlight.yPx), radius: 20, startAngle: 0, endAngle: .pi*2, clockwise: true)
|
75
|
+
circleLayer?.path = circlePath.cgPath
|
76
|
+
circleLayer?.strokeColor = UIColor.red.cgColor
|
77
|
+
circleLayer?.fillColor = UIColor.clear.cgColor
|
78
|
+
circleLayer?.lineWidth = 2.0
|
79
|
+
circleLayer?.add(animation, forKey: nil)
|
80
|
+
chartView.layer.addSublayer(circleLayer!)
|
81
|
+
}
|
82
|
+
}
|
83
|
+
}
|
84
|
+
```
|