11487 sujets

JavaScript, DOM et API Web HTML5

Bonjour à tous,

J'aimerais réaliser une carte qu'on fait défiler en cliquant/glissant (quand on va vers le haut, elle défile vers le bas et vice-versa) sans utiliser flash, uniquement verticalement, et en pouvant y adjoindre du contenu (liens, image, texte, etc.).

Avez-vous des pistes pour réaliser ce projet ? Pensez-vous que ce soit faisable et judicieux ?

Merci d'avance pour vos conseils.
Modifié par montoumes (16 Jan 2008 - 08:44)
Le principe est bien celui-là. Sauf que je voudrais utiliser quelque chose de léger, dont je fournirais moi-même le contenu (le fond de carte -c'est une carte antique !- + les éléments à y adjoindre)...
Salut,

a écrit :
je fournirais moi-même le contenu (le fond de carte -c'est une carte antique !- + les éléments à y adjoindre)...

C'est tout à fait possible avec l'API Google Maps, comme l'explique ce tutoriel. Quant aux éléments que tu veux y ajouter, tu pourras trouver ce qu'il faut dans la doc de l'API dont skywalk3r t'a fourni le lien.

Pour revenir à ta question initiale, si j'ai bien compris, tu as une simple image (ta carte) que tu veux faire défiler seulement verticalement avec des éléments en overlay et ceci sans niveau de zoom? Si c'est le cas, effectivement utiliser Google Maps revient à déboucher une bonne Duvel au burin Smiley cligne

dunjl
Modifié par dunjl (09 Jan 2008 - 17:14)
Oui tu as tout compris dunjl : une image à scroller, des calques au-dessus "synchronisés" avec le déplacement, et quelques liens...

C'est pour cela que je cherche autre chose que Google Maps. Je n'ai pas besoin d'une usine à gaz Smiley smile

Donc si quelqu'un à d'autres pistes Smiley smile Sinon je ferais peut-être un "vieux" innerHTML ou un div overflow:hidden... avec des positionnements absolus des villes. Mais c'est dommage de mettre une affreuse scrollbar...
Alors ce que tu peux faire c'est placer ton image dans un div (id="carte" par exemple) à la taille de ta carte. Ce div aura comme parent un autre div (id="mask" par exemple) qui va servir de masque avec overflow:hidden et des dimensions inférieures évidemment.
D'ailleurs le div #mask devrait par défaut être en overflow:auto et modifié en overflow:hidden dans ton script pour permettre la visualisation de ta carte même si javascript n'est pas activé.

Concernant le drag & drop tu peux utiliser ce script de Quirksmode à modifier pour qu'il ne drag le div #carte que verticalement.

J'espère que ça te donne des pistes.

dunjl
Merci pour le lien... mais j'ai testé en suivant la procédure, et je n'arrive pas à le faire fonctionner. Alors j'ai testé en copiant/collant l'exemple sur la même page, et ça ne fonctionne toujours pas... Je ne trouve pas ce qui cloche...
Est-ce que l'élément que tu veux dragger est bien en position:absolute ou fixed ? Peux tu poster ton code ou un lien ?
Dans le head, pour les styles, j'ai placé :


 <style type="text/css">
    #conteneurCarte {
    	width: 620px;
    	height: 400px;
    	overflow: hidden;
    	position: absolute; 
    	border: 1px solid #AF0078;
    	margin-left: 20px;
    	}
    #conteneurCarte #carte {
			width: 620px;
			height: 800px;
			background-color: #ffffff;
			position: absolute;
			top: 0;
			left: 0;
			cursor: pointer;
			z-index: 200;
		}
		
		</style>


Toujours dans le head, pour le script :


<script type="text/javascript">
			dragDrop = {
				keyHTML: '<a href="#" class="keyLink">#</a>',
				keySpeed: 10, // pixels per keypress event
				initialMouseX: undefined,
				initialMouseY: undefined,
				startX: undefined,
				startY: undefined,
				dXKeys: undefined,
				dYKeys: undefined,
				draggedObject: undefined,
				initElement: function (element) {
					if (typeof element == 'string')
						element = document.getElementById(element);
					element.onmousedown = dragDrop.startDragMouse;
					element.innerHTML += dragDrop.keyHTML;
					var links = element.getElementsByTagName('a');
					var lastLink = links[links.length-1];
					lastLink.relatedElement = element;
					lastLink.onclick = dragDrop.startDragKeys;
				},
				startDragMouse: function (e) {
					dragDrop.startDrag(this);
					var evt = e || window.event;
					dragDrop.initialMouseX = evt.clientX;
					dragDrop.initialMouseY = evt.clientY;
					addEventSimple(document,'mousemove',dragDrop.dragMouse);
					addEventSimple(document,'mouseup',dragDrop.releaseElement);
					return false;
				},
				startDragKeys: function () {
					dragDrop.startDrag(this.relatedElement);
					dragDrop.dXKeys = dragDrop.dYKeys = 0;
					addEventSimple(document,'keydown',dragDrop.dragKeys);
					addEventSimple(document,'keypress',dragDrop.switchKeyEvents);
					this.blur();
					return false;
				},
				startDrag: function (obj) {
					if (dragDrop.draggedObject)
						dragDrop.releaseElement();
					dragDrop.startX = obj.offsetLeft;
					dragDrop.startY = obj.offsetTop;
					dragDrop.draggedObject = obj;
					obj.className += ' dragged';
				},
				dragMouse: function (e) {
					var evt = e || window.event;
					var dX = evt.clientX - dragDrop.initialMouseX;
					var dY = evt.clientY - dragDrop.initialMouseY;
					dragDrop.setPosition(dX,dY);
					return false;
				},
				dragKeys: function(e) {
					var evt = e || window.event;
					var key = evt.keyCode;
					switch (key) {
						case 37:	// left
						case 63234:
							dragDrop.dXKeys -= dragDrop.keySpeed;
							break;
						case 38:	// up
						case 63232:
							dragDrop.dYKeys -= dragDrop.keySpeed;
							break;
						case 39:	// right
						case 63235:
							dragDrop.dXKeys += dragDrop.keySpeed;
							break;
						case 40:	// down
						case 63233:
							dragDrop.dYKeys += dragDrop.keySpeed;
							break;
						case 13: 	// enter
						case 27: 	// escape
							dragDrop.releaseElement();
							return false;
						default:
							return true;
					}
					dragDrop.setPosition(dragDrop.dXKeys,dragDrop.dYKeys);
					if (evt.preventDefault)
						evt.preventDefault();
					return false;
				},
				setPosition: function (dx,dy) {
					dragDrop.draggedObject.style.left = dragDrop.startX + dx + 'px';
					dragDrop.draggedObject.style.top = dragDrop.startY + dy + 'px';
				},
				switchKeyEvents: function () {
					// for Opera and Safari 1.3
					removeEventSimple(document,'keydown',dragDrop.dragKeys);
					removeEventSimple(document,'keypress',dragDrop.switchKeyEvents);
					addEventSimple(document,'keypress',dragDrop.dragKeys);
				},
				releaseElement: function() {
					removeEventSimple(document,'mousemove',dragDrop.dragMouse);
					removeEventSimple(document,'mouseup',dragDrop.releaseElement);
					removeEventSimple(document,'keypress',dragDrop.dragKeys);
					removeEventSimple(document,'keypress',dragDrop.switchKeyEvents);
					removeEventSimple(document,'keydown',dragDrop.dragKeys);
					dragDrop.draggedObject.className = dragDrop.draggedObject.className.replace(/dragged/,'');
					dragDrop.draggedObject = null;
				}
			}
function addEventSimple(obj,evt,fn) {
				if (obj.addEventListener)
					obj.addEventListener(evt,fn,false);
				else if (obj.attachEvent)
					obj.attachEvent('on'+evt,fn);
			}
			
			function removeEventSimple(obj,evt,fn) {
				if (obj.removeEventListener)
					obj.removeEventListener(evt,fn,false);
				else if (obj.detachEvent)
					obj.detachEvent('on'+evt,fn);
			}
			dragDrop.initElement('carte');
			/* j'essaie les deux méthodes, au cas ou... */
			dragDrop.initElement(document.getElementById('carte'));
		</script>


et enfin dans mon body :


<div id="index">
				  	<div id="conteneurCarte">				    
					  	<div id="carte">
						  	Blabla
					  	</div>  
					  </div>
				  </div>

J'ai aussi testé de placer le conteneurCarte et Carte en tête de page, en dehors de toute mise en page, mais ça ne marche pas non plus...

Pour être sur de rien manqué, j'ai mis la page en ligne ici

Merci Smiley smile
salut,

J'ai regardé, ton souci vient du fait que tu places l'appel à la fonction initElement dans le head, ça veut dire que cet appel est exécuté alors que ton élément 'carte' n'existe pas encore.

remplace
dragDrop.initElement('carte');

par
window.onload = function () {dragDrop.initElement('carte');}

Ta fonction est alors appelée lorque le document est entièrement chargé.

Concernant ton div #conteneurCarte, tu devrais le mettre en position:relative, cela permettrait que ton pied de page soit sous la carte.

bon courage
dunjl
Yes ! Tu as tout à fait raison, ça fonctionne à présent.

Y'a plus qu'a bidouiller pour bloquer le défilement horizontal Smiley smile

Meric encore !
hm...hm... c'est sympa le Javascript, hein ? Smiley confus Smiley sweatdrop

Dis Dunjl, tu pourrais me filer un coup de pouce ? Je n'arrive pas à bloquer la carte en haut et en bas ! Trop compliqué pour néophyte comme moi !

La page ressemble à ceci : http://egypte.webou.net/test/gabarit_carte.html

Et, si je n'abuses pas trop (sinon tant pis), peux-tu m'indiquer la manière d'implémenter le "overflow: auto" et "overflow:hidden" pour l'accessibilité... ?

Merci Smiley confused
hm...hm... c'est sympa le Javascript, hein ? Smiley confus Smiley sweatdrop

Dis Dunjl, tu pourrais me filer un coup de pouce ? Je n'arrive pas à bloquer la carte en haut et en bas ! Trop compliqué pour néophyte comme moi !

La page ressemble à ceci : http://egypte.webou.net/test/gabarit_carte.html

Et, si je n'abuses pas trop (sinon tant pis), peux-tu m'indiquer la manière d'implémenter le "overflow: auto" et "overflow:hidden" pour l'accessibilité... ?

Merci Smiley confused
Et bien ça commence à prendre forme Smiley cligne

Je me suis permis de faire quelques modifs sur ce que tu avais fait, notamment pour le défilement vertical j'ai vu que tu avais mis en commentaire une ligne dans le script dragDrop.
Il ne vaut mieux pas faire comme ça si tu veux réutiliser le script plus tard pour d'autres objets.

Par contre, j'ai ajouté une fonction appelée setLimits permettant de fixer des limites en X et en Y pour le déplacement. Cette fonction prend 4 paramètres : minX, maxX, minY, maxY qui sont des valeurs de déplacement par rapport au positionnement de départ.

DOnc voici le code dans ton head, place ces lignes
<script type="text/javascript" src="dragDrop.js"></script>
<script type="text/javascript" src="myMap.js"></script>


cree un fichier dragDrop.js et place y le code suivant :
dragDrop = {
	keyHTML: '<a href="#" class="keyLink">#</a>',
	keySpeed: 10, // pixels per keypress event
	initialMouseX: undefined,
	initialMouseY: undefined,
	startX: 0,
	startY: undefined,
	dXKeys: undefined,
	dYKeys: undefined,
	draggedObject: undefined,
	mode: undefined,
	minX: -Infinity,
	minY: -Infinity,
	maxX: Infinity,
	maxY: Infinity,
	initElement: function (element) {
		if (typeof element == 'string')
			element = document.getElementById(element);
		element.onmousedown = dragDrop.startDragMouse;
		element.innerHTML += dragDrop.keyHTML;
		var links = element.getElementsByTagName('a');
		var lastLink = links[links.length-1];
		lastLink.relatedElement = element;
		lastLink.onclick = dragDrop.startDragKeys;
	},
	startDragMouse: function (e) {
		dragDrop.startDrag(this);
		var evt = e || window.event;
		dragDrop.initialMouseX = evt.clientX;
		dragDrop.initialMouseY = evt.clientY;
		addEventSimple(document,'mousemove',dragDrop.dragMouse);
		addEventSimple(document,'mouseup',dragDrop.releaseElement);
		return false;
	},
	startDragKeys: function () {
		dragDrop.startDrag(this.relatedElement);
		dragDrop.dXKeys = dragDrop.dYKeys = 0;
		addEventSimple(document,'keydown',dragDrop.dragKeys);
		addEventSimple(document,'keypress',dragDrop.switchKeyEvents);
		this.blur();
		return false;
	},
	startDrag: function (obj) {
		if (dragDrop.draggedObject)
			dragDrop.releaseElement();
		dragDrop.startX = obj.offsetLeft;
		dragDrop.startY = obj.offsetTop;
		dragDrop.draggedObject = obj;
		obj.className += ' dragged';
	},
	dragMouse: function (e) {
		var evt = e || window.event;
		var dX = evt.clientX - dragDrop.initialMouseX;
		var dY = evt.clientY - dragDrop.initialMouseY;
		dragDrop.setPosition(dX,dY);
		return false;
	},
	dragKeys: function(e) {
		var evt = e || window.event;
		var key = evt.keyCode;
		switch (key) {
			case 37:	// left
			case 63234:
				dragDrop.dXKeys -= dragDrop.keySpeed;
				break;
			case 38:	// up
			case 63232:
				dragDrop.dYKeys -= dragDrop.keySpeed;
				break;
			case 39:	// right
			case 63235:
				dragDrop.dXKeys += dragDrop.keySpeed;
				break;
			case 40:	// down
			case 63233:
				dragDrop.dYKeys += dragDrop.keySpeed;
				break;
			case 13: 	// enter
			case 27: 	// escape
				dragDrop.releaseElement();
				return false;
			default:
				return true;
		}
		dragDrop.setPosition(dragDrop.dXKeys,dragDrop.dYKeys);
		if (evt.preventDefault)
			evt.preventDefault();
		return false;
	},
	setLimits: function (minX, maxX, minY, maxY) {
		dragDrop.minX = minX;
		dragDrop.maxX = maxX;
		dragDrop.minY = minY;
		dragDrop.maxY = maxY;
	},
	setPosition: function (dx,dy) {
	  dragDrop.draggedObject.style.left = 0 + 0 + 'px';
	  if ((dragDrop.startX + dx) > dragDrop.minX && (dragDrop.startX + dx) < dragDrop.maxX)
	  	dragDrop.draggedObject.style.left = dragDrop.startX + dx + 'px';
	  if ((dragDrop.startY + dy) > dragDrop.minY && (dragDrop.startY + dy) < dragDrop.maxY)
	  	dragDrop.draggedObject.style.top = dragDrop.startY + dy + 'px';
	},
	switchKeyEvents: function () {
		// for Opera and Safari 1.3
		removeEventSimple(document,'keydown',dragDrop.dragKeys);
		removeEventSimple(document,'keypress',dragDrop.switchKeyEvents);
		addEventSimple(document,'keypress',dragDrop.dragKeys);
	},
	releaseElement: function() {
		removeEventSimple(document,'mousemove',dragDrop.dragMouse);
		removeEventSimple(document,'mouseup',dragDrop.releaseElement);
		removeEventSimple(document,'keypress',dragDrop.dragKeys);
		removeEventSimple(document,'keypress',dragDrop.switchKeyEvents);
		removeEventSimple(document,'keydown',dragDrop.dragKeys);
		dragDrop.draggedObject.className = dragDrop.draggedObject.className.replace(/dragged/,'');
		dragDrop.draggedObject = null;
	}
}
function addEventSimple(obj,evt,fn) {
	if (obj.addEventListener)
		obj.addEventListener(evt,fn,false);
	else if (obj.attachEvent)
		obj.attachEvent('on'+evt,fn);
}

function removeEventSimple(obj,evt,fn) {
	if (obj.removeEventListener)
		obj.removeEventListener(evt,fn,false);
	else if (obj.detachEvent)
		obj.detachEvent('on'+evt,fn);
}

Ainsi tu as ton script dragDrop à part, que tu peux réutiliser ailleurs.

Crée enfin un fichier myMap.js et place y ce code:
myMap = {
	container: undefined,
	init: function(element) {
		if (typeof element == 'string')
			element = document.getElementById(element);
		dragDrop.initElement(element);
		dragDrop.setLimits(0, 0, -500, 0);
		myMap.container = element.parentNode;
		myMap.container.style.overflow = 'hidden';
	}
}
window.onload = function () {myMap.init('carte');};

C'est ici qu'on initialise le dragDrop sur ton élément 'carte' et qu'on y fixe des limites pour le déplacement . Enfin on passe le div parent de 'carte' en overflow:'hidden';
Tu peux tester en mettant la ligne setLimits en commentaire, cela devrait fonctionner sans contrainte.

Pour le css, tu devrais également le placer dans un fichier externe Smiley cligne
Pour l'overflow ligne à modifier :
 #conteneurCarte {
    	width: 620px;
    	height: 400px;
    	overflow: auto;
    	position: relative; 
    	border: 1px solid #E0E3C9;
    	margin-left: 20px;
		 	}


Bon courage

dunjl
Modifié par dunjl (15 Jan 2008 - 19:38)
Bonjour !

C'est génial dunjl ! Merci beaucoup pour cette aide. Le fonctionnement est parfait, et fonctionne autant sur FF que sur IE Smiley smile

Y'a plus qu'à compléter la carte, et à trouver un dispositif (rollover, ou lightbox, ou juste un rollover avec un span, je vais voir Smiley smile )

Je te tiendrais informé une fois la carte achevée.

Merci encore Smiley smile
Une question subsidiaire : c'est possible un "getElementByClass" ?

J'ai placé sur ma carte un rollover sur "abou simbel" (descendre sur la carte), mais je me demandais comment "automatiser" ce comportement ?

Par ici pour le test Smiley smile