I want to add more degrees of rotation to #rad-spin every time someone clicks on #rad-btn
$(document).ready(function(){
$("#rad-btn").click(function(){
$("#rad-spin").css("transform", "rotate(90deg)");
});
});
Now it just goes one time to 90deg and if I click again it won't go further to 180deg (obviously). That's what I want.. Anyone knows how to do this?
By lexical scope, you can do this.By this, keep the outer value index.
$(document).ready(function(){
var index = 0
$("#rad-btn").click(function(){
index++
$("#rad-spin").css("transform", "rotate(" + 90 * index + "deg)");
});
});
By data- and $.data, you can save the info in the DOM.
$(document).ready(function(){
$("#rad-spin").data('index', 0)
$("#rad-btn").click(function(){
var index = $("#rad-spin").data('index')
$("#rad-spin").data('index', ++index)
$("#rad-spin").css("transform", "rotate(" + 90 * index + "deg)");
});
});
Just store the angle somewhere.
$(document).ready(function(){
var angle = 0;
$("#rad-btn").click(function(){
angle+=720;
$("#rad-spin").css("transform", "rotate("+angle+"deg)");
$(this).prop('disabled',true).delay(2000).queue(()=>$(this).prop('disabled',false).dequeue());
});
});
#rad-spin{
transition: transform 2s;
position: absolute;
top: 150px;
left: 50px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id='rad-btn'>v. rad</button>
<div id='rad-spin'>spin me round and round</div>
Related
Not sure why this is so hard to do in Javascript... Slightly frustrating LOL
Here's one of the ways I've tried to do it:
function rotateDavid() {
$("#david").css({
'transform' : 'rotate(90deg)'
});
setTimeout(rotateDavid, 10000);
};
rotateDavid();
It will do it once but doesn't repeat... I dunno...
The problem here is not how you are calling the function. This way is actually preferred over setInterval in some cases.
The issue you have is that setting the Css to 90degrees is not changing it over and over. You are setting it to the same degree value every time.
You need to update the angle on every iteration. So in this case you want to add 90 to it.
var rotation = 0;
function rotateDavid() {
rotation += 1
$("#david").css({
'transform' : 'rotate(' + (90 * rotation) + 'deg)'
});
setTimeout(rotateDavid, 1000);
};
rotateDavid();
div{
width:100px;
height: 100px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="david">Hi</div>
You can also use a mod operator to keep the number from getting huge.
'transform' : 'rotate(' + (90 * (rotation%4)) + 'deg)'
Your method, actually, is called every 10s. You can check it if you add a log to the console inside the method. However, you was setting the css property always to the same value, so you won't see any visual effect. A possible fix is shown on next example:
function rotateDavid(rot)
{
$("#david").css({
'transform': `rotate(${rot}deg)`
});
rot = rot + 90 >= 360 ? 0 : rot + 90;
setTimeout(() => rotateDavid(rot), 5000);
};
rotateDavid(0);
#david {
background: skyblue;
width: 50px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="david">David</div>
Even more, you can get similar functionality using setInterval():
function rotateDavid(rot)
{
$("#david").css({
'transform': `rotate(${rot}deg)`
});
};
var rot = 90;
setInterval(
() => {rotateDavid(rot); rot = rot + 90 >= 360 ? 0 : rot + 90;},
5000
);
#david {
background: skyblue;
width: 50px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="david">David</div>
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>
I have a simple animation of a wheel spinning. I am trying to control the speed of the spinning wheel using a slider (input range). I have managed to do this, but every time I change the animation the animation restarts (it jumps). Looking for a solution to create a smooth increase of the speed. As the user increases the value of the slider, the wheel rotates with an increased speed.
In the code below, #loading is the spinning wheel.
$(document).on('input', '#slider', function() {
var speed = $(this).val();
$('#speed').html(speed);
$("#loading").css("animation-duration", 50 / speed + "s");
});
#loading {
position: absolute;
width:100px; height:100px; background-color:black;
left: 0;
right: 0;
margin: auto;
transform-origin: 50% 50%;
animation: rotateRight infinite linear;
animation-duration: 0;
}
#keyframes rotateRight {
100% {
transform: rotate(360deg);
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<div id="loading"></div>
<input type="range" min="0" max="100" value="0" class="slider" id="slider">
<p>Speed: <span id="speed"></span></p>
Classic Question
(with jumping.. now yet )
Version with jQuery
var lasttime = 0, lastduration = 0, angle = 0;
$(document).on('input', '#slider', function(event) {
var speed = $(this).val();
$('#speed').html(speed);
var el = $("#loading");
var duration = (speed > 0) ? 50 / speed : 0;
var currenttime = event.originalEvent.timeStamp / 1000;
var difftime = currenttime - lasttime;
el.removeClass("enable_rotate").show();
if (!lastduration && duration)
el.css("transform", "");
else
angle += (difftime % lastduration) / lastduration;
if (duration){
el.css("animation-duration", duration + "s")
.css("animation-delay", -duration * angle + "s")
.addClass("enable_rotate");
}
else
el.css("transform", "rotate(" + 360 * angle + "deg)");
angle -= angle | 0; //use fractional part only
lasttime = currenttime;
lastduration = duration;
});
.anime_object {
width:100px; height:100px; background-color:black;
position: absolute;
left: 0;
right: 0;
margin: auto;
}
.enable_rotate {
animation: rotateRight infinite linear;
}
#keyframes rotateRight {
100% {
transform: rotate(360deg);
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<img id="loading" class="anime_object">
<input type="range" min="0" max="100" value="0" id="slider">
<p>Speed: <span id="speed"></span></p>
Work draft
save variable of currentanimation
http://www.w3.org/TR/css-animations-1/#interface-animationevent-attributes
SO
css-tricks.com
I'm not entirely sure that this will be possible without a different approach that doesn't use CSS animations. The issue is that the animation does not normalize whenever you change the speed. It is always animating from 0% of the animation to 100% of the animation. Every time you adjust the animation-duration, you're going to re-interpolate using the current position in the animation.
In other words, if you change from animation-duration: 25 to 50 at t=12, well the animation was halfway finished (180 degrees); now it's only a quarter finished (90 degrees). You can't control t though, that's the browser's. If you could, you would want to set t to remain where it was in the interpolation, in this example, t=25, so that you remain at the same percentage complete of the animation that you were, but you stretch the remaining time.
I modified your script a little to try and show what I'm describing a little better. It will increment the speed by 0.25 every second between speed 0 and 5. You can kind of see how the problem is that the browser controlled t is the issue.
You can rewrite this in order to control t yourself with JavaScript, but I think you'll have to drop the CSS animations.
To talk a little bit more to the point of this browser controlled t variable, take a look at this article on CSS-Tricks: Myth Busting: CSS Animations vs. JavaScript
Some browsers allow you to pause/resume a CSS keyframes animation, but
that's about it. You cannot seek to a particular spot in the
animation, nor can you smoothly reverse part-way through or alter the
time scale or add callbacks at certain spots or bind them to a rich
set of playback events. JavaScript provides great control, as seen in
the demo below.
That's your problem, you want to be able to change the duration of your animation, but then also seek to the correct spot in the animation.
$(function() {
var speed = parseInt($("#slider").val(), 10);
$("#speed").html(speed);
$("#loading").css("animation-duration", 50 / speed + "s");
var forward = true;
setInterval(function() {
speed += (forward ? 0.25 : -0.25);
if (speed >= 5) {
forward = false;
} else if (speed <= 0) {
forward = true;
}
$("#loading").css("animation-duration", 50 / speed + "s");
$("#slider").val(speed);
$("#speed").html(speed);
}, 1000);
});
#loading {
position: absolute;
left: 0;
right: 0;
margin: auto;
transform-origin: 50% 50%;
animation: rotateRight infinite linear;
animation-duration: 0;
}
#keyframes rotateRight {
100% {
transform: rotate(360deg);
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<img id="loading" src="//placehold.it/100">
<input type="range" min="0" max="100" value="0" step=".25" class="slider" id="slider" value="0">
<p>Speed: <span id="speed"></span></p>
TL;DR
No, you can't (according to my tests)
Firs of all, let's get rid of the animation declaration from your css and move it up to Javascript so the animation loop doesn't start (even if you can't visually see it running).
Have you noticed that even when you move your slider from the initial position the box appears to start from a random position? that's because the animation loop has actually been running.
Now, you can actually get the current transform value applied to your box at any given time by your animation, using getComputedStyle(loadingElement).getPropertyValue('transform'); this will return a matrix which doesn't give you much just like that but we can calculate the angle of the rotation from that matrix:
(using some maths explained here)
Math.round(Math.atan2(b, a) * (180/Math.PI));
Now that we have this value we have to normalize it to have only positive values for the angle, and then we can apply this angle as the base value for transform: rotate(Xdeg)
so far so good, you can see this working in the code snippet, however even when you do this, and increment/decrement the speed value, the animation loop is already running with a set time scale and you can't reset this loop.
My answer so far is so someone else with a deeper understanding of the animation loop can build from, and maybe come up with a working code.
If you are still reading this you might think, well just drop the animation with loadingElement.style.removeProperty('animation') and the assign it again, tried it doesn't work. And what about starting the animation again with a setInterval(...,0) so it runs in the next loop, won't work either.
$(document).on('input', '#slider', function() {
var speed = $(this).val();
var loadingElement = document.querySelector("#loading")
$('#speed').html(speed);
//get the current status of the animation applied to the element (this is a matrix)
var currentCss = getComputedStyle(loadingElement).getPropertyValue('transform');
if (currentCss !== 'none'){
//parse each value we need from the matrix (there is a total of 6)
var values = currentCss.split('(')[1];
values = values.split(')')[0];
values = values.split(',');
var a = values[0];
var b = values[1];
var c = values[2];
var d = values[3];
//here we make the actual calculation
var angle = Math.round(Math.atan2(b, a) * (180/Math.PI));
//normalize to positive values
angle = angle < 0 ? angle + 360 : angle;
loadingElement.style.removeProperty('animation'); //remove the property for testing purposes
$("#loading").css('transform', 'rotate(' + angle + 'deg)');
}
else{ //else for testing purposes, this will change the speed of the animation only on the first slider input change
$("#loading").css('animation', 'rotateRight infinite linear'); //see how the animation now actually starts from the initial location
$("#loading").css("animation-duration", 50 / speed + "s");
}
});
#loading {
position: absolute;
left: 0;
right: 0;
margin: auto;
transform-origin: 50% 50%;
/*I removed the initialization of the animation here*/
}
#keyframes rotateRight {
100% {
transform: rotate(360deg);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<img id="loading" src="https://placehold.it/100">
<input type="range" min="0" max="100" value="0" class="slider" id="slider">
<p>Speed: <span id="speed"></span></p>
Yes, we can!
Here's the approach we'll take:
On input change, get the new speed value
Grab the current transform value of the element, which is returned as a matrix()
Convert the matrix() to a rotate value in degrees
Remove the existing animation
Create a new animation based on the current speed and rotate value
Apply the new animation to the element
The main issue we need to overcome is creating a new animation keyframes based on the current rotate value - we need to create a new animation with a starting value equal to the current rotate value, and an end value equal to the current rotate value + 360.
In other words, if our element is rotated 90deg and the speed is changed, we need to create a new #keyframes of:
#keyframes updatedKeyframes {
0% {
transform: rotate(90deg);
},
100% {
transform: rotate(450deg); // 90 + 360
}
}
To create the dynamic animation I'm using the jQuery.keyframes plugin to create dynamic #keyframes.
While this solution works, I don't believe it's super performant based on how the jQuery.keyframes plugin works. For every new animation keyframes the plugin appends an inline <style>. This results in potentially dozens, hundreds, or even thousands of keyframes being defined. In the example below I'm using the speed variable to create the #keyframe names, so it will create up to 100 unique #keyframes styles. There are a few optimizations we could make here but that's outside the scope of this solution.
Here's the working example:
$(document).on('input', '#slider', function() {
var speed = $(this).val();
$('#speed').html(speed);
var transform = $("#loading").css('transform');
var angle = getRotationDegrees(transform);
$("#loading").css({
"animation": "none"
});
$.keyframe.define([{
name: `rotateRight_${speed}`,
"0%": {
"transform": "rotate(" + angle + "deg)"
},
"100%": {
'transform': "rotate(" + (angle + 360) + "deg)"
}
}]);
if (speed === "0") {
$("#loading").css("transform", "rotate(" + angle + "deg)");
} else {
$("#loading").playKeyframe({
name: `rotateRight_${speed}`,
duration: 50 / speed + "s",
timingFunction: "linear",
iterationCount: "infinite"
});
}
});
function getRotationDegrees(matrix) {
if (matrix !== 'none') {
var values = matrix.split('(')[1].split(')')[0].split(',');
var a = values[0];
var b = values[1];
var angle = Math.round(Math.atan2(b, a) * (180 / Math.PI));
} else {
var angle = 0;
}
return angle;
}
#loading {
position: absolute;
left: 0;
right: 0;
margin: auto;
transform-origin: 50% 50%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://rawgit.com/jQueryKeyframes/jQuery.Keyframes/master/jquery.keyframes.js"></script>
<img id="loading" src="http://via.placeholder.com/100x100">
<input type="range" min="0" max="100" value="0" class="slider" id="slider">
<p>Speed: <span id="speed"></span></p>
$(document).ready(function() {
//ENTRANCE
$("#first").css("top", -1000);
setTimeout(function() {
$("#first").animate({
top: 10
}, 400);
}, 200);
$("#second").css("top", -1000);
setTimeout(function() {
$("#second").animate({
top: 10 + 45 + 15
}, 400);
}, 400);
$("#third").css("top", -1000);
setTimeout(function() {
$("#third").animate({
top: 10 + 45 + 45 + 30
}, 400);
}, 600);
$("#four").css("top", -1000);
setTimeout(function() {
$("#four").animate({
top: 10 + 45 + 45 + 45 + 45
}, 400);
}, 800);
//EXIT
$('#first').on('click', function() {
$('#first').toggle();
$('#second').animate({top: 5}, 400);
});
$('#second').on('click', function() {
$('#second').toggle();
$('#third').animate({top: 5}, 400);
});
$('#third').on('click', function() {
$('#third').toggle();
$('#four').animate({top: 5}, 400);
});
$('#four').on('click', function() {
window.location.reload();
});
});
`
I have been trying for a while to make elements interact with each other using jquery, Here is a
Fiddle of my code.
I have although been having a few hiccups.
In a real world environment, elements may not be called in ascending or logical order.
Items do not animate properly when closed, there are gaps and in some cases, some items do not move depending on which is clicked.
There may be more than 4 items.
Here is my question: How can i make the elements animate and cover properly regardless of which item is clicked and what order the items are sorted.
please see this fiddle
var elements = $('.menu');// Here you can write any selector to get list of elements
elements.on('click', function() {
$(this).toggle();
var nextEleemnts = $(this).nextAll('.menu'); // Same selector will follow here
for (var i = 0; i < nextEleemnts.length; i++) {
var topPos = $(nextEleemnts[i]).position().top - 60; //little bit of counting
$(nextEleemnts[i]).animate({
top: topPos
}, 400);
}
});
There is also a good solution and straight forward solution provided to you by a guy in comment, For this you need to do a bit of change in CSS aswell, so if you don't want to do it, then you can take my approach aswell
Here I am talking an alternate approach, here what I am doing whenever you click on any element I am finding it's next siblings and position them up by 60 pixels
If I were you, I would consider using jqueryUI
But maybe you have some restrictions of some kind.
I came up with a solution, in which I use jquery gt selector to select elements after the one clicked.
Please note that html is almost empty, which allows to add as many elements as you like.
(By the way I wouldn't make elements position absolute as well, but that's another story.
$(document).ready(function() {
"use strict";
var childCount = 12;
// some templating library would make a better job
for (var i = 0; i < childCount; ++i) {
var child = $("<div>" + i + "th div </div>");
child.css("background-color", "#" + ((1 << 24) * Math.random() | 0).toString(16));
child.css("top", i * 50);
$("#parent").append(child); // add any transition here
}
var reset = $("<div id='reset'>Reset</div>")
.css("background-color", "black")
.css("color", "white")
.css("top", childCount * 50);
$("#parent").append(reset);
$("#parent > div").on("click", function() {
var clicked = $(this);
var index = $("#parent > div").index(clicked);
$("#parent > div:gt(" + (index - 1) + ")").add(reset).animate({
top: "-=50"
}, 100, function() {
clicked.remove();
});
childCount -= 1;
});
});
#parent > div {
width: 100px;
height: 40px;
margin-bottom: 10px;
position: absolute;
text-align: center;
-webkit-transition: all .5s;
-moz-transition: all .5s;
-o-transition: all .5s;
transition: all .5s;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="parent">
<!-- some data-bind attribute would be better than an id -->
</div>
I have a picture of an Air balloon. I need it to fly around my page randomly (it is kind of small). I need it only to fly in the top half of my page. I found the following code:
$("#Friends").animate({
top: "-=30px",
}, duration );
But I'm not sure how I could loop it and have it go both on the x axis and the y axis. Thanks if you can! I do have jQuery enabled :)
How about something like this.... LIVE FIDDLE
HTML
<img src="http://www.birdsnways.com/imgs/blbd48rt.gif" id="picture" />
CSS
#picture{
position:absolute;
}
JS
doNextPoint();
function doNextPoint(){
var maxX = $(window).width() - $('#picture').width();
var newX = rand(0, maxX);
var maxY = ($(window).height()/2) - $('#picture').height();
var newY = rand(0, maxY);
var speed = rand (1000, 3000);
$('#picture').animate({
'top': newY + 'px',
'left': newX + 'px'
}, speed, function(){
doNextPoint();
});
}
function rand (min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
CSS
#friends { position: absolute; }
Markup
<img src="http://jsfiddle.net/img/logo.png"
id="friends"/>
JS
function moveit() {
var newTop = Math.floor(Math.random()*350);
var newLeft = Math.floor(Math.random()*1024);
var newDuration = Math.floor(Math.random()*5000);
$('#friends').animate({
top: newTop,
left: newLeft,
}, newDuration, function() {
moveit();
});
}
$(document).ready(function() {
moveit();
});
Live demo:
http://jsfiddle.net/W69s6/embedded/result/
More updated Live Demo: http://jsfiddle.net/9cN4C/
(old demo is obsolete and has a broken link, however the code is still correct so it is left for reference, not for demonstration)
You can stick that code into a named function, and then add that function as the callback parameter for the animation, so it will call itself again after it finishes.
var flying;
flying = function() {
$("#Friends").animate({
top: "-=30px", // you'll need to change this
},
duration,
flying
);
}
flying();
As is, it will just keep flying upward because the animation is always set to go up by 30 px. You'll have to change the flying function to randomize the motions a bit. For more realism, save the previous movement, and just change it by a little (small acceleration) so it doesn't have very jerky motions.
To loop it: use SetTimeout: https://developer.mozilla.org/en/window.setTimeout
For the x-axis, use the CSS property left: (top: will get you y-axis)