JS mouseenter -> acceleration value increases; mouseleave -> deceleration value decreases - javascript

I'm trying to achieve a mouseover effect.
When the usere hovers the element, it start spinning slowly and over time the speed will increase. When the user leaves the element, the spinning will decrease and eventually stop.
My approach would be to set a loop, that multiplies the given value 1.
That works.
Now when the user leaves, I somehow have to get the value and divide it by some number. Thats not working :-(
Here my code, I use jQuery
https://codepen.io/hhqh/pen/gOOVQPV?editors=1011
var deg = 1;
var img;
var keepGoing = true;
var keepStopping = true;
function myLoop(img) {
console.log(img);
deg *= 1.1;
console.log(deg);
img.css('transform', 'rotate(' + deg + 'deg)');
if(keepGoing) {
setTimeout(myLoop, 30, img);
}
}
function myStop(img) {
console.log(img);
deg /= 1.1;
console.log(deg);
img.css('transform', 'rotate(' + deg + 'deg)');
if(keepStopping) {
setTimeout(myStop, 30, img);
}
}
$('#spinner').on('mouseenter', function(){
var img = $(this).find('img');
startLoop(img);
}).on('mouseleave', function(){
var img = $(this).find('img');
stopLoop(img);
});
function startLoop(img) {
keepGoing = true;
keepStopping = false;
myLoop(img);
}
function stopLoop(img) {
keepGoing = false;
keepStopping = true;
myStop(img);
}
As you see, it just jumps back. I want to slowly decrease the value, but because it rotates and just adds up the number, decreasing actually rotates it backwards.
Maybe I have to get the current rotation, and make a new calculus that is some how adding a decreasing number. No idea how..

You have to stop myStop function in a specific condition, when rotation degrees is at starting position.
function myStop(img) {
console.log(img);
deg /= 1.1;
console.log(deg);
if (deg.toFixed(1) < 0.1) {
return;
}
img.css('transform', 'rotate(' + deg + 'deg)');
if(keepStopping) {
setTimeout(myStop, 30, img);
}
}

Related

Plain JavaScript rotate

I would like to rotate an object exactly as the fiddle: http://jsfiddle.net/nqC6T/
however, I do not have the JQuery library available in my project.
var angle = 0;
$(document).ready(function () {
$('#rotate').click(function () {
angle += 90;
$('#div1').animate({ rotate: angle }, {
step: function (now, fx) {
$(this).css('-webkit-transform', 'rotate(' + now + 'deg)');
$(this).css('-moz-transform', 'rotate(' + now + 'deg)');
$(this).css('transform', 'rotate(' + now + 'deg)');
},
duration: 3000
}, 'linear');
});
});
Would this be possible in plain JavaScript?
Thanks!
A plain Javascript based solution is as follows:
var obj = document.getElementById("div1");
var total = 100;
var current = 0;
setInterval(function(){
if (current < total) {
current += 1;
obj.style.transform = 'rotate('+current+'deg)';
}
}, 1);
This is just an example. You can definitely improve this code further. As mentioned by Mohammad, you can also use CSS3 based animations.
You could add a 'rate of speed' and 'initial rotate position' to the element you
wish to rotate, by simply using a closure to automatically return a given rotational increase/decrease rate:
var division=document.getElementById("rotdiv");
function rotElem(startpos,rate){
return function(mult){
return division.style="transform:rotate("+ startpos+ mult*rate++ +"deg)";};
}
var rotelem = rotElem(0,1);
var atspeedof = setInterval(rotelem.bind(null),1000,10);
rotElem(0,1) You define optional start position '0' of the element before starting rotate and the self-increasing 'unit' of change return by the closure.
setInterval(rotelem.bind(null),1000,10) You call setInterval to run the closure at each second AND passing the value '10' as the multiplier for the rate speed. Changing the rightmost argument after the setInterval time, increases or decreases rotation.
var division = document.getElementById("rotdiv");
function rotElem(startpos, rate) {
return function(mult) {
return division.style = "transform:rotate(" + startpos + mult * rate++ + "deg)";
};
}
var rotelem = rotElem(0, 1);
var atspeedof = setInterval(rotelem.bind(null), 500, 10);
#rotdiv {
position: relative;
margin: auto;
top: 50px;
width: 80px;
height: 80px;
background-color: gray;
}
<div id='rotdiv'>
</div>

JS - moving an image horizontally after a period of time

Everything was going smoothly until now. I want to have this hor() function reverse after 20 seconds. The original hor() function grabs an image offscreen and moves it horizontally from the left to the center of the page. I'd like to create a function that does the opposite after 20 seconds. The "after 20 seconds" part is giving me the most grief. If you could show me what a new function would look like or an 'else' addition to the current function that would be great. Thanks.
<script language="JavaScript" type="text/JavaScript">
var x = -500;
var y = 100;
function hor(val) {
if (x <= 500){
x = x + val;
document.getElementById("pos").style.left = x + "px";
setTimeout("hor(5)", 10);
}
}
</script>
<style type="text/css">
<!--
#pos {
position: absolute;
left: -500px;
top: 100px;
z-index: 0;
}
</style>
<body onLoad="setTimeout('hor(5)',5000)">
<div id="pos">
<img src="image.jpg">
</div>
Perhaps you could try changing the script to this:
// Define variables
var x = -500,
y = 100,
direction = 1;
// Function which moves "pos" element
function hor(val) {
// Move by specified value multiplied by direction
x += val * direction;
if(x > 500){
x = 500;
// Reverse direction
direction = -1;
} else if(x < -500){
x = -500;
// Reverse direction, once again
direction = 1;
}
// Move element
document.getElementById("pos").style.left = x + "px";
// Continue loop
setTimeout("hor("+val+")", 10);
}
This code will continue moving the pos element by the specified value until x greater than 500, at which point it will switch direction, then continue until x reaches -500, and so on.
EDIT:
This code will fix that issue with 20 seconds (I had thought that the 500 pixel thing computed to 20 seconds, lol).
// Define variables
var x = -500,
y = 100,
direction = 1;
firstCall = true;
timeElapsed = 0;
// Function which moves "pos" element
function hor(val) {
// Don't let the first call count!
if(!firstCall)timeElapsed += 10;
else firstCall = false;
if(timeElapsed >= 2000){
// Reverse direction
direction *= -1;
timeElapsed = 0;
}
// Move by specified value multiplied by direction
x += val * direction;
// Move element
document.getElementById("pos").style.left = x + "px";
// Continue loop
setTimeout("hor("+val+")", 10);
}
Try this. Here the img is moved horizontally and after sometime it is reverted back to its original position.
<script>
var x = -500;
var y = 100;
var op;
function hor(val) {
if (x <= 500 && x>=-500) {
x = x + val;
document.getElementById("pos").style.left = x + "px";
setTimeout(function(){hor(val);},10);
}
}
$(document).ready(function(){
setTimeout(function(){hor(5);},1000);
setInterval(function(){
setTimeout(function(){hor(-5);},1000);
},2000);
});
</script>
I have changed the timings for testing purpose only, you can change it back.

jQuery spin function - specify 20% spin upon image click?

I'm a jQuery newbie - but have managed to modify a roulette wheel script to spin a "pie" image for a homepage I'm working on.
It works great - but the client also want to add an arrow on either side that will advance the pie one section upon click - so clockwise for one arrow, counter-clockwise for another.
Is there a way to specify a partial spin?
Any guidance is much appreciated! I'm trying to meet a ridiculous deadline and am struggling with this.
Here's the page:
http://bluetabby.com/rr/index13.html
Here's the jQuery code so far - the functions I need to figure out are leftArrow and rightArrow:
$( document ).ready(function() {
window.WHEELOFFORTUNE = {
cache: {},
init: function () {
console.log('controller init...');
var _this = this;
this.cache.wheel = $('.wheel');
this.cache.wheelSpinBtn = $('.wheel');
this.cache.leftArrow = $('.leftarrow');
this.cache.rightArrow = $('.rightarrow');
//mapping is backwards as wheel spins clockwise //1=win
this.cache.wheelMapping = ['Mitzvahs','Galas','Florals','Props','Weddings'].reverse();
this.cache.wheelSpinBtn.on('load', function (e) {
e.preventDefault();
if (!$(this).hasClass('disabled')) _this.spin();
});
this.cache.rightArrow.on('click', function (e) {
e.preventDefault();
if (!$(this).hasClass('disabled')) _this.spin();
});
},
spin: function () {
console.log('spinning wheel');
var _this = this;
//disable spin button while in progress
this.cache.wheelSpinBtn.addClass('disabled');
/*
Wheel has 10 sections.
Each section is 360/10 = 36deg.
*/
var deg = 1000 + Math.round(Math.random() * 1000),
duration = 6000; //optimal 6 secs
_this.cache.wheelPos = deg;
//transition queuing
//ff bug with easeOutBack
this.cache.wheel.transition({
rotate: '0deg'
}, 0).delay(1000)
.transition({
rotate: deg + 'deg'
}, duration, 'easeOutCubic');
//move marker
_this.cache.wheelMarker.transition({
rotate: '-20deg'
}, 0, 'snap');
//just before wheel finish
setTimeout(function () {
//reset marker
_this.cache.wheelMarker.transition({
rotate: '0deg'
}, 300, 'easeOutQuad');
}, duration - 500);
//wheel finish
setTimeout(function () {
// did it win??!?!?!
var spin = _this.cache.wheelPos,
degrees = spin % 360,
percent = (degrees / 360) * 100,
segment = Math.ceil((percent / 5)), //divided by number of segments
win = _this.cache.wheelMapping[segment - 1]; //zero based array
console.log('spin = ' + spin);
console.log('degrees = ' + degrees);
console.log('percent = ' + percent);
console.log('segment = ' + segment);
console.log('win = ' + win);
//re-enable wheel spin
_this.cache.wheelSpinBtn.removeClass('disabled');
}, duration);
},
resetSpin: function () {
this.cache.wheel.transition({
rotate: '0deg'
}, 0);
this.cache.wheelPos = 0;
}
}
window.WHEELOFFORTUNE.init();
});//]]>
Thanks for any pointers!
I looked through your code and figured out you are using transit.js to do the spinning animations. Essentially, the object's css (transform "rotate") is being updated over a certain amount of time (like jQuery's animate).
You can extend your wheel of fortune object with spinright and spinleft functions (or whatever name you prefer), which you can bind to the keys/buttons that you'll create. Your code would look something like this:
WHEELOFFORTUNE.spinright = function() {
// get current degree of wheel and convert to integer
var degree = parseInt( this.cache.wheel.css('rotate'), 10 );
this.cache.wheel.transition( { "rotate": (degree + 73) + "deg" },1000 );
}
WHEELOFFORTUNE.spinleft = function() {
var degree = parseInt( this.cache.wheel.css('rotate'), 10 );
this.cache.wheel.transition( { "rotate": (degree - 73) + "deg" },1000 );
}
Then you can bind these functions to buttons or call the functions directly in console:
WHEELOFFORTUNE.spinright()
WHEELOFFORTUNE.spinleft()
Note: 73deg looks to be about the amount that 1 section is, but you'll probably have to play around with the numbers. You may also want to cache the degrees in your object as well. You probably will also need to figure out a way to center on each section per button press.
Cheers!

Javascript Circle slider degrees to time

I am looking at this slider http://jsfiddle.net/sCanr/1/.
(function () {
var $container = $('#container');
var $slider = $('#slider');
var sliderW2 = $slider.width()/2;
var sliderH2 = $slider.height()/2;
var radius = 200;
var deg = 0;
var elP = $('#container').offset();
var elPos = { x: elP.left, y: elP.top};
var X = 0, Y = 0;
var mdown = false;
$('#container')
.mousedown(function (e) { mdown = true; })
.mouseup(function (e) { mdown = false; })
.mousemove(function (e) {
if (mdown) {
var mPos = {x: e.clientX-elPos.x, y: e.clientY-elPos.y};
var atan = Math.atan2(mPos.x-radius, mPos.y-radius);
deg = -atan/(Math.PI/180) + 180; // final (0-360 positive) degrees from mouse position
X = Math.round(radius* Math.sin(deg*Math.PI/180));
Y = Math.round(radius* -Math.cos(deg*Math.PI/180));
$slider.css({ left: X+radius-sliderW2, top: Y+radius-sliderH2 });
// AND FINALLY apply exact degrees to ball rotation
$slider.css({ WebkitTransform: 'rotate(' + deg + 'deg)'});
$slider.css({ '-moz-transform': 'rotate(' + deg + 'deg)'});
//
// PRINT DEGREES
$('#test').html('angle deg= '+deg);
}
});
})();
What i want to do it turn this into a time line control for a html5 video. However, i am having some trouble with calculating the math behind this.
Try this:
http://jsfiddle.net/phdphil/Zv4K7/#base
It works by keeping global variables for the current position and last angle (you should change this setup to construct a specific dial with its own state). Each movement then calculates the delta (modulo 360, which requires a proper modulus function) and assumes that movements of < 180 degrees are forward movements, and > 180 degrees (remember -1 modulo 360 is 359) are negative movements. This then updates the cumulative total position:
var current = 0;
var lastAngle = 0;
// ... inside the handler
var delta = 0;
var dir = 0;
var rawDelta = mod(deg-lastAngle,360.0);
if(rawDelta < 180) {
dir = 1;
delta = rawDelta;
} else {
dir = -1;
delta = rawDelta-360.0;
}
current += delta;
lastAngle = deg;
$('#test').html('angle deg= '+current); // current instead of deg
Just for clarity, the dir variable holds the direction of this movement, which could be used to update a >> or << indicator onscreen.
The real modulus function, taken from this SO answer:
function mod(x,n) {
return ((x%n)+n)%n;
}

rotate object onclick

So i have the code that is supposed to add when clicked "+10" button 10degree rotation to object, when clicked "+30" button 30degree rotation to the object, the 90degree position to be max available. Now it ads only by one and i dont know how to make it to move as much degree as i want it to move.
http://jsfiddle.net/9Xghf/
var rotateObject = document.getElementById("object");
var objectRotation = 0;
var add10 = document.getElementById("add10");
var add30 = document.getElementById("add30");
add10.onclick = function(){
rotate(0, 10);
}
add30.onclick = function(){
rotate(0, 30);
}
function rotate(index, limit){
if(objectRotation < 90 && index <= limit){
index++;
objectRotation++;
rotateObject.style.transform="rotate(" + objectRotation + "deg)";
rotateObject.style.WebkitTransform="rotate(" + objectRotation + "deg)";
rotateObject.style.msTransform="rotate(" + objectRotation + "deg)";
setTimeout(rotate, 50);
}else{
// 90 degree is the max limit for this object
}
}
Replace the timer by this :
setTimeout(function(){
rotate(index,limit);
}, 50);
nb : this won't work for all browsers

Categories