I have searched for an answer before this, but like most of my problems, I find nothing. :(
Basically I'm trying to make a custom jQuery image slider using a basic system:
Put all image paths into an array.
Pre-load all images using each array entry path.
Load HTML 'img's (left, center and right) with the array paths [0],1 and [2].
When you click left, all the images margin-left move to left by 100% (and vice versa for right)
Here's my problem; When I click one of the navigation buttons, the images move but NOT at the same speed, there's some kind of acceleration factor I can't seem to turn off, meaning there is a gap between the images when they move.
Anyone know why this happens and how to stop it?
I have another issue as well regarding this, should I make a separate question for this?
Here's the Javascript.
$(document).ready(function(){
var images = [ "http://furrydex.net/img1.png", "http://furrydex.net/img2.png" ];
var loadedImages = [];
var pos = 0;
$.each(images, function( index, value ) {
var img=new Image();
img.src=value;
loadedImages.push(img);
});
if(images[2] == undefined) {
$('#left').attr('src', images[1]);
$('#center').attr('src', images[0]);
$('#right').attr('src', images[1]);
}
$('.navigationLeft').click(function() {
console.log("yay");
$( '.slide' ).animate({
marginLeft: "100%"
}, 500, "linear", function() {
// Animation complete.
});
});
});
The left black block is 'left' which you need to test it.
Here's the JSFiddle
Ok, I put something up, that makes it gapless, but I do think finding the culprit for making it somehow percentage-based-failing would be the right trick. ;)
var selWidth = $('.selector').width();
$( '.slide' ).animate({
marginLeft: selWidth
})
JSFIDDLE: http://jsfiddle.net/TRNCFRMCN/RrQ5d/5/
Related
I'm trying to make something happen when my element has moved a certain left amount.
var box = $('#box');
box.css('left', '500px'); //This is moving the box. I have a transition set in my css
if (box.offset().left == 200){
alert("yes");
}
It doesn't alert yes, though. I tried outputting the offset().left position into the console, and it DOES reach 200. Am I just using inproper syntax?
Using elem.css('left','500px') will set the left of the element to 500px. As you are comparing with 200, it will never meet that condition. Even in the soultion provided below, you still con not reallt compare it with single value as the progress will never be one pixle at a time. In provided solution, range of 200 - 250 is given.
Use progress option of jQuery animate
Try this:
var box = $('#box');
var datatDiv = $('#data');
box.animate({
'left': '500px'
}, {
duration: 5000,
progress: function() {
var leftVal = box.offset().left
if (leftVal > 200 && leftVal < 250) {
datatDiv.text("YES");
} else {
datatDiv.text("NO");
}
}
});
#box {
position: absolute;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<div id="box">BOX</div>
<br>
<div id='data'></div>
Fiddle here
I was able to accomplish what I needed through the position() function. I have a side scrolling image that moves to the left, and you control a snowball that must hop over trees. I needed to detect when the image had moved a certain distance to the left, which meant it collided with a tree in the image.
if (
(sideScroller.position().left < -960 && sideScroller.position().left > -1200 + mobileDelay) && (snowball.css('bottom') == '75px')
) {
hitTree()
}
mobileDelay was just some additional value for mobile devices, and hit tree just caused the snowball to evaporate when it hits a tree, lol. Position() works like a charm here.
I would just like to point out that Rayon's answer works as well, however I personally prefer to leave as much animation to CSS as possible, since in my experience it always runs smoother. Due to the large image, and the timed interval involved, using jQuery animation was not ideal in this situation.
I'm stuck in a drupal project, I would like to know how to get this effect done please, the left image will expand to right on click and same I want to the right image which will expand left on click, I want to know if it can be done by css3 only or javascript needed and how please... here are two image for my issue, I am mainly as front-end developer and know little of backend, so if anyone can help please..!
http://s14.postimg.org/aahx57ke9/img.png
If you want the image to slide and stay in that position after letting go of the mouse button, you have to use JavaScript.
I recommend jQuery. Here is an example illustrating how you can use JavaScript to slide elements and seamlessly superimpose them over each other, with jQuery animations; the JFiddle link at the bottom will show you the HTML, CSS, and JavaScript. It should be perfectly applicable to your image situation, assuming the images are positioned absolute.
JavaScript:
var b1 = $('#block1');
var b2 = $('#block2');
function slide(block, left, callback)
{
block.animate({
'left': left
}, 750, function() {
// Do this after finished animating.
if (callback) callback();
});
}
b1.on('click', function() {
// Only slide if not already done.
if (b1.css('left') != '-50px') {
// First slide both elements so they meet at the,
// middle, then switching the z-index is not noticeable.
slide(b1, '-250px');
slide(b2, '250px', function() {
// After animating, superimpose b1 over b2
// by changing z-index order, then animate
// the rest of the way.
b1.css('z-index', '1');
b2.css('z-index', '0');
slide(b1, '-50px');
});
}
});
b2.on('click', function() {
// Same here but with right element.
if (b2.css('left') != '50px') {
slide(b1, '-250px');
slide(b2, '250px', function() {
b1.css('z-index', '0');
b2.css('z-index', '1');
slide(b2, '50px');
});
}
});
Check it out in action here: https://jsfiddle.net/86sr3okk/6/
Welcome to the wonderful world of JavaScript.
I thought I had resolved this issue but turns out i hadn't. Basically building a tumblr theme and something in my code is conflicting with the jquery animated scroll to top. I've tried removing things as I'm not entirely sure what it could be and thought it might be really obvious to somebody else?
Here is a link to my theme http://minori-theme.tumblr.com/ and a jsfiddle that I was following in order to animate the smooth scroll http://jsfiddle.net/YtJcL/1008/
The code I'm using is below and I'm just using a standard a link and id which are linking fine as it goes to the correct point its just not smooth scrolling.
$(document).ready(function() {
var hashTagActive = "";
$(".scroll").click(function (event) {
if(hashTagActive != this.hash) { //this will prevent if the user click several times the same link to freeze the scroll.
event.preventDefault();
//calculate destination place
var dest = 0;
if ($(this.hash).offset().top > $(document).height() - $(window).height()) {
dest = $(document).height() - $(window).height();
} else {
dest = $(this.hash).offset().top;
}
//go to destination
$('html,body').animate({
scrollTop: dest
}, 2000, 'swing');
hashTagActive = this.hash;
}
});
});
Edit: If anyone has a simpler alternative I'm open to suggestions?
Easing effect on your animate function won't work if you don't add easing libary. jQuery core does not have easing.
<script type="text/javascript" src="http://gsgd.co.uk/sandbox/jquery/easing/jquery.easing.compatibility.js"></script>
Also you can define dynamic value to animate's timing based on your element's offset top value. This will make your animation smoother based on the current value.
Here is jsFiddle with smooth scrolling effect.
$(".scroll").click(function(event){
event.preventDefault();
var dest = 0;
var $target = $(this.hash);
var targetTop = $target.offset().top;
var remainTop = $(document).height() - $(window).height();
if( targetTop > remainTop){
dest = remainTop;
}else{
dest = targetTop;
}
// Dynamic value for timing
var dur = dest*1.2;
$('html,body').animate({scrollTop:dest}, dur,'easeInOutCubic');
});
And one last note, you should orgnize your code with using variables, these coding of your is hard to read and maintain.
The scroll works the first time, but not any time after that. Check through all the var's that get used to see if something is being kept.
EDIT:
The line
if(hashTagActive != this.hash)
will not bother with the jquery animation if you have already clicked "Back to top" because the hashTagActive is already #top. Thats why it works once but not twice.
EDIT 2:
Check out This fiddle for a way around it
Im trying to create a custom horizontal accordion style showcase. In terms of actual functionality, i have the framework (which can be seen here):
http://www.jsfiddle.net/adrianjacob/UdUus/
However my main bug bear (and the clients) is that if you look at the right hand side, there is always slight movement/flickering as the widths animate up and down.
Ideally I want it to appear smooth so only the opening/closing lists have movement.
ANy advice would be much appreciated.
A.
Use the animate function's step (it's not well documented)... I've updated the demo
var panels = $('#promo li');
panels.hoverIntent(
function() {
if (!$(this).is('.expanded') && !panels.is(':animated')) {
$(this).animate({
width: 200
}, {
// width is the calculated width, ani is the animation object
step: function(width, ani) {
var w = Math.floor(width);
// use 250 so we end up with 50 as the reduced size
$('.expanded').css('width', (250 - w) + 'px');
$(ani.elem).css('width', (200 - w) + 'px');
},
duration: 500,
complete: function() {
panels.removeClass('expanded');
$(this).addClass('expanded');
}
});
}
}, function() {});
A similar method is used in the Kwicks plugin.
You could try this plugin which may have figured out the bug. The example provided was too showy to actually tell.
Have you played around with jQuery UI easings?
You can also try to stop the event just when the div is opening.
The website with explanation is: http://api.jquery.com/stop/
I am running jQuery Cycle for an image gallery. View the link: Here
My problem is that the images are getting squished when viewed in firefox. The problem disappears when I re-load the page. This leads me to believe that the Javascript is triggering before all the images are loaded (usually the first image works fine and the rest are squished.)
A hard re-fresh reproduces the problem.
I've wrapped everything in a $(document).ready(function(){ }); but it still happens.
Additional Info: If I specify the width and height of the image, everything works fine. However there are hundreds of images all at different sizes..
I'm pretty frustrated with this problem. Any ideas/help is greatly appreciated!
Here is my code:
$(document).ready(function(){
//function onBefore(curr,next,opts) {
// var $slide = jQuery(next);
// var w = $slide.outerWidth();
// var h = $slide.outerHeight();
// $slide.css({
// marginTop: (482 - h) / 2,
// marginLeft: (560 - w) / 2
// });
//};
// Decare the function that center the images...
function onBefore(curr,next,opts) {
var $slide = jQuery(next);
var w = $slide.outerWidth();
var h = $slide.outerHeight();
$slide.css({
marginTop: (480 - h) / 2,
marginLeft: (560 - w) / 2
});
};
$(document).ready(function() {
$('#slideshow').cycle({
fx: 'fade',
next: '#next',
pause: 0,
speed: 500,
before: onBefore,
prev: '#prev',
pause: '#pause',
pager: '.thumbs',
pagerClick:function(zeroBasedSlideIndex, slideElement) {$(slideElement).find('div.cover').hide();},
pagerAnchorBuilder: function(idx, slide) {
var src = $('img',slide).attr('src');
//Change height of thumbnail here
return '<li><img src="' + slide.src + '" height="90" /></li>';
}
});});});
There is a much simpler and cleaner solution that I used to solve this problem than what has already been proposed:
Using jQuery, you need to use $(window).load instead of $(document).ready for your particular situation. To fix the issue, change this:
$(document).ready(function() {
$('#slideshow').cycle({
/* ... */
});
});
To this:
$(window).load(function() {
$('#slideshow').cycle({
/* ... */
});
});
Why does this work? Because window.onload fires after all referenced images on the page are loaded (See https://developer.mozilla.org/en/DOM/window.onload, and .load() - jQuery API), which is the desired behavior in your situation. $(document).ready, better known as "DOM Ready", will fire before images have loaded. This is typically the desired behavior, but in your situation it's too early.
I had the same problem when working on a site several months ago (linked below). If you're starting cycle in $(document).ready(), here's what happens when a client browses to your page:
1) The client's browser sends a request for each img element. Those requests take variable amounts of time to fulfill.
2) Before the image requests are completed, cycle starts. Cycle works by hiding all but the first image in the slide show: it sets visibility:hidden and display:none on each of its images.
The problem is that Firefox fixes the img element's size once and for all at the point the display style is set to none. So if the image hasn't finished loading, its height and width style attributes are small (I'm not sure exactly what they correspond to - perhaps the size of Firefox's image placeholder). When cycle shows the image by setting its style attribute to display:block, it uses whatever dimensions it had at the time it was hidden.
I solved this by changing my code so that it doesn't start the cycle plugin until all the images are finished loading. To do that, I initialize a counter variable to the number of images I'm cycling, then bind a load event to each image like this:
var imagesRemaining = 12; // 12 is just the number of images in the slideshow div
$(document).ready(function() {
$('#slideshow > img').bind('load', function(e) {
imagesRemaining = imagesRemaining - 1;
if (imagesRemaining == 0) {
// I'm doing some other stuff when initializing cycle
startCycle();
// My images all start with visibility:hidden so they don't show
// before cycle hides them in a 'stack', so ...
$('#slideshow > img').css('visibility', 'visible');
}
});
});
function onBefore(curr, next, opts) { // Your code here ... }
function startCycle() {
$('#slideshow').cycle({ ... // your initialization here });
}
You can see it in action by viewing the galleries on this site in Firefox. I'm building the gallery pages dynamically, so it's structured a bit differently than your page, but you can see more details if you poke around with Firebug.
I'd also like to add that it seems adding a width and height attribute solves this problem.
Ok i know its probably an awfull way of calling load but i just coulnd bind my cycle code to .load for some reason it just don't work so i called the whole Cycle initializer inside the ...
i couldn't force the sizes since i'm cycling through li containing dynamic images and data
its probably flawed at some extend but for those as desperated as me...
Josh, your solution has just saved me a headache, thank you very much!
I think i've amended it slightly in order to handle pages where you don't know the total number of images. It seems to be working fine for me, if anyone can see any flaws, please point them out - i'm still learning.
$(document).ready(function () {
$('#slideshow > img').each(
function go() {
$(this).bind('load', function (e) {
projects();
$('#slideshow > img').css('visibility', 'visible');
});
});
});
function projects() {
$('#slideshow').cycle({
fx: 'scrollHorz',
speed: 300,
timeout: 0,
next: '#next ',
prev: '#prev ',
after: onAfter,
nowrap: 1,
autostop: 1
});
}
If you're using a database to populate the slideshow you could try accessing the image dimensions from the image itself.
For example, using django you can use
width="{{ xxx.image.width }}px" height="{{ xxx.image.height }}px"
in your img tag.
You can use a solution similar to making youtube videos responsive. You need to know the ratio of your width to height, and add that as padding-bottom to the cycling div. For my 1024X680 photos, I used 680/1024 = 66.4%
In your case, I believe
#slideshow{
padding-bottom:66.4%;
}
will show the image unshrunk. I have no idea what the actual height and width values you are working with, so substitute your own. I had to use this solution when the $(window).load solution proved maddeningly ineffective -- so now I use both.
This is better than setting the dimensions of the image, because it's slides into a fluid, responsive enviroment.