iPhoneアプリで加速度センサーの値を取得する方法については多くの記事が見つかりましたが、リアルタイムに計測値をグラフ表示する方法についてはなかなか見つけられなかったので試行錯誤で作成してみました。
以下が動作結果です。
スマホを振ると加速度の値も変化しておりながらリアルタイムの表示ができました。
ソースコード
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)!) } )
以上。