device orientation values jumping around? - javascript

is it normal that the alpha, beta, and gamma value of deviceorientation event aren't continuous? ( except from passing from -90 to 90, or 0 to 360 )
take a look at this picture : https://i.stack.imgur.com/JZfTc.png
when i roll my phone, at some point, the alpha ( yaw ) and and beta ( pitch ) value will "jump" to another value, while the gamma ( roll ) value will gradually go from -90 to 90
here's the project i'm currently working on to further demonstrate this : https://codepen.io/anon/pen/ReRORG open this up on your phone, then roll your phone to the left slowly and at some point the colors will change abruptly
as you can see i'm displaying the alpha,beta and gamma values untouched here :
$("#yaw")[0].textContent = "yaw :" + event.alpha;
$("#pitch")[0].textContent = "pitch :" + event.beta;
$("#roll")[0].textContent = "roll :" + event.gamma;
why is that? is there a way to workaround this?

Related

Number slider with different min max

I am trying to make an app where user slides the slider to select a compass direction, but we all know that sliders usually starts at 0 (left) and ends at N (right).
I am trying to replicate this:
Bottomline, I want the slider to start at 270(West) and the center should be 360 and 0(0 degree North) and next should be 0-90(North to East) then 90-180(East to South) and then 180-269(South to West)
Sorry for bad english, not native speaker. If my explanation is not understandable, please refer to the image.
If you start the slider on 270 degrees, then the center would be 90 degrees, because your compass is not centered on the slider range.
You can use negative values to determine the applicable direction with some math:
$('#slider-degrees').change(() => {
let selection = parseInt($('#slider-degrees').val());
let degrees = (selection < 0) ? (360 + selection) : selection;
$('#label-degrees').html(degrees);
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input id="slider-degrees" type="range" min="-90" max="269" value="-90">
<span id="label-degrees"></span>

Collision detection on a static element with dynamically generated skewed and rotated elements on a 2D plane

I am developing a wheel spinner (think Wheel of Fortune) with a static selector.
The circle segments are generated by having a square element which is then skewed by X degrees depending on the amount of segments. Another square element with a completely rounded left and top side. The overlap is then displayed to make the segment.
Once the wheel is spun, I need the clicker to detect which segment is selected.
The question is, how do I determine the co-ordinates of the segment to determine if the clicker is inside a segment.
Edit to add code segment:
Segment Generation
<div className="Segment-outer" style={{transform: "skewX(" + this.props.skewDegrees
+ "deg)"}}>
<div className="Segment-inner" style={{transform: "skewX(-"
+ this.props.skewDegrees + "deg)"}}>
</div>
</div>
Segments are held in the following div which is then rotated as shown.
<div className="Spinwheel-holder" style={{transform: "translate(-50%, -50%)
rotate(" + this.state.rotateDegrees + "deg)"}}>
Output (after Skewing and CSS) is this for five segments. Each segment gets thinner as more are added:
Known Variables:
Top, Left, Right, Bottom, x, y, height, width
Further Edit:
At the moment, I am using this for the collision detection, which works but is not entirely accurate.
collision = !(
((segmentRect.y + segmentRect.height) < (this.state.clickerLocation.y)) ||
(segmentRect.y > (this.state.clickerLocation.y + this.state.clickerLocation.height)) ||
((segmentRect.x + segmentRect.width) < this.state.clickerLocation.x) ||
(segmentRect.x > (this.state.clickerLocation.x + this.state.clickerLocation.width))
)

How to normalize the compass input?

I want to rotate the compass image according to the degrees I receive. The input degrees are between 0 and 359 so when I rotate -1 degree from 0 , the image rotates one complete round and sets on 359:
function setCompass(degrees){
$("#compass").stop().transition({rotate: -1*degrees +'deg'});
}
I tried to solve the problem by going back to -1 instead of 359 so I changed the code to the following:
function setCompass(degrees){
if (degrees>180){degrees=degrees-360}
$("#compass").stop().transition({rotate: -1*degrees +'deg'});
}
It solved the lag on 0 and 360 but the problem was shifted to 180. Now when I rotate the device from 180 to 181, it rotates a complete negative round to go back to -179 ! Please suggest me how to modify the calculations so I get smooth changes on every degree?
You could use some modulo formula to find out whether to turn clockwise or anti-clockwise. Persist the current angle with jQuery's data method (so you could have more than one such compass if you wanted to), and allow the angle that you pass as CSS value to be outside the 0-359 range.
Here is how it could work:
function setCompass(degrees){
var curr = $("#compass").data("rotation") || 0;
var next = curr + ((degrees - curr)%360 + 180*3) % 360 - 180;
$("#compass").data("rotation", next).stop().transition({rotate: -next + 'deg'});
}
// Demo with randomly generated angles between 0 and 359
setInterval(function() {
setCompass(Math.floor(Math.random()*360));
}, 1000);
<img id="compass" src="https://i.stack.imgur.com/zdHVn.png" width="100px" height="100px">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.transit/0.9.12/jquery.transit.min.js"></script>

Smooth DeviceOrientation Values

I'm trying to shift an image around based on the device orientation. But the values are very jumpy at rest, going between -1 to +2 with no movement, and I need a way to smooth it out a bit.
Is there an easy way to make this less jittery by averaging it out or something?
init();
var count = 0;
function init() {
if (window.DeviceOrientationEvent) {
window.addEventListener('deviceorientation', function(eventData) {
// gamma is the left-to-right tilt in degrees, where right is positive
var tiltLR = eventData.gamma;
// beta is the front-to-back tilt in degrees, where front is positive
var tiltFB = eventData.beta;
// alpha is the compass direction the device is facing in degrees
var dir = eventData.alpha
// call our orientation event handler
deviceOrientationHandler(tiltLR, tiltFB, dir);
}, false);
}
}
function deviceOrientationHandler(tiltLR, tiltFB, dir) {
var logo = document.getElementById("imgLogo");
logo.style.webkitTransform = "rotate("+ tiltLR +"deg) rotate3d(1,0,0, "+ (tiltFB*-1)+"deg)";
logo.style.MozTransform = "rotate("+ tiltLR +"deg)";
logo.style.transform = "rotate("+ tiltLR +"deg) rotate3d(1,0,0, "+ (tiltFB*-1)+"deg)";
}
http://codepen.io/picard102/pen/zvOVLx
Use CSS transitions to smooth out setting CSS values.
You can try adding transition: all 0.5s;-webkit-transition: all 0.5s; to your logo. This will cause the browser to smoothly transition from one transform state to the next.
You might need to experiment a bit with this setting; and you may have to implement your own smoothing instead (in JavaScript, using JavaScript-based animation) if you're not happy with the results of CSS transition.

Javascript : accurate CSS TranslateX ( position ) taking Transform Scale into account

I'm scaling a div.parent by n% using transform : scale( 0.25 ). The width of div.parent is quite large and exceeds the viewport bounds. This container div has n children, each with a relative offset position, which I'm getting via jQuery like ( approximation )
parent = $ '.parent'
child = $ '.child'
posLeft = child.position().left
I'm then moving the div.parent container using the value posLeft.
parent.css
transform : "translate3d( #{posLeft}px, 0, 0 )"
I would like to expand the function that handles the above animation by allowing it to continue to move div.parent accurately ( as related to the child items posLeft ) when it's scaled down. Here's an image to help illuminate the problem.
The solution turned out to be really simple — after eliminating a few bugs in my code. For anyone else who is interested in doing something similar, I'll post an approximation of the code below ( which uses TweenMax to handle the transitions )
_state =
scale : 1
state: ( state, value )->
if value is undefined
return _state[state]
else
_state[state] = value
calculateDistance( distance, scale )->
newDistance = distance * scale
return newDistance
scaleDown = ( amount )->
if amount > 1 then amount = 1
props =
x : 0
scale : amount
transformOrigin : 'center left'
onComplete : Done
TweenMax.to container, 0.4, props
Done =->
num = this.vars.css.scale
state( 'scale', num )
and how to use calculateDistance()
location = calculateDistance( move.destination.attr( 'data-location' ), state('scale' ) )
This enables me to use 1 method for both the scaled and full versions of any transitions.

Categories