I have a 360 degrees rotating wheel on my player page which acts as a volume button eventually.
I need to limit its functionality to 270 degrees and not 360 (from 7 O'clock to 5 O'clock) so it can have the effect of min to max.
How can i achieve this using the code attached?
The Player Page
$('#metal .indicator-cw').bind('touchmove', function(event){
updateMetal();
});
$("#metal .indicator-cw").mousemove(updateMetal);
function updateMetal(){
var number = $("#metal .result-cw").text();
var Degrees = parseInt(number);
var vol = ((Degrees + 150) % 360) * (1/270);
$musicPlayer.jPlayer("volume", vol);
$("#rotateit").css({'transform':'rotate(' + (Degrees) + 'deg)', '-webkit-transform':'rotate(' + (Degrees) + 'deg)', '-o-transform':'rotate(' + (Degrees) + 'deg)', '-moz-transform':'rotate(' + (Degrees) + 'deg)', '-ms-transform':'rotate(' + (Degrees) + 'deg)' });
if (Degrees > 120 || Degrees < 210) return;
}
//js code for the metal style wheel - above
Add this to stop updating the volume wheel
if (Degrees > 150 && Degrees < 210) return;
You'll also need to calculate the volume a bit differently
//This shifts the degrees from 210-120 to be 0-270 and then scales it to 0-1
var vol = ((Degrees + 150) % 360) * (1/300);
Related
I'm working on a wheel of fortune project. Each time someone press "spin" button, we get the prize from an api and calculate the angle based on our target gift and then rotate. In some cases, on iphone, after rotation the result doesn't match our target gift. Therefore I'm looking for a way to double check the result with target and keep rotating if they doesn't match. here is my rotation Javascrip functions:
function startRotation(target){
let giftIndex = parseInt(target.attr('id'))
angle = 360 - ((giftIndex - 1) * (360 / wheelItems.lenght)) - ((360 / wheelItems.lenght) / 3)
angle = angle === 360 ? 0 : angle
rotate(target)}
function rotate(target) {
randomNum = angle + (1800 * ri);
ri++
$(".mainCircle").css('transform', `translate(-50%, -50%) rotate(${randomNum}deg)`)
setTimeout(() => {
winPrize(target)
}, 7500)}
and here is where I add gifts to the wheel:
function createCircle(wheelItems){
let colors = ['#16A085', '#2989B9', '#8E44AD', '#F39C12', '#D35400', '#C0392B', 'cyan', 'brown', 'gray', 'pink', 'maroon', 'gold']
let count = wheelItems.lenght
for (let i = 0; i < count; i++) {
let img = document.createElement('img')
let text = document.createElement('span')
text.innerHTML = wheelItems[i].title
img.src = '/wheel/'+wheelItems[i].title;
img.style.transform = 'skewY('+ Math.abs(90 - (360 / count)) +'deg) rotate('+ 360 / count / 2 + 'deg)'
img.style.width = (40 - ((count - 4) * 3.125)) + '%'
img.style.left = (34 - ((count - 4) * 1.75)) + '%'
img.style.paddingTop = (43 + ((count - 4) * 3.25)) + '%'
text.style.transform = 'skewY('+ Math.abs(90 - (360 / count)) +'deg) rotate('+ 360 / count / 2 + 'deg)'
text.style.width = (50 - ((count - 4) * 3.125)) + '%'
text.style.left = (25 - ((count - 4) * 1.75)) + '%'
text.style.paddingTop = (75 + ((count - 4) * 3.25)) + '%'
$('<li>')
.css({'transform': 'rotate(' + i * (360 / count) + 'deg) skewY(-' + Math.abs(90 - (360 / count)) + 'deg)', 'background' : colors[i]})
.appendTo('ul.mainCircle')
.addClass('item' + i)
.append(img)
.append(text)
}}
I already tried to check the overlap between pin element and the target gift element (<li>) but apparently the <li> elements overlap each other so the result is not always accurate. I also tried to find a way to calculate the angle difference of the wheel after rotation, but I couldn't find one that does not use the css transform rotate value.
I would really appreciate it if you can help me find a way to make sure this problem doesn't happen again.
thanks
So, I've built a quick function to change hue values of a target element in JavaScript, and it works mostly fine now, but I do have some more questions that go beyond the initial post's scope. So I'll open a new question and post them here.
Here's the code:
document.getElementById('left').style.filter = "hue-rotate(" + 20 + "deg)";
document.getElementById('right').style.filter = "hue-rotate(" + 20 + "deg)";
document.querySelectorAll('div').forEach(occurence => {
occurence.addEventListener('click', (e) => {
const filter = e.target.style.filter;
var deg = parseInt(filter.replace(/[^0-9.]/g, ""));
deg += 40;
e.target.style.filter = "hue-rotate(" + deg + "deg)";
if (deg >= 360) {deg -= 360}
console.log(e.target.id + " is " + deg + "deg");
});
});
My main question (1) is that I've coded an if statement to log the current hue value within 360º (the hue-rotate works anyway with values over +360º, but I find it to be clearer this way). However, while the check works perfectly the first time around, it stops working after the function loops once through the 360º (on subsequent loops, it goes beyond 360º).
For clarification, the statement has been positioned after the degree value is already set (and animated) so as to sidestep the quick loop animation that happens when it goes from, say, 340 to 20º (instead of going there directly, it seems to loop back through the whole hue wheel).
Also, (2) the initial hue-rotate states are defined (at the top) within the script because the function does not work otherwise, although both DIVs do have defined CSS values.
That's it! Thanks in advance!
Since the degree value on the element is always set before limiting the degrees to 360, the 2nd time it loops subtracting 360 wont be enough.
style logged value
0 0
360 (-360) 0
720 (-360) 360
etc
To limit the logged value between [0, 360], use the % operator instead
document.querySelectorAll('div').forEach(occurence => {
occurence.addEventListener('click', (e) => {
const filter = e.target.style.filter;
var deg = parseInt(filter.replace(/[^0-9.]/g, ""));
deg += 40;
e.target.style.filter = "hue-rotate(" + deg + "deg)";
deg %= 360; // deg = deg % 360
console.log(e.target.id + " is " + deg + "deg");
});
});
For (2):
To get the style of the element from css, use getComputedStyle
occurence.addEventListener('click', (e) => {
const filter = getComputedStyle(e.target).filter;
...
});
e.target.style.filter = "hue-rotate(" + deg + "deg)";
above line should be below if condition if (deg >= 360) {deg -= 360}
document.getElementById('left').style.filter = "hue-rotate(" + 20 + "deg)";
document.getElementById('right').style.filter = "hue-rotate(" + 20 + "deg)";
document.querySelectorAll('div').forEach(occurence => {
occurence.addEventListener('click', (e) => {
const filter = e.target.style.filter;
console.log(filter);
let deg = parseInt(filter.replace(/[^0-9.]/g, ""));
deg += 40;
if (deg >= 360) {
deg -= 360
}
e.target.style.filter = "hue-rotate(" + deg + "deg)";
console.log(e.target.id + " is " + deg + "deg");
});
});
<div id="left">left</div>
<div id="right">right</div>
I am currently writing a tracking app that is able to get your currently facing angle and the angle to a destination and point an arrow in the direction you need to travel. (As the crow flies)
I am having trouble taking these 2 angles and making them work together so that the arrow points in the correct direction.
My knowledge of Mathematics is extremely limited so any help would be appreciated.
function deviceOrientationListener(event) {
facing = Math.round(event.alpha);
deg = bearing(lat, lng, getUrlVars()["lat"], getUrlVars()["long"]);
finaldeg = facing - deg;
c.innerHTML = '<img style="-ms-transform: rotate(' + finaldeg + 'deg);-webkit-transform: rotate(' + finaldeg + 'deg);transform: rotate(' + finaldeg + 'deg);" src="images/arrow.png" />';
}
The finaldeg is what i am having trouble with working out.
I did like this with Ionic and the plugin cordova-plugin-device-orientation
to_turn is the variable in which I record the computed angle
degreeStyle is the style applied to the arrow shown on end-user's
screen
last_lat/last_lng is the current position of the user
target_lat/target_lng is the destination
`
this.destinationBearing = this.bearing(
this.last_lat,
this.last_lng,
this.target_lat,
this.target_lng);
this.compass = this.deviceOrientation.watchHeading().subscribe(
(data: DeviceOrientationCompassHeading) => {
this.currentHeading = data.trueHeading;
if (this.destinationBearing > this.currentHeading) {
this.to_turn = this.destinationBearing - this.currentHeading;
} else {
this.to_turn = 360 - (this.currentHeading - this.destinationBearing);
}
this.degreeStyle = 'rotate(' + this.to_turn + 'deg)';
}
);
bearing(startLat, startLng, destLat, destLng){
startLat = this.toRadians(startLat);
startLng = this.toRadians(startLng);
destLat = this.toRadians(destLat);
destLng = this.toRadians(destLng);
let y = Math.sin(destLng - startLng) * Math.cos(destLat);
let x = Math.cos(startLat) * Math.sin(destLat) -
Math.sin(startLat) * Math.cos(destLat) * Math.cos(destLng - startLng);
let brng = Math.atan2(y, x);
brng = this.toDegrees(brng);
return (brng + 360) % 360;
}
toRadians(degrees) {
return degrees * Math.PI / 180;
};
toDegrees(radians) {
return radians * 180 / Math.PI;
}
I have a image which always points in the direction of the mouse.
At some point the angle goes from 180deg to -180deg, how do I get the image to take the short angle instead of doing full circle?
// Find ship angle (Math.atan2(y2 - y1, x2 - x1) * 180 / Math.PI;).
var mouseAngle = getAngle(FIREFLY.CENTER.X, FIREFLY.CENTER.Y, currentMousePos[0], currentMousePos[1]);
var turnDegrees = mouseAngle - FIREFLY.ANGLE;
var maxDegrees = 5;
console.log(mouseAngle + " " + FIREFLY.ANGLE);
if (turnDegrees > -5 && turnDegrees < 5) {
// Do nothing.
} else if (turnDegrees < 0) {
FIREFLY.ANGLE -= 5;
} else {
FIREFLY.ANGLE += 5;
}
// Set ship direction.
FIREFLY.style.transform = 'rotate(' + (FIREFLY.ANGLE + 90) + 'deg)';
Fiddle
Angles are the same modulo 360 degrees, so to avoid big rotations like 359° you choose -1° and to avoid -359° you choose 1°
You could do something like
var turnDegrees = (mouseAngle - FIREFLY.ANGLE) ;
if(-540<turnDegrees&&turnDegrees <=-180) turnDegrees+=360;
else if(180<turnDegrees&&turnDegrees<=540) turnDegrees-=360;
but it turns out FIREFLY.ANGLE can take large values, so to avoid plenty of other if clauses, a general formula is better. Here is one using modulo
var turnDegrees = mod(mouseAngle - FIREFLY.ANGLE +180, 360) -180;
function mod(x, value){ // Euclidean modulo
return x>=0 ? x%value : value+ x%value;
}
plot test
fiddle updated: http://jsfiddle.net/crl/2rz296tf/31
You could turn off CSS transforms, and do the interpolation yourself.
Try calculating the difference between the angles when the mouse moves and add that to a total angle, that way the angle wont be bound to (-180, 180)
This is all about mathematics. It's a shame that I'v forgotten those I learned in scool.
OK, I'm trying to get the image dimension after rotation (using canvas) with a certain angle in Javascript.
Since I don't have any tools other than MSPaint here, I'll re-use your image:
Say your original rectangle's size is R(ectangle)W(idth) * RH(eight),
in this case RW=200, RH=80;
After rotating a certain angle A, counterclockwise,
where 0deg <= A <= 90deg in degrees (or 0 <= A <= Math.PI/2 in radians),
in this case A=30deg or A=Math.PI/6,
In the new "outer" rectangle, each side is divided by two parts (for the convenience of describing; corresponding to the image).
On the left side, let's say the upper (purple) part is called N(ew)H(eight)U(p), and the lower (red) part is called NHL(ow);
Same rule on the bottom side, we have NW(idth)L(eft) (blue) and NWR(ight) (orange).
So the size (area) of new rectangle would be (NHU + NHL) * (NWL + NWR)
According to the definition of sin and cos:
NWL = RW * Math.cos(A); //where A is in radians
NHL = RW * Math.sin(A);
NHU = RH * Math.cos(A);
NWR = RH * Math.sin(A);
(if you're using A in degrees, replace A to Math.PI*A/180).
So the new "outer" width would be NWL + NWR, and new "outer" height would be NHU + NHL, and now you can calculate everything.
Here's a drop-in function that implements #Passerby's solution + a couple other safeguards:
function imageSizeAfterRotation(size, degrees) {
degrees = degrees % 180;
if (degrees < 0) {
degrees = 180 + degrees;
}
if (degrees >= 90) {
size = [ size[1], size[0] ];
degrees = degrees - 90;
}
if (degrees === 0) {
return size;
}
const radians = degrees * Math.PI / 180;
const width = (size[0] * Math.cos(radians)) + (size[1] * Math.sin(radians));
const height = (size[0] * Math.sin(radians)) + (size[1] * Math.cos(radians));
return [ width, height ];
}
// USAGE:
imageSizeAfterRotation([ 200, 80 ], 30) // [ 213.20508075688775, 169.28203230275508 ]