I have a div with some text which I would like to rotate 360 degrees for x amount of times but I would also like to modify the text every 180 degrees. how can I achieve this in Jquery or Javascript?
So far, I am stuck on this as I don't know of a way to monitor the rotation.
$('.pie_chart').css({'transform' : 'rotate(2000deg)'});
I looked at this post thinking that I could utilize the solution but it didn't work for me, or I might be just using it wrong: CSS rotation cross browser with jquery.animate()
This is very imprecise but it gets the idea across and should be enough to get you on the right track
function AnimateRotate(angle) {
// caching the object for performance reasons
var $elem = $('#square');
var texts = ['text', 'another thing', 'one more thing', 'finally']
var maxRotations = Math.floor(angle / 180);
var rotations = 0;
var lastRotation = 0;
// we use a pseudo object for the animation
// (starts from `0` to `angle`), you can name it as you want
$({deg: 0}).animate({deg: angle}, {
duration: 2000,
step: function(now) {
// in the step-callback (that is fired each step of the animation),
// you can use the `now` paramter which contains the current
// animation-position (`0` up to `angle`)
$elem.css({
transform: 'rotate(' + now + 'deg)'
});
// Here we must allow ourselves some margin for error
// We are making 4 rotations in 2 seconds, so in theory
// The box will be at the 180 degrees every half a second
// but in actuality it never is at exactly 180 degree except at the star and end
// Trial and error has shown that +6 degrees is more or less accurate,
// you could do some math to get a better precision
// We don't want to update the text at 0 degrees
if(now % 180 <= 6 && rotations > 0) {
// Shift off the first text and use that for the new text
$("#text").html(texts.shift());
rotations++;
} else if(now % 180 >= 177) {
$("#text").html(texts.shift());
rotations++;
}
}
})
};
AnimateRotate(720);
Related
I am trying to make a simple game in which you can rotate each element by 90 degrees on each click with some transition like 500ms. When it passes from 270 to 0 it goes in opposite direction. It is possible to achieve this by keeping incrementing the value to +Infinity, but what if I want to keep the angle normalized, from 0 to 359? How do I tell browser to use closest path to rotate an object basically going from 270 to 360 and not from 270 to 0. What if someday I exceed the integer limit and it brakes? Is it even possible? Here is an example of how it works right now.
const images = document.querySelectorAll("img")
for(const image of images) {
let rotation = 0;
image.style.transition = 'transform 500ms';
image.addEventListener('click', function() {
rotation = (rotation + 90) % 360
image.style.transform = `rotate(${rotation}deg)`
})
}
No need to mod the angle by 360. Integer limit in JS is about 9007199254740991. So if you rotate 100 times per second, it's still would last 100,000 years or so.
const images = document.querySelectorAll("img")
for(const image of images) {
let rotation = 0;
image.style.transition = 'transform 500ms';
image.addEventListener('click', function() {
rotation = (rotation + 90)
image.style.transform = `rotate(${rotation}deg)`
})
}
<img src="https://picsum.photos/200">
Using three.js, I'm creating a game with cars that move in a specific direction, depending on their y-rotation. An example would be 90 degrees. I use object.translateZ() to move them forward but I've run into a problem.
I'm using physijs to simulate the cars. Cars that run into each other may change their y-rotation (because of the crash) and I want to find a way for the cars to slowly change their rotation back to the original rotation like they are turning to get back on the road. Without this my city is very chaotic.
Here's the code that I'm already using (this is just part of it):
var targetRotation = 90
var rotation = car.mesh.rotation.y * 180 / Math.PI //to convert to degrees
I want to find a way to slowly change the car's rotation so it's the same as the target rotation.
Any help is appreciated! (but some sort of function would be perfect)
I've done stuff like this before in other systems (2D, not Three.js), and essentially all you want to do is gradually increment the angle until you reach something close enough to the target angle. Usually this means the float is less than the turning speed you're incrementing by (so you don't "overshoot" the value).
The amount of the increment depends on how quickly you want them to turn.
You also want to check if it's better to increase the angle or decrease (do you turn clockwise or counterclockwise) depending on if you're closer to 360 or 0. This prevents the car from turning the "long way" around. You can find this out by seeing if the difference is greater/less than 180.
We can use the modulus operator to get the "real" angle between -360/360.
var currentAngle = car.mesh.rotation.y * 180 / Math.PI; //car's angle in degrees
var targetAngle = 90; //preferred angle *this time* ;)
var turningSpeed = 1; //one degree per update (wayyy to high for real stuff, usually)
currentAngle = currentAngle % 360; //get the 0-360 remainder
if ( Math.abs(targetAngle - currentAngle) >= turningSpeed) {
var addto = 0
if (targetAngle - currentAngle < 0) {
addto = 360
}
if ( targetAngle - currentAngle + addto <= 180 ) {
currentAngle += turningSpeed;
}
else {
currentAngle -= turningSpeed;
}
}
else { currentAngle = targetAngle; } //we're close enough to just set it
car.mesh.rotation.y = ( currentAngle * Math.PI ) / 180; // back to radians!
Im designing a clock, for the "hands" Im using a combination of JS and CSS to make an smooth animation, converting second, minutes and hours to its corresponding degree in the analog clock:
function clock() {
var t = moment(),
s = t.seconds() * 6,
a = t.minutes() * 6,
o = t.hours() % 12 / 12 * 360 + (a / 12);
$(".hour").css("transform", "rotate(" + o + "deg)");
$(".minute").css("transform", "rotate(" + a + "deg)");
$(".second").css("transform", "rotate(" + s + "deg)");
}
setInterval(clock, 1000);
The problem is, after getting to 360 degrees I don't want the variable to keep increasing forever, I just return to 0 and start again, but, CSS makes the hands turn anticlockwise making an undesired effect.
Example
I was thinking about removing the transition property using JS when im about to go from 360 to 0 and then put it in again, this may be a solution, but I wonder if there is a cleaner way.
It can't be done natively. A transition from 356 to 2 degrees will always go counter clockwise. If you don't mind the visible tick from 356 to 2 degrees, just remove the transition. But there's no reason to do that. Try to exploit the fact that rotate can take any sane value, also above 360 degrees. So instead of returning to 0, just let the clock continue to increase the value "endlessly" (the highest int value in js is 9007199254740991, so you'll have to refresh the browser after a few million years... :)).
You can keep track of rotations so far in a separate counter object outside the setInterval callback like this:
var counter = {
s: 0,
a: 0,
o: 0
};
var previous = null;
Then you want to store all values from the previous iteration somewhere, and compare the current values to the previous ones. If necessary, increase the appropriate counter by one.
if(previous){
if(s < previous.s){
counter.s += 1;
}
if(a < previous.a){
counter.a += 1;
}
if(o < previous.o){
counter.o += 1;
}
}
previous = {
s: s,
a: a,
o: o
};
Then just set the multiplied degree value in your inline css. This way you will still have access to the pure values of s etc in case you need those for something.
$(".second").css("transform", "rotate(" + (s + 360 * counter.s) + "deg)");
Working fiddle: https://jsfiddle.net/dannyjolie/tccroo1q/6/
I'm trying to create a wheel of fortune type animation using jquery but for some reason the code that i am using always displays the wrong number!
here is the jsfiddle: http://jsfiddle.net/wf49mqaa/2/
click on the WHITE AREA in the wheel to see the animation and you will see a wrong number will be shown!
at the moment I only have 4 columns and 4 segments in my jquery code but in the future i am will pull the amount of segments from a database and I need this to work correctly at all times and display the correct number.
I tried everything from changing the segment = Math.ceil(((percent/100) * 4)), to segment = Math.ceil(((percent/100) * 4) -1), and also segment = Math.ceil(((percent/100) * 5)),
and it still display wrong number!
could someone please advise on this?
Thanks
Part of the Code you use I found in a Non-working demo from sitepoint., digging a bit deeper there are two different errors/ problems to solve the fortune-wheel behavior:
First: How to define the degree:
// existing code fragment (wrong)
var deg = 1500 + Math.round(Math.random() * 1500);
This would cause the wheel to stop at a totally random position, but that is not what you need. The wheel should always stop at the marker position, it should just turn around by a random number of segments.
// supposing you have a wheel with 4 segments (here the items array):
var deg = 0, /* basic degree */
spinbase = 1080, /* basic spinning of the wheel, here 3 times full turn */
items = [1,2,3,4];
// your spinning function...
spin: function () {
var min = 1,
max = 10,
rand = Math.floor(min + Math.random()*(max+1-min));
[...]
// like this you'll stop at the same position,
// but the wheel moved by a random number of segments
deg = deg + ( Math.round( 360 / items.length ) * rand) + spinbase;
[...]
}
Second: How to get the correct segment:
In short:
// where deg is the current degree, and items the array from above.
var segmentIndex = Math.ceil(
(deg - (360 * parseInt(deg / 360))) /
Math.round(360/items.length)
);
And when filling the algorithm..
// e.g. deg is (degree of each segment) * random (here 5) + 1080
// deg = 1530 (1080 + ( (360/4) * 5) )
// (1530 - (360 * parseInt( 1530 / 360))) / Math.round(360 / 4);
// (1530 - (360 * 4)) / 90;
// 90 / 90 = 1
// since we have 4 segments only and the random number is higher,
// the wheel did another full turn + 1 (from the starting number)
// so we get items[ 1 ] = (result: 2);
// due to the ceil/floor/round methods in calculation it can happen
// that you reach the extrem values segments.length or less than 0,
// to fix this:
var segmentIndex = Math.ceil(
(deg - (360 * parseInt(deg / 360))) /
Math.round(360/items.length)
);
if(target < 0 ) { target = segment.length - 1; }
if(target === segments.length ) { target = 0; }
alert( 'Winning: ' + items[target] );
Putting this together you'll get a working fortune-wheel. I allowed myself to create a new variant of the fortune wheel, which is able to handle different amounts of segments to make it easier to prove the algorithm.
I'm trying to build a game somewhat like Wheel of Fortune, actually it's done but there seems to a weird issue I can't figure out.
Here's the wheel itself, as you can see the values are spaced evenly, each having a 15 ° slice.
To spin the wheel I generate a random number which will be the amount of rotation in degrees, I animate the wheel and everything is fine but when the rotation stops I have to get the value from the wheel which stops at the top-center position so I though this would solve it:
wheelValues = [
1000, 3250, 1800, 1000, 1200, 3750, 5000, 1000, 3000, 1600, 1000, 3500,
1000, 2000, 1000, 2750, 1000, 4000, -1, 1000, 2500, 1400, 1000, 2250
];
if (toAngle > 360)
{
toAngle = toAngle - (Math.floor(toAngle / 360) * 360);
}
arrIndex = Math.floor(toAngle / 15) + 1;
result = wheelValues[arrIndex];
where toAngle is the random spin I generate which can be between 370 and 1440.
This method works in about 8/9 times out of 10 and I can actually get the correct value the wheel stops at but I can't really understand why sometimes the value is off (and sometimes really off, not even near the correct value).
You're adding 1 to your array index for some reason.
array indexes start from 0.
Two problems I can see;
Firstly, this line:
if (toAngle > 360)
If toAngle == 360, I believe this will produce an error, as you will skip the 'modulus' section and toAngle will finally be 24 (larger than your dataset)
Second:
arrIndex = Math.floor(toAngle / 15) + 1;
No need to +1 this, as you will never get your first value, and on occasion you will exceed the array bounds.
Also, as to why you get odd values, have you tried to write some simple code to debug your assumptions? Write a loop, that iterates from 370 to 1440 (your stated input boundaries) and see what your calculation comes up with for each value. Print it to a file, or screen and you can quickly scan to see where the issues might be.
BTW, it's probably best if you make your random number an even multiple of 15 degrees in the first place, then you don't need all that rounding and flooring, e.g.
function randDeg() {
var epoch = 360; // minimum value
var max = 1440; // maximum value to return
var step = 15; // even multiple to return
var t = Math.random() * (max - epoch) | 0;
t -= t % 15;
return t + epoch;
}
Will return a number n where epoch <= n <= max and n%15 = 0.