I am building my own animation library; here is the jsfiddle link.
The problem is when I try to animate multiple properties the animation is finished as soon as the property with the last value is satisfied. For example:
I want to change an element's top and left properties to 500 and 300, respectively. The animation completes with both top and left as 300. This is incorrect.
My code structure resembles the following:
Main animate function:
function animate(ele,prop,duration,easing,callback) {
//...
}
Animation manager:
function Animation() {
this.start = function(ele,prop,duration,easing,callback) {
new animate(ele,prop,duration,easing,callback).start();
};
}
Please let me know how can solve this problem
http://jsfiddle.net/rrqe4qh1/1/
while applying the styles
this.ele.style[k]= val + 'px';
It was conflicting with style values of other properties as well
adding the below check helped
if(e===k) this.ele.style[k]= val + 'px';
Related
I’ve created an animation for my website to change a certain element (for example its background colour) while scrolling using Vanilla JS. For this I have used the window.onscroll property and I trigger the animation when window.scrollY reaches a specific position, my code is:
window.addEventListener('scroll', () => {
if (window.scrollX >= 1000) {
box.style = "background:red"
}
})
It looks great when I am editing on my big screen resolution, but if I look at the page on my laptop, the animation gets messed up because the innerWidth and innerHeight of the screen are different. I want to trigger the animation dynamically if it reaches a certain section of the page without having to worry about the scroll position.
Does anyone have any ideas about how I can fix this?
I think using getBoundingClientRect() solves your problem.
You basically do something like this:
var my_box = document.getElementById('my-box');
var rect = my_box.getBoundingClientRect();
The rect variable now contains an Object which includes a top and a left property with values that are relative to the viewport.
https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect
I have a JS feature on the following site that is working just fine in Firefox but not in Safari: http://rossbolger.com/kids/light-stories/
The feature slides out a grid of thumbnails called #image-thumbs when the mouse hovers over the container called #hit-area. It works (at least in Firefox) by first changing #image_thumbs height from '48px' to 'auto', the height is then measured using jQuery's height(). This height is stored in a variable and then using jQuery's css() it is given back to the #image-thumbs when the mouse is over.
The code on the site looks a little something like this:
// Thumbnails Nav Reveal and Hide Scripts
var thumbs_height = 1,
thumbs = $('#image-thumbs'),
thumbs_original_height = thumbs.css('height');
// Slide Up Thumbs
(function revealThumbs() {
// On hover let the thumbs become their full height
$('#image-thumbs #hit-area').hover(function(){ // Mouse over
// Get the unrestricted height of the thumbs
thumbs.css('height', 'auto');
thumbs_height = thumbs.height();
// then put it back to what it was so we can animate it using CSS3 transition
thumbs.css('height', 'inherit');
// delay 0.1s before triggering the change in height (time for the calculations to complete)
setTimeout( function() { thumbs.css('height', thumbs_height ) }, 100 );
}, function(){ // Mouse out
hideThumbs();
});
})();
// Hide thumbs
function hideThumbs(){
thumbs.css('height', thumbs_original_height );
};
The reason for measuring the unrestricted height and passing it back as a pixel value, rather than simply setting the height to 'auto', is to create a sliding effect via CSS3 (i.e. transition: height 0.5s). The transition only takes place if the affected attribute goes from one numeric value to another.
Thanks for any help bug testing this. I haven't even looked at other browsers yet.
All the best,
Laurence
Okay, so I've worked it out...
In the javascript document (scripts.js on the site) there was a function higher up the page calling the hideThumbs() function. So it wasn't working because the variables in hideThumbs() hadn't been declared at that point. Funny that it should still work in Firefox and IE9!
I've moved all this code to a point before that other function and the problem is now resolved. So far I've only done this locally. I'll update the site in the link above later.
I'm using jQuery.crSpline to animate a graphic along a curved path. I'm pretty happy with the result.
However, the full canvas size is intentionally pretty wide - definitely larger than most screens - so the graphic will run out of viewport space pretty quickly and animate off the screen.
Instead, I'd like browser viewport to follow or centre on the image so that it stays 'in shot'.
How would I go about this with jQuery? Is scrollTop an option?
I've created a jsFiddle demo, based on the crSpline demo source, but with a wide minX setting.
NB: I did first attempt this with YUI3 and Loktar offered a canvas based solution, however I'm not using YUI & canvas any longer.
Is this what you had in mind? http://jsfiddle.net/gNdwD/33/. It seems a little choppy but its a rough first attempt.
It doesn't seem like crSpline exposes any coordinates on the animated element so we have to periodically observe them and adjust the viewport accordingly:
setInterval(function() {
var mover = $('#mover'),
posX = mover.position().left,
posY = mover.position().top;
$(window)
.scrollLeft(posX - $(window).width() / 2)
.scrollTop(posY - $(window).height() / 2);
}, 10);
I suspect the choppiness happens because our setInterval is out of sync with the $.animate on the mover. You can fix that by running two animations: one on the mover and one on the scrollTop and scrollLeft of a wrapper div. You can simultaneously apply two $.animates like this.
There exists an option for step function in jQuery animate,which is run on every step of the animation.
See second version of function parameters here :
http://api.jquery.com/animate/
.animate( properties, options )
propertiesA map of CSS properties that the animation will move toward.
optionsA map of additional options to pass to the method. Supported keys:
duration: A string or number determining how long the animation will run.
easing: A string indicating which easing function to use for the transition.
complete: A function to call once the animation is complete.
step: A function to be called after each step of the animation.
queue: A Boolean indicating whether to place the animation in the effects queue. If false, the animation will begin immediately. As of jQuery 1.7, the queue option can also accept a string, in which case the animation is added to the queue represented by that string.
specialEasing: A map of one or more of the CSS properties defined by the properties argument and their corresponding easing functions (added 1.4).
See this fiddle based on your code, which calls step function to adjust viewport :
http://jsfiddle.net/gNdwD/35/
$('<div id="mover" />')
.appendTo($(document.body))
.animate({ crSpline: spline },{
duration: 20000,
step: function() { /* THE STEP FUNCTION TO ADJUST VIEWPORT */
var mover = $('#mover'),
posX = mover.position().left;
posY = mover.position().top;
$(window)
.scrollLeft(posX - $(window).width() / 2)
.scrollTop(posY - $(window).height() / 2);
} ,
complete:function () {
// Re-run the demo with a new spline after we're done
window.setTimeout(function() {
DEMO.run();
}, 5000);
}
});
I'm sorry this isn't more specific, but I'm having trouble isolating the issue.
I've written a very simple jQuery plugin that scrolls images or other elements through a div, like a carousel, on a set interval. I wanted this plugin to work with multiple instances on one page, but when I call it on multiple elements, only the last initialized element scrolls. I assume the way I'm using setInterval is the cause, but I don't understand why.
The function for scrolling is as follows, and the full source is linked above.
function scrollRight() {
// Don't animate if the mouse is over the scrollah
if (hovering) { return; }
/* If we're at the end, flip back to the first image
* before animating, lest we view blankness in the wrapper
*/
if (position === nChildren) {
position = 0;
$wrapper.css('left', '0px');
}
// Animate to the next view
position++;
$wrapper.animate({
left: position*-width+'px'
}, 1000, 'swing', function() {
// Animation complete.
});
}
setInterval(scrollRight, 5000);
So why do individual instances of this plugin not scroll once more have been initialized?
I think if you change $wrapper = $this.find('.wrapper'); to var $wrapper = $this.find('.wrapper'); it might work.
Learned this the other day from Stack Overflow: variables that don't use the var keyword are implicitly global in scope, so I think each scroller is overwriting the same global $wrapper variable.
EDIT: might also want to do var $this = $(this);.
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/