How do I capture acceleration of DeviceMotionEvent after button is pressed
I want to capture and save (maybe console.log()
too), the acceleration from the moment I press the start button which has startTest()
. But I don't know how to do such thing as I have never used these DeviceMotionEvent
. Any help on how can I start capturing the acceleration as described here and stop capturing it when I press the stop button would be highly appreciated. Thank you!
Here is my starting code with the buttons:
<template>
<q-page padding>
<div class="text-center text-h5 q-mt-lg">
{{ $t('tasks.motion.title') }}
</div>
<div class="row justify-center q-mt-lg">
<q-btn
@click="startTest"
v-show="!isStarted"
:label="$t('common.start')"
/>
<q-btn
@click="completeTest"
v-show="isStarted"
:label="$t('common.complete')"
/>
</div>
</q-page>
</template>
<script>
import phone from 'modules/phone'
import userinfo from 'modules/userinfo'
import { format as Qformat } from 'quasar'
const TEST_DURATION = 60
export default {
name: 'MotionOrientationPage',
props: {
sKey: String,
tId: Number
},
data: function () {
return {
isSignalCheck: true,
isStarted: false,
isCompleted: false,
timer: undefined,
totalTime: TEST_DURATION,
startedTS: undefined,
completionTS: undefined,
acceleration: [],
distance: 0
}
},
mounted: async function () {
},
methods: {
async startTest () {
this.isStarted = true
this.startedTS = new Date()
this.startTimer()
phone.screen.forbidSleep()
},
startTimer () {
this.totalTime = TEST_DURATION
this.timer = setInterval(() => this.countDown(), 1000)
},
stopTimer () {
clearInterval(this.timer)
},
countDown () {
if (this.totalTime >= 1) {
this.totalTime--
} else {
this.completeTest()
}
},
completeTest () {
this.isStarted = false
this.completionTS = new Date()
this.stopTimer()
phone.screen.allowSleep()
this.isCompleted = true
// package the report
const sKey = this.sKey
const taskId = parseInt(this.taskId)
const userKey = userinfo.user._key
let report = {
userKey: userKey,
sKey: sKey,
taskId: taskId,
createdTS: new Date(),
startedTS: this.startedTS,
completionTS: this.completionTS,
acceleration: this.acceleration,
distance: this.distance
}
this.$router.push({ name: 'reportMotionOrientation', params: { report: report } })
}
},
computed: {
minutes () {
return Qformat.pad(Math.floor(this.totalTime / 60))
},
seconds () {
return Qformat.pad(this.totalTime - (this.minutes * 60))
}
},
beforeDestroy: function () {
this.stopTimer()
phone.screen.allowSleep()
}
}
</script>
Updated 2022-01-04 23:52:26Z by
ga1996
Solution:
- Use a button to Start / Stop the test.
<button @click="toggleTest"> {{ isTestRunning ? "Stop Test" : "Start Test" }} </button> // javascript > vue methods toggleTest() { if (this.isTestRunning) { this.completeTest(); } else { this.startTest(); } },
- Add a DeviceMotionEvent handler upon starting the test to track the acceleration values.
window.addEventListener("devicemotion", this.reader, false)
// javascript > vue methods startTest(){ ... window.addEventListener("devicemotion", this.reader, false) ... }, ... reader(event) { console.log(event.acceleration.x + " m/s2"); this.accelerationX = event.acceleration.x | 0; // Acceleration has 3 axes (x, y, z) this.acceleration.push(event.acceleration.x | 0); },
- And remove the DeviceMotionEvent handler upon completion of the test.
window.removeEventListener("devicemotion", this.reader)
// javascript > vue methods completeTest(){ ... window.removeEventListener("devicemotion", this.reader) ... },
- All discrete acceleration reading for X axis will be stored in the acceleration array
Example:
https://codesandbox.io/s/js-devicemotion-pjn7v
const TEST_DURATION = 60; // in seconds
const FREQUENCY = 1000; // in milliseconds
const round = function(x) {
x = x * 1000;
x = Math.round(x);
x = x / 1000;
return Math.round(x);
};
new Vue({
el: '#app',
data() {
return {
timer: undefined,
isTestRunning: false,
timeElapsed: 0,
startedTS: undefined,
completionTS: undefined,
accelerationX: 0,
velocityX: 0,
distanceX: 0,
acceleration: [],
report: "Click on Start",
}
},
methods: {
reader(event) {
console.log(event.acceleration.x + " m/s2");
this.accelerationX = event.acceleration.x | 0;
// Acceleration has thre axes
this.acceleration.push(event.acceleration.x | 0);
//this.countDown();
},
toggleTest() {
if (this.isTestRunning) {
this.completeTest();
} else {
this.startTest();
}
},
startTest() {
this.startedTS = new Date();
this.completionTS = new Date();
this.isTestRunning = true;
this.startTimer();
window.addEventListener("devicemotion", this.reader, false);
},
startTimer() {
this.totalTime = TEST_DURATION;
this.timer = setInterval(this.countDown, FREQUENCY);
},
stopTimer() {
clearInterval(this.timer);
this.timer = undefined;
},
countDown() {
if (this.timeElapsed < TEST_DURATION) {
let timeDuration = (new Date().getTime() - this.completionTS) / 1000;
this.timeElapsed += timeDuration;
//Calculating only for X Axis here
// You may need to consider all 3 axes
this.velocityX = round(
this.velocityX + this.accelerationX * timeDuration
);
this.distanceX = round(
this.distanceX +
this.velocityX * timeDuration +
0.5 * this.accelerationX * timeDuration * timeDuration
);
this.completionTS = new Date();
} else {
this.completeTest();
}
},
completeTest() {
window.removeEventListener("devicemotion", this.reader);
this.stopTimer();
this.completionTS = new Date();
this.isTestRunning = false;
// package the report
let report = {
createdTS: new Date(),
startedTS: this.startedTS,
completionTS: this.completionTS,
accelerationX: this.accelerationX,
velocityX: this.velocityX,
distanceX: this.distanceX,
};
this.report = report;
//uncomment below line when required
//this.$router.push({ name: 'reportMotionOrientation', params: { report: report } })
},
},
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div class="row justify-center q-mt-lg">
<button @click="toggleTest">
{{ isTestRunning ? "Stop Test" : "Start Test" }}
</button>
<div v-if="isTestRunning">
<div>Time Elapsed :: {{ Math.round(timeElapsed) }}</div>
<div>Distance :: {{ distanceX }}</div>
<div>Velocity :: {{ velocityX }}</div>
<div>Acceleration X :: {{ accelerationX }}</div>
<div>Acceleration :: {{ acceleration }}</div>
</div>
<div v-else>
{{ report }}
</div>
</div>
</div>
Updated 2022-01-12 19:25:19Z by
Alpesh Patil
Tags:
vue javascriptvue javascript in templatevue javascript tutorialvue javascript in htmlvue javascript classvue javascript vs typescriptvue javascript heap out of memoryvue javascript to typescriptvue javascript examplevue javascript alertvue.jsvue.js tutorialvue.js vs reactvue.js devtoolsvue.js not detectedvue.js examplesvue.js vs angularvue.js watchvue.js propsvue.js interview questions