Javascript Smooth Glide? - javascript

I want to be able to move my element, El1, from (30,40) to (30,30) in 1000 milliseconds in a smooth animation. Is it even possible?

If you are not familiar to jQuery and if you don't want to use it and increase your page size by about 50kb just for some movements, I suggest you to use one of my functions:
function smooth(x, max){
return Math.floor((Math.sin((x/max*Math.PI)-(Math.PI/2))+1)*max/2);
}
and You need a code to move that element, something like this:
function process(LI){
LI = LI || Config.From;
LI++;
Left = smooth(LI, Config.To)
Config.Element.style.left = Left + 'px'
if (LI < Config.To)
setTimeout ("process("+LI+")", 10);
}
Config = {
Element: document.getElementById('El1'),
From: 0,
To: 400
};
process();

Try looking at the jquery libraries the animate function is exactly what you are looking for, and easy to implement.
Jquery is at http://jquery.com/
and the animate function specifically is at http://api.jquery.com/animate/
your code will look something like this
$('El1').animate({top: "-10px"}), 1000);

$("#moveme").animate({
top: "30px"
}, 1000);
Make sure there's an element with id="moveme" and css position: absolute

Related

Using a jquery slider for text instead of images?

This may be a little too specific, but I have a jquery slider that I am using <p> classes instead of images to cycle through customer quotes. Basically the problem I am running into right now is when it is static and non moving (JS code is commeneted out) they are aligned how I want them to be. As soon as the JS is un commented, they stretch out of view and you just see a white box?
Any ideas?
How I want each panel to look like:
jsfiddle
So I sort of made this my Friday project. I've changed a whole lot of your code, and added a vertical-align to the quotes and authors.
Here's the fiddle http://jsfiddle.net/qLca2fz4/49/
I added a whole lot of variables to the top of the script so you could less typing throughout.
$(document).ready(function () {
//rotation speed and timer
var speed = 5000;
var run = setInterval(rotate, speed);
var slides = $('.slide');
var container = $('#slides ul');
var elm = container.find(':first-child').prop("tagName");
var item_width = container.width();
var previous = 'prev'; //id of previous button
var next = 'next'; //id of next button
Since you used a % based width I'm setting the pixel widths of the elements in case the screen is reszed
slides.width(item_width); //set the slides to the correct pixel width
container.parent().width(item_width);
container.width(slides.length * item_width); //set the slides container to the correct total width
As you had, I'm rearranging the slides in the event the back button is pressed
container.find(elm + ':first').before(container.find(elm + ':last'));
resetSlides();
I combined the prev and next click events into a single function. It checks for the ID of the element targeted in the click event, then runs the proper previous or next functions. If you reset the setInterval after the click event your browser has trouble stopping it on hover.
//if user clicked on prev button
$('#buttons a').click(function (e) {
//slide the item
if (container.is(':animated')) {
return false;
}
if (e.target.id == previous) {
container.stop().animate({
'left': 0
}, 1500, function () {
container.find(elm + ':first').before(container.find(elm + ':last'));
resetSlides();
});
}
if (e.target.id == next) {
container.stop().animate({
'left': item_width * -2
}, 1500, function () {
container.find(elm + ':last').after(container.find(elm + ':first'));
resetSlides();
});
}
//cancel the link behavior
return false;
});
I've found mouseenter and mouseleave to be a little more reliable than hover.
//if mouse hover, pause the auto rotation, otherwise rotate it
container.parent().mouseenter(function () {
clearInterval(run);
}).mouseleave(function () {
run = setInterval(rotate, speed);
});
I broke this in to its own function because it gets called in a number of different places.
function resetSlides() {
//and adjust the container so current is in the frame
container.css({
'left': -1 * item_width
});
}
});
//a simple function to click next link
//a timer will call this function, and the rotation will begin :)
And here's your rotation timer.
function rotate() {
$('#next').click();
}
It took me a little bit, but I think I figured out a few things.
http://jsfiddle.net/qLca2fz4/28/
First off, your console was throwing a few errors: first, that rotate wasn't defined and that an arrow gif didn't exist. Arrow gif was probably something you have stored locally, but I changed the 'rotate' error by changing the strings in the code here to your actual variables.
So, from:
run = setInterval('rotate()', speed);
We get:
run = setInterval(rotate, speed);
(No () based on the examples here: http://www.w3schools.com/jsref/met_win_setinterval.asp)
But I think a more important question is why your text wasn't showing up at all. It's because of the logic found here:
$('#slides ul').css({'left' : left_value});
You even say that this is setting the default placement for the code. But it isn't..."left_vaule" is the amount that you've calculated to push left during a slide. So if you inspect the element, you can see how the whole UL is basically shifted one slide's worth too far left, unable to be seen. So we get rid of 'left_value', and replace it with 0.
$('#slides ul').css({'left' : 0});
Now, there's nothing really handling how the pictures slide in, so that part's still rough, but this should be enough to start on.
Let me know if I misunderstood anything, or if you have any questions.
So, a few things:
1) I believe you are trying to get all of the lis to be side-by-side, not arranged up and down. There are a few ways to do this. I'd just make the ul have a width of 300%, and then make the lis each take up a third of that:
#slides ul {
....
width: 300%;
}
#slides li {
width: calc(100% / 3);
height:250px;
float:left;
}
2) You got this right, but JSFiddle automatically wraps all your JS inside a $(document).ready() handler, and your function, rotate needs to be outside, in the normal DOM. Just change that JSFiddle setting from 'onload' to 'no wrap - in head'
3) Grabbing the CSS value of an element doesn't always work, especially when you're dealing with animating elements. You already know the width of the li elements with your item_width variable. I'd just use that and change your code:
var left_indent = parseInt($('#slides ul').css('left')) - item_width;
$('#slides ul').animate({'left' : left_indent}, 1500, function () {
to:
$('#slides ul').stop().animate({'left' : -item_width * 2}, 1500, function () {
4) Throw in the .stop() as seen in the above line. This prevents your animations from overlapping. An alternative, and perhaps cleaner way to do this, would be to simply return false at the beginning of your 'next' and 'prev' functions if #slides ul is being animated, like so:
if ($('#slides ul').is(':animated')) return false;
And I think that's everything. Here's the JSFiddle. Cheers!
EDIT:
Oh, and you may also want to clearInterval at the beginning of the next and prev functions and then reset it in the animation callback functions:
$('#prev').click(function() {
if ($('#slides ul').is(':animated')) return false;
clearInterval(run);
$('#slides ul').stop().animate({'left' : 0}, 1500,function(){
....
run = setInterval('rotate()', speed);
});
});

How to implement autoscroll to follow my div

I've looked at several tutorials online and a few similar questions on SO but not been able to work out how to make the screen autoscroll left and right so that my #sheep stays in the centre of the screen.
I'm using javascript and jquery to move a simple div across the screen.
Here's my jsfiddle
http://jsfiddle.net/JosephByrne/CkkVr/
What's the best method of making the screen follow my div?
I think you're trying to move the wrong element left/right. I think you need to leave your sheep in the middle of the screen then move the background.
Something like:
var walkLeft = function() {
$('#background').animate({left:"-=10px",top:"-=2px"}, 100);
$('#background').animate({left:"-=10px",top:"+=2px"}, 100);
};
var walkRight = function() {
$('#background').animate({left:"+=10px",top:"-=2px"}, 100);
$('#background').animate({left:"+=10px",top:"+=2px"}, 100);
};
http://jsfiddle.net/CkkVr/22/ (you'll need to "jump right" to see the sheep), but you get the general idea!
You need something similar to this:
function scrollContainer() {
var $sheep = $("#sheep");
$("body").scrollLeft($sheep.position().left + $sheep.width());
}
That utilizes jQuery's scrollLeft() function as well as the position() function (on the sheep).
You just need to keep messing with the math until it works out properly...
I've implemented it on the "jump" functions here:
http://jsfiddle.net/Dxe8a/11/
function scrollContainer() {
var $sheep = $("#sheep");
var $body = $("body");
var windowWidthOver2 = ($(window).width()/2);
var pos = $sheep.position().left + windowWidthOver2 - $sheep.width() - 80;
if($body.width() <= (pos + windowWidthOver2 - $sheep.width() - 80)) {
$body.width($body.width() + windowWidthOver2);
}
$body.scrollLeft(pos);
}
You should alter it so that it looks a bit better, but at least it follows your sheep somewhat.
P.S. it works better in fiddle if you view it in "/show": http://jsfiddle.net/Dxe8a/11/show

Dynamically binding/unbinding SuperScrollorama tweens

I'm trying to bind/unbind SuperScrollorama tweens dynmaically. On unbind, I also need to reset the tweened element to its default styles. In my case, I'm the bind/unbind needs to happen, based on browser width. I thought I could do something like this:
calcSizes = function() {
controller.addTween( '#panel', TweenMax.to( $('#panel h1'), .5, {css:{top: 0 }}), 0, 50);
if ( viewport().width >= '720' ) {
controller.removeTween( '#panel' );
}
}
$(window).resize(function(){
calcSizes();
});
Of course, this isn't particularly elegant, and doesn't work.
this does work with ScrollMagic. :)
check it out. -> http://janpaepke.github.io/ScrollMagic/
regards,
J

jquery animation and .offset

Basically I have an image that is 780px long and I have a window through which you can only see 390px at a time. There are left and right arrows so you can scroll one way and then the other. I would like the arrows to be disabled once you reach the end of the image either at 0px or -780px. I have tried the following code just to see if I am going in the right direction however it only works with the ">" sign and I need it to work with "==":
$(function() {
$(".big-fwd img").click(function() {
var offset = $(".wrap-nga").offset();
$(".wrap-nga").animate({
left: "-=390px"
})
if (offset > "-780px") {
alert("hello");
}
});
The second problem is that when I write the code I really want to have instead of the alert, nothing at all happens:
$(function() {
$(".big-fwd img").click(function() {
var offset = $(".wrap-nga").offset();
$(".wrap-nga").animate({
left: "-=390px"
})
if (offset > "-780px") {
$(".big-fwd img").removeAttr();
}
});
I'm really at a loss. I've tried "position" instead of "offset" but that's not the problem.
Any help would be fantastic. You can also get a better idea of what I'm trying to do by going to http://www.lieslswogger.com and clicking on one of the images in the gallery. Thank you!!
I think your comparison issue is due to the fact the the result of $.offset() is an object, not a value.
From http://api.jquery.com/offset/
.offset() returns an object containing the properties top and left.
You probably want to use offset.left, in your case.
Hope that helps!
Do the offset check before animating. You also will need to compare a numeric value for the inequalities in this case.
$(".big-fwd img").click(function(){
var offset = $(".wrap-nga").offset();
if(offset.left < 780)
$(".wrap-nga").animate({ left: "-=390px" })
});
Similarly on back .big-back img:
if(offset.left > 0) // proceed with animation
Make sure you close your function. It should be:
$(function() {
$(".big-fwd img").click(function() {
var offset = $(".wrap-nga").offset();
$(".wrap-nga").animate({
left: "-=390px"
}) if (offset > "-780px") {
$(".big-fwd img").removeAttr();
}
});
});

Is there any way to make two jQuery animations run (properly) simultaneously?

I have an event listener that calls two animation actions. Unfortunately their starts are staggered by a small amount (e.g. the first in the function starts first).
Does anyone know a way to properly sync them up?
Here's my code:
$("#nav ul li a").hover(
function(){
$(lastBlock).children("div").animate({width: "0px"}, { queue:false, duration:400, easing:"swing" });
$(this).children("div").animate({width: maxWidth+"px"}, { queue:false, duration:400, easing:"swing"});
lastBlock = this;
}
);
Because the first animation runs slightly before the second, it causes the overall width to become momentarily unequal, which looks a bit funky.
There was a recent disussion about this exact topic on the jQuery dev list. They created a few test cases you might wanna look at. Specially the Johns test.
Here's the discussion topic btw.
The trick is to have a single interval/callback in which all elements are updated.
You can find an example in my post here:
Can I implement a callback with each animation step in jQuery?
What you end up is basically:
var el1 = $("#element1");
var el2 = $("#element2");
var animation = new AnimationTimeline( {
easing: "swing"
, onstep: function( stepValue, animprops )
{
// This is called for every animation frame. Set the elements:
el1.css( { left: ..., top: ... } );
el2.css( { left: ..., top: ... } );
}
});
// And start it.
animation.start();

Categories

Resources