iPhoneアプリで加速度センサーの値を取得する方法については多くの記事が見つかりましたが、リアルタイムに計測値をグラフ表示する方法についてはなかなか見つけられなかったので試行錯誤で作成してみました。
以下が動作結果です。
スマホを振ると加速度の値も変化しておりながらリアルタイムの表示ができました。
ソースコード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 |
import UIKit import CoreMotion import Charts class ViewController: UIViewController{ let motionManager = CMMotionManager() // チャート var chartView1 = LineChartView() var chartView2 = LineChartView() var chartView3 = LineChartView() var dataEntries1 = [ChartDataEntry]() var dataEntries2 = [ChartDataEntry]() var dataEntries3 = [ChartDataEntry]() var xValue: Double = 8 override func viewDidLoad() { super.viewDidLoad() setupViews() setupInitialDataEntries() setupChartData() //加速度値を取得 motionManager.accelerometerUpdateInterval = 0.1 motionManager.startAccelerometerUpdates( to:OperationQueue.current!, withHandler: {(accelData:CMAccelerometerData?,errorOC: Error?) in self.didUpdatedChartView1(yValue: (accelData?.acceleration.z)!) self.didUpdatedChartView2(yValue: (accelData?.acceleration.y)!) self.didUpdatedChartView3(yValue: (accelData?.acceleration.x)!) } ) } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) //Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(didUpdatedChartView), userInfo: nil, repeats: true) } func stopAccelerometer(){ if(motionManager.isAccelerometerActive){ motionManager.stopAccelerometerUpdates() } } func didUpdatedChartView1(yValue: Double) { let newDataEntry = ChartDataEntry(x: xValue, y: yValue) updateChartView1(with: newDataEntry, dataEntries: &dataEntries1) xValue += 1 } func didUpdatedChartView2(yValue: Double) { let newDataEntry = ChartDataEntry(x: xValue, y: yValue) updateChartView2(with: newDataEntry, dataEntries: &dataEntries2) xValue += 1 } func didUpdatedChartView3(yValue: Double) { let newDataEntry = ChartDataEntry(x: xValue, y: yValue) updateChartView3(with: newDataEntry, dataEntries: &dataEntries3) xValue += 1 } func setupViews() { //z view.addSubview(chartView1) chartView1.translatesAutoresizingMaskIntoConstraints = false //chartView1.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true //chartView1.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true chartView1.frame = CGRect(x: 0 ,y: (self.view.frame.height/2)+100,width: self.view.frame.width,height: 150) //chartView1.widthAnchor.constraint(equalToConstant: view.frame.width - 32).isActive = true //chartView1.heightAnchor.constraint(equalToConstant: 100).isActive = true chartView1.leftAxis.axisMaximum = 1.2 //y左軸最大値 chartView1.leftAxis.axisMinimum = -1.2 //y左軸最小値 chartView1.leftAxis.labelCount = 5 //y軸ラベルの表示数 chartView1.leftAxis.drawTopYLabelEntryEnabled = true //y軸の最大値 chartView1.rightAxis.enabled = false //y右軸を非表示 chartView1.legend.enabled = true //凡例を表示 //y view.addSubview(chartView2) chartView2.translatesAutoresizingMaskIntoConstraints = false chartView2.frame = CGRect(x: 0 ,y: (self.view.frame.height/2)-100, width: self.view.frame.width,height: 150) chartView2.leftAxis.axisMaximum = 1.2 //y左軸最大値 chartView2.leftAxis.axisMinimum = -1.2 //y左軸最小値 chartView2.leftAxis.labelCount = 5 //y軸ラベルの表示数 chartView2.leftAxis.drawTopYLabelEntryEnabled = true //y軸の最大値 chartView2.rightAxis.enabled = false //y右軸を非表示 chartView2.legend.enabled = true //凡例を表示 //x view.addSubview(chartView3) chartView3.translatesAutoresizingMaskIntoConstraints = false chartView3.frame = CGRect(x: 0 ,y: (self.view.frame.height/2)-250,width: self.view.frame.width,height: 150) chartView3.leftAxis.axisMaximum = 1.2 //y左軸最大値 chartView3.leftAxis.axisMinimum = -1.2 //y左軸最小値 chartView3.leftAxis.labelCount = 5 //y軸ラベルの表示数 chartView3.leftAxis.drawTopYLabelEntryEnabled = true //y軸の最大値 chartView3.rightAxis.enabled = false //y右軸を非表示 chartView3.legend.enabled = true //凡例を表示 } func setupInitialDataEntries() { (0..<Int(xValue)).forEach { let dataEntry = ChartDataEntry(x: Double($0), y: 0) dataEntries1.append(dataEntry) dataEntries2.append(dataEntry) dataEntries3.append(dataEntry) } } func setupChartData() { //z let chartDataSet1 = LineChartDataSet(entries: dataEntries1, label: "z-ac") chartDataSet1.drawCirclesEnabled = false chartDataSet1.setColor(NSUIColor.red) chartDataSet1.mode = .linear chartDataSet1.drawValuesEnabled = false let chartData1 = LineChartData(dataSet: chartDataSet1) chartView1.data = chartData1 chartView1.xAxis.labelPosition = .bottom //y let chartDataSet2 = LineChartDataSet(entries: dataEntries2, label: "y-ac") chartDataSet2.drawCirclesEnabled = false chartDataSet2.setColor(NSUIColor.green) chartDataSet2.mode = .linear chartDataSet2.drawValuesEnabled = false let chartData2 = LineChartData(dataSet: chartDataSet2) chartView2.data = chartData2 chartView2.xAxis.labelPosition = .bottom //x let chartDataSet3 = LineChartDataSet(entries: dataEntries3, label: "x-ac") chartDataSet3.drawCirclesEnabled = false chartDataSet3.setColor(NSUIColor.blue) chartDataSet3.mode = .linear chartDataSet3.drawValuesEnabled = false let chartData3 = LineChartData(dataSet: chartDataSet3) chartView3.data = chartData3 chartView3.xAxis.labelPosition = .bottom } func updateChartView1(with newDataEntry: ChartDataEntry, dataEntries: inout [ChartDataEntry]) { dataEntries.append(newDataEntry) chartView1.data?.addEntry(newDataEntry, dataSetIndex: 0) chartView1.notifyDataSetChanged() chartView1.moveViewToX(newDataEntry.x) } func updateChartView2(with newDataEntry: ChartDataEntry, dataEntries: inout [ChartDataEntry]) { dataEntries.append(newDataEntry) chartView2.data?.addEntry(newDataEntry, dataSetIndex: 0) chartView2.notifyDataSetChanged() chartView2.moveViewToX(newDataEntry.x) } func updateChartView3(with newDataEntry: ChartDataEntry, dataEntries: inout [ChartDataEntry]) { dataEntries.append(newDataEntry) chartView3.data?.addEntry(newDataEntry, dataSetIndex: 0) chartView3.notifyDataSetChanged() chartView3.moveViewToX(newDataEntry.x) } } |
処理の流れ
(1) 折れ線チャートをインスタンス
var chartView1 = LineChartView()
(2)Viewに折れ線チャートを加える。
view.addSubview(chartView1)
以降に軸や凡例の表示について設定
(3) 加速度値を取得
例えば、x方向の加速度値は「accelData?.acceleration.x」に格納されます。
//加速度値を取得 motionManager.accelerometerUpdateInterval = 0.1 motionManager.startAccelerometerUpdates( to:OperationQueue.current!, withHandler: {(accelData:CMAccelerometerData?,errorOC: Error?) in self.didUpdatedChartView1(yValue: (accelData?.acceleration.z)!) self.didUpdatedChartView2(yValue: (accelData?.acceleration.y)!) self.didUpdatedChartView3(yValue: (accelData?.acceleration.x)!) } )
以上。