I was just wondering if there are any methods of creating nice, smooth transition effects when navigating between pages? Things like blind effects, sliding effects, etc. I guess I'm looking for something like what jQuery can do with images - but for actual web pages. I know there are fade effects and all that, but I was just wondering if there was something more 'modern' out there. While I realize Flash would be a good fit for this, it is not an option.
You can do some pretty cool effects if you use jQuery UI. They will go much smoother if you load everything in using AJAX... but, here's an example to get it working with full page loads.
First you need to additionally include jQuery UI (I just built my own and only grabbed the effects I needed):
<script type="text/javascript" src="jquery-ui-1.7.1.custom.min.js"></script>
And here's the javascript you'll need to make it work.
$(function() {
$('body').hide();
$('a').bind('click', function() {
var newPage = $(this).attr('href');
$('body').hide('blind',{},500, function() {
newPageParts = newPage.split('?');
newPageURL = newPageParts[0];
newPageParams = newPageParts[1];
newPage = newPageURL+"?transition=true"+(newPageParams != undefined ? "&"+newPageParams : '');
window.location=newPage;
});
return false;
});
if(getURLParam('transition') != '') {
$('body').show('blind',{},500,null);
}
});
function getURLParam(strParamName){
var strReturn = "";
var strHref = window.location.href;
if ( strHref.indexOf("?") > -1 ){
var strQueryString = strHref.substr(strHref.indexOf("?")).toLowerCase();
var aQueryString = strQueryString.split("&");
for ( var iParam = 0; iParam < aQueryString.length; iParam++ ){
if (aQueryString[iParam].indexOf(strParamName + "=") > -1 ){
var aParam = aQueryString[iParam].split("=");
strReturn = aParam[1];
break;
}
}
}
return strReturn;
}
Of course, fading in is only going to work on pages that have this script on it...
Just a note: I did just kinda make this in a few minutes so it might be really ghetto. But, it does work... so... yeah...
IE has a very simple implementation of page transition effects, but I don't think they will work on other browsers like Mozilla and Safari.
Related
I'm trying to set up a website that loads pages through ajax calls replacing the current contents of with the ajax response. I'm putting a # and a page name at the end of my URLs so that people can book mark pages.
www.examplesite.com#home
www.examplesite.com#examples
www.examplesite.com#examples/example1
www.examplesite.com#examples/example2
I'm new to jQuery and to a lesser extent JavaScript but I'm trying to get a different page animation when I go to a page that is stored in a sub folder. fadeIn() works fine on both pages and pages in sub-folders however I can't get .slideDown() or .animate() to work at all. Here is an extract from my code:
<script>
//All pages are stored in a folder called 'pages' or a subfolder of 'pages'
$(document).ready(function(){
var myUrl = $(location).attr('href');
var noPage = myUrl.indexOf('#');
if(noPage == -1) {
location.hash = 'home';
}
window.onhashchange = function() {
pageChange();
}
function pageChange() {
var myUrl = $(location).attr('href');
var page = myUrl.substring(myUrl.indexOf('#') + 1, myUrl.length);
$.get('pages/' + page + '.html', function(pageHtml) {
if (page.indexOf('/') != -1) {
$('.main').hide().html(pageHtml).slideDown(400);
} else {
$('.main').hide().html(pageHtml).fadeIn(400);
}
});
};
pageChange();
});
</script>
If I'm approaching this from completely the wrong direction and that's why it's not working do feel free to point me in the correct direction by giving me an example of how it should work.
Got it!
I was using the css min-height property with a couple of my divs so that the page would expand automatically with the content if there was a lot on the page. If I remove the min-height property and replace it with a fixed height .slideDown() works fine.
Here are some links for more info if anyone else has the same issue:
http://www.only10types.com/2011/09/jquery-slidedown-doesnt-work-on.html
http://docs.jquery.com/Tutorials:Getting_Around_The_Minimum_Height_Glitch
I would take this...
if (page.indexOf('/') != -1) {
$('.main').hide().html(pageHtml).slideDown(400);
} else {
$('.main').hide().html(pageHtml).fadeIn(400);
}
And rearrange it to make sure your if statement is correct
if (page.indexOf('/') != -1) {
$('.main').hide().html(pageHtml).fadeIn(400);
} else {
$('.main').hide().html(pageHtml).slideDown(400);
}
If it now slides instead of fades, the if statement is corrupt
What about this ? Does this work ?
var main_div=$('.main');
main_div.hide();
$.get('pages/' + page + '.html', function(pageHtml) {
if (page.indexOf('/') != -1) {
main_div.html(pageHtml)
} else {
main_div.html(pageHtml)
}
});
main_div.slideDown(400);
maybe something in the CSS must be blocking it ? try disabling the CSS for the main class and try again ?
I want the javascript code to show a div in slow motion.
function showDiv(divID)
{
if(document.getElementById(divID).style.display=='none')
{
document.getElementById(divID).style.display='block';
}
}
Here div appears, but not in slow motion. Can anyone help ??
Thanks in advance
Dev..
There is no need of jQuery in this atall , its just a basic I am using your function to explain how thats done.
function showDiv(divID)
{
if(document.getElementById(divID).style.display=='none')
{
document.getElementById(divID).style.display='block';
}
}
What your function is doing is basically removing the whole Element from BOX Model ( the toggle of block and none removes the element totally from the BOX Model so it doesnt occupies any space or anything , this but may / may not cause some layout issues );
Now to animate it in slow motion you need a timing function.
a timing function is a simple mathematical function which gives the value of the property ( opacity in your case ) for a given time or depending on other parameters .
Other then that you also need to use properties like opacity in order to fade it (Opacity is a CSS property that defines the transparency of an element and its childrens )
So let us begin with a very basic show / hide using setTimeout Function in JS.
function getValue(t,dir){
if( dir > 0){
return 0.5*t; /* Y = mx + c */
}else{
return 1-(0.5*t);
}
/*
Here the slope of line m = 0.5.
t is the time interval.
*/
}
function animator(divID){
if(!(this instanceof animator)) return new animator(divID); /* Ignore this */
var Node = document.getElementById(divID),
start = new Date.getTime(), // The initiation.
now = 0,
dir = 1,
visible = true;
function step( ){
now = new Date.getTime();
var val = getValue( now - start,dir)
Node.style.opacity = val;
if( dir > 0 && val > 1 || dir < 0 && val < 0 ){
visible = !(visible*1);
// Optionally here u can call the block & none
if( dir < 0 ) { /* Hiding and hidden*/
Node.style.display = 'none'; // So if were repositioning using position:relative; it will support after hide
}
/* Our animation is finished lets end the continous calls */
return;
}
setTimeout(step,100); // Each step is executated in 100seconds
}
this.animate = function(){
Node.style.display = 'block';
dir *= -1;
start = new Date.getTime();
setTimeout(step,100);
}
}
now you can simply call the function
var magician = new animator('divName');
then toggle its animation by
magician.animate();
Now playing with the timing function you can create whatever possibilities you want as in
return t^2 / ( 2 *3.23423 );
or even higher polynomial equations like
return t^3+6t^2-38t+12;
As you can see our function is very very basic but it explains the point of how to make animations using pure js . you can later on use CSS3 module for animation and trigger those classes with javascript :-)
Or perhaps write a cross browser polyfill using CSS3 where available ( it is faster ) , and JS if not :-) hope that helps
Crossbrowser solution (without jQuery) :
HTML :
<div id="toChange" ></div>
CSS :
#toChange
{
background-color:red;
width:200px;
height:200px;
opacity:0;//IE9, Firefox, Chrome, Opera, and Safari
filter:alpha(opacity=0);//IE8 and earlier
}
Javascript :
var elem=document.getElementById("toChange");
var x=0;
function moreVisible()
{
if(x==1)clearInterval(t);
x+=0.05;
elem.style.opacity=x;
elem.style.filter="alpha(opacity="+(x*100)+")";
}
var t=setInterval(moreVisible,25);
Fiddle demonstration : http://jsfiddle.net/JgxW6/1/
So you have a few jQuery answers but I wouldn't recommend jQuery if fading the div is all you want.
Certainly jQuery makes things easier but it is a lot of overhead for a single simple functionality.
Here is someone that did it with pure JS:
Fade in and fade out in pure javascript
And a CSS3 example:
How to trigger CSS3 fade-in effect using Javascript?
You can use jquery $.show('slow') for the same, if you want to do the same without using jquery then you might be required to code something to show the effect yourself, you may have a look at source of jquery's show function http://james.padolsey.com/jquery/#v=1.6.2&fn=show . alternatively , you can also use fadein() for fade in effect in jquery
Yes you can do it using Jquery. Here is my sample example
$('#divID').click(function() {
$('#book').show('slow', function() {
// Animation complete.
});
});
For details clik here
Thanks.
I'm using a js image gallery on a magento site. Because Magento uses prototype, I've used prototype for this gallery; it's a simple application and I thought it unnecessary to load jQuery library as well just for this one element.
If you have a look at http://web74.justhost.com/~persia28/ in IE8 or less, the transitions between gallery slides is so slow, to the point where the text from one slide remains visible for a short time when the next slide is in place.
I know IE is rubbish with js, but I thought the extent of the slowness here is extreme, even for IE.
I don't want to load jQuery library just for this one gallery, Magento is enough of a tank as it is; so if it came to that I might opt for just putting the text in the images, not in HTML.
Anyway, would be great to hear your wisdom.
Many thanks, and here is the js code for the gallery.
var i = 0;
// The array of div names which will hold the images.
var image_slide = new Array('image-1', 'image-2', 'image-3');
// The number of images in the array.
var NumOfImages = image_slide.length;
// The time to wait before moving to the next image. Set to 3 seconds by default.
var wait = 4000;
// The Fade Function
function SwapImage(x,y) {
$(image_slide[x]).appear({ duration: 1.5 });
$(image_slide[y]).fade({duration: 1.5});
}
// the onload event handler that starts the fading.
function StartSlideShow() {
play = setInterval('Play()',wait);
$('PlayButton').hide();
$('PauseButton').appear({ duration: 0});
}
function Play() {
var imageShow, imageHide;
imageShow = i+1;
imageHide = i;
if (imageShow == NumOfImages) {
SwapImage(0,imageHide);
i = 0;
} else {
SwapImage(imageShow,imageHide);
i++;
}
}
function Stop () {
clearInterval(play);
$('PlayButton').appear({ duration: 0});
$('PauseButton').hide();
}
function GoNext() {
clearInterval(play);
$('PlayButton').appear({ duration: 0});
$('PauseButton').hide();
var imageShow, imageHide;
imageShow = i+1;
imageHide = i;
if (imageShow == NumOfImages) {
SwapImage(0,imageHide);
i = 0;
} else {
SwapImage(imageShow,imageHide);
i++;
}
}
function GoPrevious() {
clearInterval(play);
$('PlayButton').appear({ duration: 0});
$('PauseButton').hide();
var imageShow, imageHide;
imageShow = i-1;
imageHide = i;
if (i == 0) {
SwapImage(NumOfImages-1,imageHide);
i = NumOfImages-1;
} else {
SwapImage(imageShow,imageHide);
i--;
}
}
I looked at the site and it doesn't seem slow, it takes the same time to run. It looks as though the text is not changing in opacity until the end of the animation then is just being hidden. When I look with IE7 it works normally which is a clue, IE8 has a different way of making transparencies.
Magento still ships with Prototype 1.6.0 when I know that Prototype 1.6.1 fixes several IE8 bugs and Prototype 1.7 fixes some IE9 bugs too. You could try upgrading Prototype and Scriptaculous in the js/prototype/ and js/scriptaculous/ directories. I don't know if that exact problem is included which is why you should make a backup before overwriting files, if this doesn't work you will have something to rollback to.
I want to display several images of the same size at the same position, one at a time, with a 5s interval between each change. To do so I've used jQuery.Timer, that uses setInterval() to call some show_next_image() function every 5s.
It actually does work with IE, Opera, Safara, Firefox and.. partly with Google Chrome. It's not working with Google Chrome if I open a new window and directly type my website URL: it'll show the second image and stop. And with any other situation (reload, from another link, not right after opening a new window) it'll badly work: one can see the back image before the front image is shown.
Thus I'm wondering whether I've done something wrong with my JavaScript source. What I do is I use a front and a back image. When I want to show the next image, the back img source is set to the new image, and the front image is faded out while the back one is faded in through jQuery. You can check it out at http://www.laurent-carbon.com/ (in French). The two img are identified with bg1 and bg2.
var images = ["/img/IMG_0435bg.jpg", "/img/IMG_0400bg.jpg", "/img/maisonnette 2.jpg", "/img/IMG_0383bg.jpg", "/img/IMG_0409bg.jpg", "/img/IMG_0384bg.jpg"];
var idx = 1;
var waitTime = 5000; // ms
$(document).ready(function() {
$("#bg2").hide();
$.timer(waitTime, load_next);
$.preLoadImages(images);
});
function load_next(timer) {
var toshow = images[idx];
idx++;
idx %= images.length;
back_image().attr('src', toshow);
swap_images();
}
function front_image() {
return (idx % 2 == 0) ? $("#bg1") : $("#bg2");
}
function back_image() {
return (idx % 2 == 0) ? $("#bg2") : $("#bg1");
}
function swap_images() {
back_image().fadeOut('slow');
front_image().fadeIn('slow');
}
Thanks,
Ceylo
Ok I've worked out a solution .... without the use of plugins.
Demo
http://jsfiddle.net/morrison/PvPXM/9/show
source
http://jsfiddle.net/morrison/PvPXM/9/
This approach is a lot cleaner and removes the problem I had while viewing your page in chrome: the animation getting out of sync and flashing.
The only thing you have to do in the HTML is wrap the two images in a <div id="fadeBox" style="position:relative"></div>
$(function() {
var images = [
"http://www.laurent-carbon.com/img/IMG_0435bg.jpg",
"http://www.laurent-carbon.com/img/IMG_0400bg.jpg",
"http://www.laurent-carbon.com/img/maisonnette 2.jpg",
"http://www.laurent-carbon.com/img/IMG_0383bg.jpg",
"http://www.laurent-carbon.com/img/IMG_0409bg.jpg",
"http://www.laurent-carbon.com/img/IMG_0384bg.jpg"
];
var idx = 1;
var max = images.length;
var easing = "swing";
var waitTime = 5000; // ms
var fadeTime = 2000; // ms
var fadeShow = function(fadeTime, fadeDelay) {
var $topImage = $("#fadeBox img:last");
$topImage.fadeTo(fadeDelay, 1, function() {
$topImage.fadeTo(fadeTime, 0, easing, function() {
$topImage
.fadeTo(0, 1)
.insertBefore("#fadeBox img:first")
.attr("src", images[++idx == max ? idx = 0 : idx]);
fadeShow(fadeTime, fadeDelay);
});
});
};
fadeShow(fadeTime, waitTime);
});
Hope this helps
PS thanks to Levi for cleaning the code up a bit.
Answer: http://jsfiddle.net/morrison/RxyZY/
Notes:
You are trying to reinvent the wheel. You are creating a simple slideshow. There are numerous plugins to do exactly this and much more. I used jQuery cycle in my example, which is extremely customizable.
You should wrap your stuff up in a function, creating an expression. In my example, the (function($){}(jQuery)) is what does the trick. It scopes your variables to the function, rather than the global namespace.
I want to be able to do a cross fade transition on large images whose width is set to 100% of the screen. I have a working example of what I want to accomplish. However, when I test it out on various browsers and various computers I don't get a buttery-smooth transition everywhere.
See demo on jsFiddle: http://jsfiddle.net/vrD2C/
See on Amazon S3: http://imagefader.s3.amazonaws.com/index.htm
I want to know how to improve the performance. Here's the function that actually does the image swap:
function swapImage(oldImg, newImg) {
newImg.css({
"display": "block",
"z-index": 2,
"opacity": 0
})
.removeClass("shadow")
.animate({ "opacity": 1 }, 500, function () {
if (oldImg) {
oldImg.hide();
}
newImg.addClass("shadow").css("z-index", 1);
});
}
Is using jQuery animate() to change the opacity a bad way to go?
You might want to look into CSS3 Transitions, as the browser might be able to optimize that better than Javascript directly setting the attributes in a loop. This seems to be a pretty good start for it:
http://robertnyman.com/2010/04/27/using-css3-transitions-to-create-rich-effects/
I'm not sure if this will help optimize your performance as I am currently using IE9 on an amped up machine and even if I put the browser into IE7 or 8 document mode, the JavaScript doesn't falter with your current code. However, you might consider making the following optimizations to the code.
Unclutter the contents of the main photo stage by placing all your photos in a hidden container you could give an id of "queue" or something similar, making the DOM do the work of storing and ordering the images you are not currently displaying for you. This will also leave the browser only working with two visible images at any given time, giving it less to consider as far as stacking context, positioning, and so on.
Rewrite the code to use an event trigger and bind the fade-in handling to the event, calling the first image in the queue's event once the current transition is complete. I find this method is more well-behaved for cycling animation than some timeout-managed scripts. An example of how to do this follows:
// Bind a custom event to each image called "transition"
$("#queue img").bind("transition", function() {
$(this)
// Hide the image
.hide()
// Move it to the visible stage
.appendTo("#photos")
// Delay the upcoming animation by the desired value
.delay(2500)
// Slowly fade the image in
.fadeIn("slow", function() {
// Animation callback
$(this)
// Add a shadow class to this image
.addClass("shadow")
// Select the replaced image
.siblings("img")
// Remove its shadow class
.removeClass("shadow")
// Move it to the back of the image queue container
.appendTo("#queue");
// Trigger the transition event on the next image in the queue
$("#queue img:first").trigger("transition");
});
}).first().addClass("shadow").trigger("transition"); // Fire the initial event
Try this working demo in your problem browsers and let me know if the performance is still poor.
I had the same problem too. I just preloaded my images and the transitions became smooth again.
The point is that IE is not W3C compliant, but +1 with ctcherry as using css is the most efficient way for smooth transitions.
Then there are the javascript coded solutions, either using js straight (but need some efforts are needed to comply with W3C Vs browsers), or using libs like JQuery or Mootools.
Here is a good javascript coded example (See demo online) compliant to your needs :
var Fondu = function(classe_img){
this.classe_img = classe_img;
this.courant = 0;
this.coeff = 100;
this.collection = this.getImages();
this.collection[0].style.zIndex = 100;
this.total = this.collection.length - 1;
this.encours = false;
}
Fondu.prototype.getImages = function(){
var tmp = [];
if(document.getElementsByClassName){
tmp = document.getElementsByClassName(this.classe_img);
}
else{
var i=0;
while(document.getElementsByTagName('*')[i]){
if(document.getElementsByTagName('*')[i].className.indexOf(this.classe_img) > -1){
tmp.push(document.getElementsByTagName('*')[i]);
}
i++;
}
}
var j=tmp.length;
while(j--){
if(tmp[j].filters){
tmp[j].style.width = tmp[j].style.width || tmp[j].offsetWidth+'px';
tmp[j].style.filter = 'alpha(opacity=100)';
tmp[j].opaque = tmp[j].filters[0];
this.coeff = 1;
}
else{
tmp[j].opaque = tmp[j].style;
}
}
return tmp;
}
Fondu.prototype.change = function(sens){
if(this.encours){
return false;
}
var prevObj = this.collection[this.courant];
this.encours = true;
if(sens){
this.courant++;
if(this.courant>this.total){
this.courant = 0;
}
}
else{
this.courant--;
if(this.courant<0){
this.courant = this.total;
}
}
var nextObj = this.collection[this.courant];
nextObj.style.zIndex = 50;
var tmpOp = 100;
var that = this;
var timer = setInterval(function(){
if(tmpOp<0){
clearInterval(timer);
timer = null;
prevObj.opaque.opacity = 0;
nextObj.style.zIndex = 100;
prevObj.style.zIndex = 0;
prevObj.opaque.opacity = 100 / that.coeff;
that.encours = false;
}
else{
prevObj.opaque.opacity = tmpOp / that.coeff;
tmpOp -= 5;
}
}, 25);
}