diff --git a/src/main.js b/src/main.js index efb886b985ec0183dfa98b2e9d9b0fa8acfa2356..5bf6f34d2a1d5aba8a9b812eef217ef3262f4683 100644 --- a/src/main.js +++ b/src/main.js @@ -5,7 +5,7 @@ const config = { controls: { mouse: true, button: true, - voice: false, + voice: true, motion: true, }, }; @@ -140,7 +140,6 @@ function init() { // listen for WebSocket messages socket.addEventListener("message", (event) => { let message = JSON.parse(event.data); - console.log(message); // perform action without broadcasting message again if (message.type === "select") navigateToPath(message.value, true, false); @@ -335,23 +334,19 @@ function focusPreviousNavigationItem() { } // focus closest item to point -function focusClosestItem( - focusPoint = new Point(window.innerWidth / 2, window.innerHeight / 2) -) { +function focusClosestItem(targetY = window.innerHeight / 2) { + targetY = targetY + window.innerHeight / 2; let lastDistance = 10000; let index = 1; let closestIndex = 0; const itemList = document.querySelectorAll("#navigation ul li"); for (let item of itemList) { let rect = item.getBoundingClientRect(); - let itemCenterPoint = new Point( - rect.left + rect.width / 2, - rect.top + rect.height / 2 - ); - let vector = new Vector(focusPoint, itemCenterPoint); - if (vector.magnitude <= lastDistance) { + let itemCenterY = rect.top + rect.height / 2; + let distance = Math.abs(targetY - itemCenterY); + if (distance <= lastDistance) { closestIndex = index; - lastDistance = vector.magnitude; + lastDistance = distance; } index++; } @@ -565,9 +560,17 @@ function addVoiceControls() { // add motion controls // =================== function addMotionControls() { - let pointOfReference; - let vectorToReference; - let screenCenter; + let referenceY; + let sensitivity = 5000; + let screenCenter = new Point(window.innerWidth / 2, window.innerHeight / 2); + + // motion buffer stuff + let motionBuffer = []; + let lastAverageY = 0; + let bufferIterations = 0; + const bufferIterationLimit = 10; + const bufferLength = 20; + const motionThreshold = 0.02; // create canvas element for motion visualization const canvasEl = document.createElement("canvas"); @@ -578,7 +581,7 @@ function addMotionControls() { //available headset sensors: accelerometer, gyroscope, relativeOrientation, linearAcceleration, GravitySensor //unavailable headset sensors: magnetometer (this results in horizontal drifting) - const options = { frequency: 20, referenceFrame: "device" }; + const options = { frequency: 30, referenceFrame: "device" }; const sensor = new RelativeOrientationSensor(options); sensor.addEventListener("reading", onChangeOrientation); @@ -594,61 +597,54 @@ function addMotionControls() { // handle motion sensor event function onChangeOrientation(event) { let quaternion = event.target.quaternion; - if (pointOfReference === undefined) setPointOfReference(quaternion); - - let mapped = { - x: quaternion[0], - y: quaternion[1], - z: quaternion[2], - w: quaternion[3], - }; - - let targetPoint = new Point(mapped.x, mapped.y); - let motionVector = new Vector(pointOfReference, targetPoint); - motionVector = motionVector.subtract(vectorToReference); - motionVector = motionVector.scale(200); - motionVector = motionVector.add( - new Vector( - new Point(), - new Point(canvasEl.width / 2, canvasEl.height / 2) - ) - ); - - // focus closest item - // ADD THRESHOLD BEFORE TRIGGERING! - focusClosestItem(motionVector); - - drawMotion(motionVector); - // printLogMsg(`${motionVector.magnitude.toFixed(2)}`); - } - - // set new point of reference - function setPointOfReference(quaternion) { - pointOfReference = new Point(quaternion[0], quaternion[1]); - vectorToReference = new Vector(new Point(), pointOfReference); + let y = quaternion[1]; + + // write quaternion y value into motion buffer + motionBuffer.push(y); + + // limit buffer length + if (motionBuffer.length > bufferLength) motionBuffer.shift(); + // check motion range within buffer + if (motionBuffer.length === bufferLength) { + let averageY, averageYDiff; + // calculate average every bufferIterations + if (!averageY || bufferIterations > bufferIterationLimit) { + // calculate average value of array numbers + averageY = motionBuffer.reduce((a, b) => a + b) / motionBuffer.length; + if (!referenceY) referenceY = averageY; // set initial reference point + bufferIterations = 0; + } + bufferIterations++; + averageYDiff = Math.abs(lastAverageY - averageY); + if (averageYDiff > motionThreshold && referenceY !== undefined) { + lastAverageY = averageY; + let targetY = averageY; + targetY = (targetY - referenceY) * -sensitivity; + + // drawMotion(targetY); + focusClosestItem(targetY); + } + } } - function drawMotion(vector) { + function drawMotion(y) { if (canvasEl.getContext) { const ctx = canvasEl.getContext("2d"); - const pointSize = 10; + const pointSize = 20; ctx.clearRect(0, 0, canvasEl.width, canvasEl.height); + ctx.strokeStyle = "rgba(255, 0, 255, .7)"; + ctx.lineWidth = 5; - ctx.strokeStyle = "#FFFFFF"; - ctx.fillStyle = "#FFFFFF"; - ctx.lineWidth = 2; + ctx.beginPath(); + ctx.moveTo(screenCenter.x, screenCenter.y); + ctx.lineTo(screenCenter.x, screenCenter.y + y); + ctx.stroke(); + ctx.closePath(); ctx.beginPath(); - ctx.moveTo(canvasEl.width / 2, canvasEl.height / 2); - ctx.lineTo(vector.x, vector.y); + ctx.arc(screenCenter.x, screenCenter.y + y, pointSize, 0, 2 * Math.PI); ctx.stroke(); - ctx.fillRect( - vector.x - pointSize / 2, - vector.y - pointSize / 2, - pointSize, - pointSize - ); } } } diff --git a/src/styles/main.css b/src/styles/main.css index 3bfa9394a3b0c567c4a717e2c6b3ba8bc4dafc02..7648f41a478b02d183d5c14ef621761ee2239d05 100644 --- a/src/styles/main.css +++ b/src/styles/main.css @@ -102,7 +102,7 @@ aside { #log { color: hsl(0, 100%, 80%); position: absolute; - font: normal 1em/1.2em sans-serif; + font: normal 3vw/1.2em sans-serif; top: 0; left: 0; max-height: 20vh; diff --git a/src/styles/main.less b/src/styles/main.less index c0e7cdf61b0428f60a331ac3be82b119c3d0262b..beddea41f38d906044bcd8aa43cee9df8a979ee8 100644 --- a/src/styles/main.less +++ b/src/styles/main.less @@ -118,7 +118,7 @@ aside { #log { color: hsl(0 100% 80%); position: absolute; - font: normal 1em/1.2em sans-serif; + font: normal 3vw/1.2em sans-serif; top: 0; left: 0; max-height: 20vh;