Forcing If Condition Within Function to Run Every Time - javascript

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>

Related

CSS rotation does not work properly on ios

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

Angle of tracking compass arrow

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;
}

How to use variable parameters for rotation of a picture

What is wrong with my approach?
I would like to allow a user to enter a value of 0 to 180 degree to rotate a picture by this value.
If I use the code below it works perfect.
document.getElementById('myCanvas').setAttribute("style", "position:relative;height:1024px;width:100%; transform: rotate(45deg)" );
But, if I use variables like in the following code, no rotation is performed.
var deg = 45;
var rotation = "transform: rotate(" + deg + "deg)";
document.getElementById('myCanvas').setAttribute("style", "position:relative;height:1024px;width:100%; rotation" );
How can I manage my requirement?
Thank you in advance.
Looking at your code, I think your problem is because you have missed some concatenation. Try this:
var deg = 45;
var rotation = "transform: rotate(" + deg + "deg);"; // Note: Extra semicolon in string
var element = document.getElementById('myCanvas')
element.setAttribute("style", "position:relative;height:1024px;width:100%;" + rotation);
Going further
If you want degree to change based on user input, then I suggest adding an input element to the page, waiting for click (or change) events and then updating your picture's styles:
var number_input = document.querySelector("input[type=number]#rotation");
var element // = ...
var myExtraStyles // = ...
// Pass in extra styles, like you width and such as above.
function rotateElement(degrees, extraStyles) {
var rotation = "transform: rotate(" + deg + "deg);";
element.setAttribute("style", extraStyles + rotation);
}
number_input.addEventListener("click", function(){
rotateElement(element.value, myExtraStyles);
})

Gameshow JavaScript spinner can't find Value

I am trying to get results of the spinner. After 6 hours of debugging and all sorts of math attempts I can't seem to find out how to get the value of the spinner with each spin. What DIV does it land on?!
http://codepen.io/anon/pen/OMrOPe
Initially I thought the following algorithm would work.
total_rotations = Get Total Degrees in rotations (including what was done historically.
total_rotations / 360 = _total_rotations_of_a_circle
value_to_subtract = Take the absolute value of _total_rotations_of_a_circle * 360
left_over_value_in_Degree = total_rotations - value_to_subtract
left_over_value_in_Degree/60 = result.
This algorithm only works SOMETIMES. I just am not sure how to do this, any tips would help.
The aoY variable was presented by the original developer, but I don't know how to use that value to find the actual div its pointing to. What math do I need here?
$('#wheel .sec').each(function(){
var t = $(this);
var noY = 0;
var c = 0;
var n = 700;
var interval = setInterval(function () {
c++;
if (c === n) {
clearInterval(interval);
}
var aoY = t.offset().top;
$("#txt").html(aoY);
console.log(aoY);
/*23.7 is the minumum offset number that
each section can get, in a 30 angle degree.
So, if the offset reaches 23.7, then we know
that it has a 30 degree angle and therefore,
exactly aligned with the spin btn*/
if(aoY < 23.89){
console.log('<<<<<<<<');
$('#spin').addClass('spin');
setTimeout(function () {
$('#spin').removeClass('spin');
}, 100);
}
}, 10);
$('#inner-wheel').css({
'transform' : 'rotate(' + totalDegree + 'deg)'
});
noY = t.offset().top;
});
});
The formula RobG proposed is correct:
Math.ceil((( totalDegree + 30 ) % 360) / 60)
Something you also have to take into account is the fact that the offset changes for every consecutive plays. In order to deal with that, you can simply use this formula:
offset = extraDegree MOD 60
You can then replace the number 30 in the function by the offset variable:
Math.ceil((( totalDegree + offset ) % 360) / 60)
See this fiddle

How to rotate image when time changes?

I have recently made a countdown timer for a website like this! It's pretty much a combination of 2 scripts I found online.
The countdown counts down to February 1st and is pretty static. But the 'clockpicture' is supposed to rotate 6 degrees every second (please see the page source). But it turns out the clock picture will start counting/turning from the moment the page is loaded, so if you arrive there between two seconds the picture will we half a second off, compared to the countdown.
Is there any way I can 'connect' the turning of the picture to the changing of the countdown?
Any help is much appreciated!
EDIT
Based on discussion with OP, finally I found the solution. The problem was, how the browsers handle the rotations.
Ok, so, remove that anim gif, and do some animation there. Create a global variable, called var degrees = 0 at the top of your script. You need to incrase that degrees in every tick with 6. If it reach the 360, then reset it to 0.
For some reason, it not works on jsfiddle, but you can check it on my site. Live demo
Then in your tick function:
if (amount < 0) {
expired.push(idx);
}
// date is still good
else {
this.display(cnt, this.format(this.math(amount)));
if (degrees === 360) {
degrees = 0;
}
degrees += 6;
obj = document.getElementById('clock');
if (navigator.userAgent.match("Chrome")) {
obj.style.WebkitTransform = "rotate(" + degrees + "deg)";
} else if (navigator.userAgent.match("Firefox")) {
obj.style.MozTransform = "rotate(" + degrees + "deg)";
} else if (navigator.userAgent.match("MSIE")) {
obj.style.msTransform = "rotate(" + degrees + "deg)";
} else if (navigator.userAgent.match("Opera")) {
obj.style.OTransform = "rotate(" + degrees + "deg)";
} else {
obj.style.transform = "rotate(" + degrees + "deg)";
}
}

Categories

Resources