Je vous présente aujourd’hui un tutoriel sur comment créer un effet de parallaxe sur son site grâce au plugin jParallax.

Premièrement il faut utiliser un id= »parallax » sur la balise sur laquelle on souhaite avoir du parallaxe afin de pouvoir lancer le script jquery.jparallax.js qui fera le reste.

Le principe est assez simple une fois que l’on a compris son fonctionnement. Par exemple j’utilise une balise qui contient tout mon parallaxe, je lui donne une largeur de 1000px et une hauteur de 500px.

Si à l’intérieur de celle-ci, je mets une image ou une balise de 1000px et 500px de large, il ne restera aucun espace afin que cette dernière bouge :
parallax2

Si je mets une balise de 900px de large et 500px de haut, cette dernière ne pourra bouger que latéralement de 100px :
parallax3

Si je mets une balise de 1000px de large et 400px de haut, cette dernière ne bougera que verticalement de 100px :
parallax4

Si je mets une balise de 900px de large et 400px de haut, cette dernière bougera sur l’axe des x comme sur l’axe des y :
parallax5

Plus les balises présentes dans la balise générale du parallaxe sont petites, plus elles seront mobiles.

Vous trouverez ci-dessous les fichiers sources ainsi qu’une démo :

DémoFichiers sources


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Parallaxe - webdesignweb - stratis bakas</title>

<link rel="stylesheet" href="css/style.css" type="text/css" media="screen"/>

<!-- Inclusion google webfont -->

<link href='http://fonts.googleapis.com/css?family=Terminal+Dosis+Light&v2' rel='stylesheet' type='text/css'>

<!-- Inclusion de jQuery et du script de parallax -->

<script type="text/javascript" src="js/jquery.js"></script>
<script type="text/javascript" src="js/jquery.jparallax.js"></script>

<!-- script qui permet de lancer la fonction jparallax lorsqu'on est dans la balise avec l'id parallax -->

<script type="text/javascript">
$(document).ready(function () {  
       $('#parallax').jparallax();
});  
</script>

</head>

<body>

	<div class="conteneur">
	
           <!-- Je mets un id="parallax" pour lancer le script js qui va faire le reste -->
		<div id="parallax">
			    		
    		<!-- Ici j'utilise une balise p dans laquelle je mets l'image afin de pouvoir régler la taille sans déformer l'image ou sans meme devoir passer par photoshop pour régler la taille de l'image. le dernier -->
    		<p style="text-align:center; width:970px;height:470px;padding-top:350px;"><img src="img/bandes.png"/></p>
    		<p style="text-align:center; width:975px;height:460px;padding-top:350px;"><img src="img/bandes.png"/></p>
    		<p style="text-align:center; width:980px;height:450px;padding-top:350px;"><img src="img/bandes.png"/></p>
    		<p style="text-align:center; width:940px;height:490px;padding-top:0px;"><img src="img/rond-rose.png"/></p>
    		<p style="text-align:center; width:780px;height:465px;padding-top:0px;"><img src="img/trait1.png"/></p>
    		<p style="text-align:center; width:680px;height:445px;padding-left:100px;"><img src="img/trait2.png"/></p>
    		<p style="text-align:center; width:580px;height:465px;padding-top:0px;"><img src="img/trait3.png"/></p>
    		<p style="text-align:left; width:800px;height:365px;padding-left:100px;"><img src="img/branches2.png"/></p>
    		<p style="text-align:right; width:800px;height:395px;padding-top:0px;"><img src="img/branches1.png"/></p>
    		<p style="text-align:center; width:970px;height:470px;padding-top:90px;"><img src="img/logo-sb.png"/></p>
    		<p style="width:980px; height:480px; color:#ed6578; text-align:center;padding-top:290px;"><a href="http://www.stratisbakas.com" target="_blank">www.stratisbakas.com</a><br /><a href="http://www.webdesignweb.fr" target="_blank">www.webdesignweb.fr</a><br /><a href="http://dribbble.com/stratweb" target="_blank">dribbble.com/stratweb</a></p>
    	</div><!-- #parallax -->
    	
	</div><!-- .conteneur -->
	
	<div id="footer">
		
		<div class="conteneur">
			<p style="text-align:center; margin:0;padding-top:80px;color:#ed6578;">Merci d'avoir suivi ce tuto et n'hésitez pas à partager.</p>
			<p style="text-align:center; margin:0;padding-top:40px;color:#ed6578;">Stratis bakas</p>
		</div><!-- .conteneur -->
		
	</div><!-- #footer -->

</body>
</html>


Le code css :

@charset "UTF-8";
/* CSS Document */

    
body {
	background: #eaecec url(../img/bg12.png) repeat;
	margin: 0;
	padding: 0;
	font-family: 'Terminal Dosis Light', sans-serif;
	text-transform: uppercase;
}

#parallax {
	position: relative;
	overflow: hidden;
	width: 1000px;
	height: 500px;
	margin-top: 0px;
}

.conteneur {
	width: 1000px;
	margin: 0 auto;
}

a {
	color: #ed6578;
	text-decoration: none;
}

#footer {
	width: 100%;
	background: #2b2b2b;
	height: 280px;
}

Le fichier jquery.jparallax.js :

// jquery.jparallax.js
// 0.9.1
// Stephen Band
//
// Dependencies:
// jQuery 1.2.6 (jquery.com)
//
// Project and documentation site:
// http://webdev.stephband.info/parallax.html


// CLOSURE

(function(jQuery) {


// PRIVATE FUNCTIONS

function stripFiletype(ref) {
  var x=ref.replace('.html', '');
  return x.replace('#', '');
}

function initOrigin(l) {
  if (l.xorigin=='left')	{l.xorigin=0;}	else if (l.xorigin=='middle' || l.xorigin=='centre' || l.xorigin=='center')	{l.xorigin=0.5;}	else if (l.xorigin=='right')	{l.xorigin=1;}
  if (l.yorigin=='top')		{l.yorigin=0;}	else if (l.yorigin=='middle' || l.yorigin=='centre' || l.yorigin=='center')	{l.yorigin=0.5;}	else if (l.yorigin=='bottom')	{l.yorigin=1;}
}

function positionMouse(mouseport, localmouse, virtualmouse) {

  var difference = {x: 0, y: 0, sum: 0};
  
	// Set where the virtual mouse is, if not on target
  if (!mouseport.ontarget) {
    
    // Calculate difference
    difference.x    = virtualmouse.x - localmouse.x;
    difference.y    = virtualmouse.y - localmouse.y;
    difference.sum  = Math.sqrt(difference.x*difference.x + difference.y*difference.y);
    
    // Reset virtualmouse
    virtualmouse.x = localmouse.x + difference.x * mouseport.takeoverFactor;
    virtualmouse.y = localmouse.y + difference.y * mouseport.takeoverFactor;
    
    // If mouse is inside the takeoverThresh set ontarget to true
    if (difference.sum < mouseport.takeoverThresh && difference.sum > mouseport.takeoverThresh*-1) {
    	mouseport.ontarget=true;
    }
  }
  // Set where the layer is if on target
  else {
    virtualmouse.x = localmouse.x;
    virtualmouse.y = localmouse.y;
  }
}

function setupPorts(viewport, mouseport) {

	var offset = mouseport.element.offset();
		
  jQuery.extend(viewport, {
    width: 		viewport.element.width(),
    height: 	viewport.element.height()
  });
  
  jQuery.extend(mouseport, {
    width:		mouseport.element.width(),
    height:		mouseport.element.height(),
    top:			offset.top,
    left:			offset.left
  });
}

function parseTravel(travel, origin, dimension) {
  
  var offset;
  var cssPos;
  
  if (typeof(travel) === 'string') {
    if (travel.search(/^\d+\s?px$/) != -1) {
      travel = travel.replace('px', '');
      travel = parseInt(travel, 10);
      // Set offset constant used in moveLayers()
      offset = origin * (dimension-travel);
      // Set origin now because it won't get altered in moveLayers()
      cssPos = origin * 100 + '%';   
      return {travel: travel, travelpx: true, offset: offset, cssPos: cssPos};
    }
    else if (travel.search(/^\d+\s?%$/) != -1) {
      travel.replace('%', '');
      travel = parseInt(travel, 10) / 100;
    }
    else {
      travel=1;
    }
  }
  // Set offset constant used in moveLayers()
  offset = origin * (1 - travel);
  return {travel: travel, travelpx: false, offset: offset}
}

function setupLayer(layer, i, mouseport) {

  var xStuff;
  var yStuff;
  var cssObject = {};

  layer[i]=jQuery.extend({}, {
  	width:		layer[i].element.width(),
  	height:		layer[i].element.height()
  }, layer[i]);

  xStuff = parseTravel(layer[i].xtravel, layer[i].xorigin, layer[i].width);
  yStuff = parseTravel(layer[i].ytravel, layer[i].yorigin, layer[i].height);

  jQuery.extend(layer[i], {
  	// Used in triggerResponse
  	diffxrat:    mouseport.width / (layer[i].width - mouseport.width),
  	diffyrat:    mouseport.height / (layer[i].height - mouseport.height),
  	// Used in moveLayers
  	xtravel:     xStuff.travel,
  	ytravel:     yStuff.travel,
  	xtravelpx:   xStuff.travelpx,
  	ytravelpx:   yStuff.travelpx,
  	xoffset:     xStuff.offset,
  	yoffset:     yStuff.offset
  });
  
  // Set origin now if it won't be altered in moveLayers()
  if (xStuff.travelpx) {cssObject.left = xStuff.cssPos;}
  if (yStuff.travelpx) {cssObject.top = yStuff.cssPos;}
  if (xStuff.travelpx || yStuff.travelpx) {layer[i].element.css(cssObject);}
}

function setupLayerContents(layer, i, viewportOffset) {

  var contentOffset;

  // Give layer a content object
  jQuery.extend(layer[i], {content: []});
  // Layer content: get positions, dimensions and calculate element offsets for centering children of layers
  for (var n=0; n<layer[i].element.children().length; n++) {
	  
	  if (!layer[i].content[n])          layer[i].content[n]             = {};
	  if (!layer[i].content[n].element)  layer[i].content[n]['element']  = layer[i].element.children().eq(n);
	  
	  // Store the anchor name if one has not already been specified.  You can specify anchors in Layer Options rather than html if you want.
    if(!layer[i].content[n].anchor && layer[i].content[n].element.children('a').attr('name')) {
    	layer[i].content[n]['anchor'] = layer[i].content[n].element.children('a').attr('name');
	  }
	  
	  // Only bother to store child's dimensions if child has an anchor.  What's the point otherwise?
	  if(layer[i].content[n].anchor) {
      contentOffset = layer[i].content[n].element.offset();
	  	jQuery.extend(layer[i].content[n], {
	  		width: 		layer[i].content[n].element.width(),
	  		height:		layer[i].content[n].element.height(),
	  		x:			  contentOffset.left - viewportOffset.left,
	  		y:			  contentOffset.top - viewportOffset.top
	  	});
	  	jQuery.extend(layer[i].content[n], { 
	  	  posxrat:  (layer[i].content[n].x + layer[i].content[n].width/2) / layer[i].width,
	  	  posyrat:  (layer[i].content[n].y + layer[i].content[n].height/2) / layer[i].height
      });
	  }
  }
}

function moveLayers(layer, xratio, yratio) {

	var xpos;
	var ypos;
	var cssObject;
	
	for (var i=0; i<layer.length; i++) {
    
    // Calculate the moving factor
  	xpos = layer[i].xtravel * xratio + layer[i].xoffset;
    ypos = layer[i].ytravel * yratio + layer[i].yoffset;
    cssObject = {};
  	// Do the moving by pixels or by ratio depending on travelpx
    if (layer[i].xparallax) {
      if (layer[i].xtravelpx) {
        cssObject.marginLeft = xpos * -1 + 'px';
      } 
      else {
        cssObject.left = xpos * 100 + '%';
        cssObject.marginLeft = xpos * layer[i].width *-1 + 'px';
      }
	  }
	  if (layer[i].yparallax) {
      if (layer[i].ytravelpx) {
        cssObject.marginTop = ypos * -1 + 'px';
      }
      else {
        cssObject.top = ypos * 100 + '%';
        cssObject.marginTop = ypos * layer[i].height * -1 + 'px';
      }
    }
    layer[i].element.css(cssObject);
	}
}

// PLUGIN DEFINITION **********************************************************************

jQuery.fn.jparallax = function(options) {
	
	// Organise settings into objects (Is this a bit of a mess, or is it efficient?)
	var settings = jQuery().extend({}, jQuery.fn.jparallax.settings, options);
	var settingsLayer = {
  			xparallax:				settings.xparallax,
  			yparallax:				settings.yparallax,
  			xorigin:					settings.xorigin,
  			yorigin:					settings.yorigin,
  			xtravel:          settings.xtravel,
  			ytravel:          settings.ytravel
  		};
  var settingsMouseport = {
  			element:					settings.mouseport,
				takeoverFactor:		settings.takeoverFactor,
				takeoverThresh:		settings.takeoverThresh
			};
	if (settings.mouseport) settingsMouseport['element'] = settings.mouseport;
	
	// Populate layer array with default settings
	var layersettings = [];
	for(var a=1; a<arguments.length; a++) {
		layersettings.push( jQuery.extend( {}, settingsLayer, arguments[a]) );
	}
	
	// Iterate matched elements
	return this.each(function() {

    // VAR
    
		var localmouse = {
					x:				0.5,
					y:				0.5
		};
		
    var virtualmouse = {
					x:				0.5,
					y:				0.5
		};
		
		var timer = {
		  running:		false,
		  frame:			settings.frameDuration,
		  fire:				function(x, y) {
		  	  				  positionMouse(mouseport, localmouse, virtualmouse);
                    moveLayers(layer, virtualmouse.x, virtualmouse.y);
		  	  				  this.running = setTimeout(function() {
		  	  				  	if ( localmouse.x!=x || localmouse.y!=y || !mouseport.ontarget ) {
		  	  				  		timer.fire(localmouse.x, localmouse.y);
		  	  				  	}
		  	  				  	else if (timer.running) {
		  	  				  		timer.running=false;
		  	  				  	}
		  	  				  }, timer.frame);
		  	  				}
		};

		var viewport	=	{element: jQuery(this)};		

		var mouseport = jQuery.extend({}, {element: viewport.element}, settingsMouseport, {
		  xinside:          false,		// is the mouse inside the mouseport's dimensions?
			yinside:	        false,
			active:		        false,		// are the mouse coordinates still being read?
			ontarget:         false			// is the top layer inside the takeoverThresh?
		});
    
		var layer			= [];
    
    // FUNCTIONS
    
    function matrixSearch(layer, ref, callback) {
      for (var i=0; i<layer.length; i++) {
        var gotcha=false;
        for (var n=0; n<layer[i].content.length; n++) {
          if (layer[i].content[n].anchor==ref) {
            callback(i, n);
            return [i, n];
          }
        }
      }
      return false;
    }
    
    // RUN
    
    setupPorts(viewport, mouseport);
		
		// Cycle through and create layers
    for (var i=0; i<viewport.element.children().length; i++) {
			// Create layer from settings if it doesn't exist
			layer[i]=jQuery.extend({}, settingsLayer, layersettings[i], {
				element:	viewport.element.children('*:eq('+i+')')
			});
			
		  setupLayer(layer, i, mouseport);
      
      if (settings.triggerResponse) {
		    setupLayerContents(layer, i, viewport.element.offset());
		  }
		}
		
		
    
    // Set up layers CSS and initial position
    viewport.element.children().css('position', 'absolute');
		moveLayers(layer, 0.5, 0.5);
		
		// Mouse Response
		if (settings.mouseResponse) {
			jQuery().mousemove(function(mouse){
				// Is mouse inside?
				mouseport.xinside = (mouse.pageX >= mouseport.left && mouse.pageX < mouseport.width+mouseport.left) ? true : false;
				mouseport.yinside = (mouse.pageY >= mouseport.top  && mouse.pageY < mouseport.height+mouseport.top)  ? true : false;
				// Then switch active on.
				if (mouseport.xinside && mouseport.yinside && !mouseport.active) {
					mouseport.ontarget = false;
					mouseport.active = true;
				}
				// If active is on give localmouse coordinates
				if (mouseport.active) {
					if (mouseport.xinside) { localmouse.x = (mouse.pageX - mouseport.left) / mouseport.width; }
					else { localmouse.x = (mouse.pageX < mouseport.left) ? 0 : 1; }
					if (mouseport.yinside) { localmouse.y = (mouse.pageY - mouseport.top) / mouseport.height; } 
					else { localmouse.y = (mouse.pageY < mouseport.top) ? 0 : 1; }
				}
				
				// If mouse is inside, fire timer
				if (mouseport.xinside && mouseport.yinside)  { if (!timer.running) timer.fire(localmouse.x, localmouse.y); }
				else if (mouseport.active) { mouseport.active = false; }			
			});
		}
		
		// Trigger Response
		if (settings.triggerResponse) {
		  viewport.element.bind("jparallax", function(event, ref){
		    
		    ref = stripFiletype(ref);
		          
        matrixSearch(layer, ref, function(i, n) {
          localmouse.x = layer[i].content[n].posxrat * (layer[i].diffxrat + 1) - (0.5 * layer[i].diffxrat);
          localmouse.y = layer[i].content[n].posyrat * (layer[i].diffyrat + 1) - (0.5 * layer[i].diffyrat);
  
          if (!settings.triggerExposesEdges) {
            if (localmouse.x < 0) localmouse.x = 0;
            if (localmouse.x > 1) localmouse.x = 1;
            if (localmouse.y < 0) localmouse.y = 0;
            if (localmouse.y > 1) localmouse.y = 1;
          }
          
          mouseport.ontarget = false;
          
          if (!timer.running) timer.fire(localmouse.x, localmouse.y);
        });
		  });
		}
		
		// Window Resize Response
		jQuery(window).resize(function() {

		  setupPorts(viewport, mouseport);
		  for (var i=0; i<layer.length; i++) {
		    setupLayer(layer, i, mouseport);
      }
		});
		
		
	});
};

// END OF PLUGIN DEFINITION **********************************************************************

// PLUGIN DEFAULTS

jQuery.fn.jparallax.settings = {
	mouseResponse:		    true,						// Sets mouse response
	mouseActiveOutside:		false,					// Makes mouse affect layers from outside of the mouseport. 
	triggerResponse:	    true,					  // Sets trigger response
  triggerExposesEdges:  false,          // Sets whether the trigger pulls layer edges into view in trying to centre layer content.
	xparallax:				    true,						// Sets directions to move in
	yparallax:				    true,						//
	xorigin:					    0.5,				    // Sets default alignment - only comes into play when travel is not 1
	yorigin:					    0.5,				    //
	xtravel:              1,              // Factor by which travel is amplified
	ytravel:              1,              //
	takeoverFactor:		    0.65,						// Sets rate of decay curve for catching up with target mouse position
	takeoverThresh:		    0.002,					// Sets the distance within which virtualmouse is considered to be on target, as a multiple of mouseport width.
	frameDuration:        25							// In milliseconds
};

// RUN

initOrigin(jQuery.fn.jparallax.settings);

jQuery(function() {
	
});


// END CLOSURE

})(jQuery);

Merci d’avoir suivi ce tuto et merci de bien vouloir partager si ça vous a plu…

21 comments
Christophe
Christophe

Bonjour, existe t-il une version compatible avec jquery-1.7.2 ? Car j'ai plusieurs script et je ne peux pas inclure un autre script Jquery. Merci :)

Destombes
Destombes

Salut, J'ai enfaîte un petit soucis, je souhaiterais avec cette effet parallaxe l'intégrer dans un slide en Jquery celui-ci : http://liquidslider.kevinbatdorf.com/ Seul problème, jqueri.min bloque l'effet parallaxe j'ai beau tout essayer sinon j'appliquerai une autres méthode...

Laurent
Laurent

Boujour, je vous remercie pour ce tutoriel! ça m'aide beaucoup pour la conception de mon portfolio, seulement j'aimerais modifier quelque chose. En fait, j'aimerais que les éléments prennent une direction opposée par rapport à la souris, je m'explique : lorsque la souris va vers la droite, les éléments vont vers la gauche, quand la souris va vers le bas, les éléments vont vers le haut, etc. Je pense qu'il faut modifier quelques éléments dans le javascript mais je ne connais pas du tout ce code, pour moi c'est du chinois! Pourriez-vous m'aider à résoudre ce problème?

Laurent
Laurent

C'est bon en fait, j'ai trouvé! Pas besoin, de modifier le javascript, il faut tout simplement faire un paragraphe de dimensions plus grandes que la balise qui contient la parallaxe. Ainsi, le paragraphe suit un mouvement opposé à celui de la souris, l'effet devient plus impressionnant!

Nitux
Nitux

Pile se qu'il me faut pour me faire un BG animé !!! Merci!! Une petite idée, sa serais bien que certain membre puisse eux aussi poster des tutos comme les tiens, sa enrichirais ton site d'avantage. (:

Mike wilkins
Mike wilkins

Bonjour ! Si j'ai bien compris, la vitesse d'un élément dépends de la place qui lui reste dans #parallax, mais alors, comment ça se passe quand on veut que l’élément soit plus large que #parallax (pour faire un paysage par exemple ) comment régler la vitesse et le sens de déplacement de chaque élément indépendamment ? merci d'avance et très bon tuto btw ! Mike

admin
admin

Bonjour je suis désolé mais je ne suis pas sûr de comprendre ta question

Mike wilkins
Mike wilkins

ouais désolé c'est pas super clair, par exemple là ta div parallax fait 1000px mais si je veux mettre y un element qui fait plus de 1000px (pour que ça défile tu vois) comment je peux faire pour regler sa vitesse en gros je sais pas si tu m'a compris

admin
admin

et bien si tu veux un element de 1200 px qui defile il te faut un conteneur (ici la div parallax) plus grande et plus cette dernière sera grande plus ton element de 1200 bougera vite

zeptof
zeptof

Coucou, j'ai essayé avec la derniere version de JQuery (1.7.1) par rapport a celle que tu proposes (1.2.6), et du coup le plugin jParallax.js ne fonctionne plus ... as tu regardé pourquoi ? merci d'avance et gg pour le tuto :)

Nicorockyou
Nicorockyou

Bonjour, Merci pour ce super tuto! J'ai le même probleme que zeptof. L'effet de Parallaxe n'est compatible qu'avec la version 1.2.6 de jQuery. Il n'y a pas un moyen de remettre tout cela à jour ?

admin
admin

J'ai un problème d'internet en ce moment donc je te réponds au plus vite désolé

admin
admin

Si vous regardez dans le fichier JS du parallaxe il est indiqué qu'il fonctionne avec la version 1.2.6 de jQuery. Sinon allez voir sur ce site pour récupérer les dernières versions http://stephband.info/jparallax/index.html

développeur php
développeur php

Salut, Très intéressant et enthousiasmant. Ca donne envie d'essayer ça tout de suite ! Why is this abrupt ?

Kicoe
Kicoe

Merci pour ces explications! je viens de faire un billet sur mon blog sur un plugin jquery, je vais te citer pour plus d'explication sur le mode de calcul pour les petits curieux :)

Biggizi
Biggizi

Ce tuto est PARFAIT!! Merci :)

admin
admin

I think the most important is the idea. I did it really quick for the article that's why it's a little bit abrupt. And also it depends of your browser ;)

admin
admin

merci c'est sympa, tu me montreras ce que t'as fait ;)

Geoffrey
Geoffrey

Hey Stratis!!! Vraiment sympa ton tuto!! Je pense que je vais me faire plaisir avec ça sur un prochain site !!! Au faite je viens tous juste de t' invite sur Google + !!

Trackbacks

  1. […] Effet de parallaxe sur son site – jParallax | WebDesignWeb cssObject.marginTop = ypos * layer[i].height * -1 + 'px' ; layer[i].element.css(cssObject); […]