Permalink
Cannot retrieve contributors at this time
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width"> | |
<title>SmartMap Angers, le plan Irigo des bus et tramway qui te géolocalise - Emmanuel Pelletier, développeur web Angers</title> | |
<meta name="description" content="Regardez simplement le plan des réseaux de bus et tramway d'Angers sur une carte similaire à Google Maps. Sur mobile, vous êtes géolocalisé en temps réel pour voir rapidement quels arrêts de bus sont prêts de vous !"> | |
<meta name="author" content="Emmanuel Pelletier"> | |
<link rel="shortcut icon" href="img/favicon.ico"> | |
<!-- d'abord l'iPhone 4, ensuite les autres : --> | |
<link rel="apple-touch-icon-precomposed" sizes="114x114" href="img/apple-touch-icon-114x114-precomposed.png"> | |
<link rel="apple-touch-icon-precomposed" href="img/apple-touch-icon-72x72-precomposed.png"> | |
<style> | |
html, body {width: 100%; height: 100%; margin: 0; padding: 0; font-family: sans-serif;} | |
.box { padding: 8px; border-radius: 4px; -webkit-box-shadow: rgba(0, 0, 0, 0.347656) 2px 2px 3px; box-shadow: rgba(0, 0, 0, 0.347656) 2px 2px 3px;color: white; border: 3px solid #6D8ACC; padding-left: 6px; font-weight: bold; background-color: #7B98D9;background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#6D8ACC), to(#7B98D9));} | |
.box img { vertical-align: bottom; padding: 2px; margin: 0 5px; cursor: pointer;} | |
#localize { cursor: pointer; } | |
#localize.off { border: 3px solid #6D8ACC; padding: 8px;} | |
#localize.on { border: 3px solid #0B3B8E; padding: 8px;} | |
#buttons { position: absolute; z-index: 999; left: 150px; top: 50px; display: none;} | |
#buttons div { float:left; margin-right: 10px; min-height: 34px; } | |
#buttons span { float: left;} | |
#searchBox input { font-size: large; margin: 4px 10px 0; padding: 0; -webkit-box-shadow: rgba(0, 0, 0, 0.347656) 2px 2px 3px; box-shadow: rgba(0, 0, 0, 0.347656) 2px 2px 3px; min-width: 25px; color: black; border: 1px solid #A9BBDF; font-weight: normal; background-color: #FEFEFE; background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#FEFEFE), to(#F3F3F3)) ; } | |
#smartmap_canvas { width: 100%; height: 100%; padding: 0; margin: 0; opacity: 1; -moz-opacity: 1; filter:alpha(opacity=1); } | |
img[src="img/search.png"] { margin: 3px 5px 0; } | |
.infos { margin: 0;} | |
#toasts { position: absolute; z-index: 999; bottom: 100px; text-align: center; left: 50%; width: 200px; margin-left: -100px;} | |
#toasts p { display:none; } | |
#toastError { background: #e01616; } | |
.mobile #buttons { left: 5px; top: 70px; width: auto;} | |
.mobile #buttons div {float: left;} | |
.mobile #searchBox.on { width: 90%; } | |
.mobile #searchBox input { width: 60%; } | |
.disclaimer { margin: 0; padding: 10px; text-align: center; border-bottom: 2px solid #555; } | |
</style> | |
</head> | |
<body> | |
<p class="disclaimer">Attention ! Ce plan n'a pas été mis à jour depuis 2013. <a href="http://bustram.irigo.fr/pdf/irigo/plansemaine.pdf">Voir le plan officiel en pdf</a></p> | |
<div id="buttons"> | |
<div id="localize" class="box off" title="Cliquer pour activer la géolocalisation"> | |
<img src="img/location.png" alt="Me localiser"> | |
</div> | |
<div id="searchBox" class="box"> | |
<input type="text" size="40" placeholder="Rechercher dans Angers et ses environs"> | |
<img src="img/search.png" alt="Rechercher" id="ok"> | |
<img src="img/close.png" alt="Fermer" id="close"></div> | |
<span id="offline" class="box">Vous êtes hors ligne, connectez vous à Internet pour utiliser l'application</span> | |
</div> | |
<div id="toasts"> | |
<p id="toast" class="box"></p> | |
<p id="toastError" class="box"></p> | |
</div> | |
<div id="smartmap_canvas"> | |
</div> | |
<script src="//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script> | |
<script>window.jQuery || document.write('<script src="js/jquery.min.js"><\/script>')</script> | |
<script src="js/geolocation.js"></script> | |
<script src="//maps.google.com/maps/api/js?sensor=true"></script> | |
<script> | |
$(document).ready(function() { | |
$("#buttons").show(); | |
if ( !navigator.geolocation ) | |
$('#localize').hide(); | |
if (navigator.onLine) { | |
$('#offline').hide(); | |
locateMe(); | |
} | |
else { | |
$('#localize, #searchBox').hide(); | |
} | |
$('#offline').click(function() { | |
if ($(this).html() == "Vous êtes hors ligne, connectez vous à Internet pour utiliser l'application") | |
$(this).html(" ? "); | |
else | |
$(this).html("Vous êtes hors ligne, connectez vous à Internet pour utiliser l'application"); | |
}); | |
$('#localize').click(function() { | |
if (watchID == null) | |
locateMe(); | |
else | |
stopLocateMe(); | |
}) | |
$('.mobile #searchBox input, .mobile #close').hide(); //on cache au départ le champ de recherche uniquement sur mobile | |
$('#ok').click(function() { | |
if ($("#searchBox input").is(':visible')) { | |
searchLocation(); | |
$('.mobile #searchBox input, .mobile #close').hide(); | |
$('.mobile #searchBox').removeClass('on'); | |
$('.mobile #localize').show(); | |
} | |
else { | |
$('.non-mobile #searchBox input, .non-mobile #close').fadeIn(); | |
$('.mobile #searchBox input, .mobile #close').show(); | |
$('#searchBox').addClass('on'); | |
$('.mobile #localize').hide(); | |
$('#searchBox input').focus(); | |
} | |
}); | |
$('#close').click(function() { | |
$('.non-mobile #searchBox input, .non-mobile #close').fadeOut(); | |
$('.mobile #searchBox input, .mobile #close').hide(); | |
$('#searchBox input').val(''); | |
$('#searchBox').removeClass('on'); | |
$('.mobile #localize').show(); | |
}); | |
//on lance la recherche quand on appui sur entrée et qu'on est positionné sur la barre de recherche | |
$(document.documentElement).keyup(function (event) { | |
if($('#searchBox input').is(':focus') && event.keyCode == 13) { | |
searchLocation(); | |
} | |
}); | |
}); | |
var clientIsMobile; | |
if (navigator.userAgent.indexOf('mobile') != -1 || navigator.userAgent.indexOf('Mobile') != -1) { | |
clientIsMobile = true; | |
$('html').addClass('mobile'); | |
if (navigator.userAgent.indexOf('Appli mobile plan Irigo Angers' != -1)) { | |
$('html').addClass('android-app'); | |
} | |
} | |
else { | |
clientIsMobile = false; | |
$('html').addClass('non-mobile'); | |
} | |
var marker = null; | |
var searchMarker = null; | |
var circle = null; | |
var watchID = null; | |
var infowindow = null; | |
var geocoder = new google.maps.Geocoder(); | |
var angers= new google.maps.LatLngBounds(new google.maps.LatLng(47.41, -0.62), new google.maps.LatLng(47.5237, -0.448)); | |
var smartMap = new google.maps.Map(document.getElementById("smartmap_canvas"), null); | |
smartMap.setCenter(new google.maps.LatLng(47.468891656982414, -0.5517196655273438)); | |
smartMap.setZoom(15); | |
// var mapMaxZoom = clientIsMobile == true ? 15 : 16; | |
var mapMaxZoom = 15; | |
var irigo = new google.maps.ImageMapType({ | |
getTileUrl: function(coords, z) { | |
return "img/tiles_new/Tile_" + coords.x + "_" + coords.y + "_" + z + ".jpg"; | |
}, | |
tileSize: new google.maps.Size(256, 256), | |
isPng: false, | |
minZoom: 13, | |
maxZoom: mapMaxZoom, | |
name: "Irigo", | |
alt: "Tuiles Plan Irigo" | |
}); | |
smartMap.mapTypes.set('irigo', irigo); | |
smartMap.setMapTypeId('irigo'); | |
var options; | |
if (clientIsMobile) { | |
options = { | |
mapTypeControlOptions: { | |
mapTypeIds: [ | |
'irigo', | |
google.maps.MapTypeId.ROADMAP, | |
google.maps.MapTypeId.TERRAIN, | |
google.maps.MapTypeId.SATELLITE, | |
google.maps.MapTypeId.HYBRID | |
], | |
style: google.maps.MapTypeControlStyle.DROPDOWN_MENU, | |
position: google.maps.ControlPosition.TOP_RIGHT | |
}, | |
panControl: false, | |
zoomControl: true, | |
zoomControlOptions: { | |
position: google.maps.ControlPosition.LEFT_BOTTOM | |
} | |
} | |
} | |
else { | |
options = { | |
mapTypeControlOptions: { | |
mapTypeIds: [ | |
'irigo', | |
google.maps.MapTypeId.ROADMAP, | |
google.maps.MapTypeId.TERRAIN, | |
google.maps.MapTypeId.SATELLITE, | |
google.maps.MapTypeId.HYBRID | |
], | |
style: google.maps.MapTypeControlStyle.HORIZONTAL_BAR | |
}, | |
scrollwheel: true | |
} | |
} | |
smartMap.setOptions(options); | |
// Create div for showing copyrights. | |
copyrightNode = document.createElement('div'); | |
copyrightNode.innerHTML = 'Plan © Irigo 2011'; | |
copyrightNode.id = 'copyright-control'; | |
copyrightNode.style.fontSize = '11px'; | |
copyrightNode.style.fontFamily = 'Arial, sans-serif'; | |
copyrightNode.style.margin = '0 2px 2px 0'; | |
copyrightNode.style.whiteSpace = 'nowrap'; | |
copyrightNode.index = 0; | |
smartMap.controls[google.maps.ControlPosition.BOTTOM_RIGHT].push(copyrightNode); | |
//place un point sur la carte correspondant à la position de l'internaute | |
function updateLocation(position) { | |
var lat = position.coords.latitude; | |
var lon = position.coords.longitude; | |
var acc = position.coords.accuracy; | |
var point = new google.maps.LatLng(lat, lon); | |
//si on a une position à 300m près, on considère que c'est une bonne position de départ et on ajoutera un marqueur si il n'y en a pas | |
if ( acc < 300 ) { | |
if(angers.contains(point)) { | |
if (marker != null) { | |
marker.setPosition(point); | |
} | |
else { | |
marker = new google.maps.Marker({ | |
position: point, | |
map: smartMap, | |
title:"Votre position" | |
}); | |
smartMap.setZoom(15); | |
smartMap.setCenter(point); | |
$('#toast').fadeIn().html('Position trouvée !'); | |
setTimeout("$('#toast').fadeOut();", 2000); | |
if ( acc > 100 ) { | |
if (circle != null) { | |
circle.setCenter(point); | |
circle.setRadius(acc); | |
} | |
else { | |
circle = new google.maps.Circle({ | |
center: point, | |
map: smartMap, | |
radius: acc, | |
clickable: false, | |
fillColor: "#0077D2", | |
fillOpacity: 0.15, | |
strokeColor: "#0077D2", | |
strokeOpacity: 0.6, | |
strokeWeight: 0.5 | |
}); | |
} | |
} | |
else { | |
if (circle != null) | |
circle.setMap(null); | |
circle = null; | |
} | |
} | |
} | |
else { | |
$('#toast').fadeIn().html('Dis donc, vous n\'êtes pas dans Angers vous...'); | |
setTimeout("$('#toast').fadeOut();", 2000); | |
setTimeout("stopLocateMe();", 3000); | |
} | |
} | |
//sinon on mettra simplement à jour un marqueur existant en ajoutant un cercle indiquant la précision | |
else if ( acc < 1000 ) { | |
if (marker != null) { | |
marker.setPosition(point); | |
if (circle != null) { | |
circle.setCenter(point); | |
circle.setRadius(acc); | |
} | |
else { | |
circle = new google.maps.Circle({ | |
center: point, | |
map: smartMap, | |
radius: acc, | |
clickable: false, | |
fillColor: "#0077D2", | |
fillOpacity: 0.15, | |
strokeColor: "#0077D2", | |
strokeOpacity: 0.6, | |
strokeWeight: 0.5 | |
}); | |
} | |
} | |
} | |
} | |
function handleError(e) { | |
//e.code = 1 -> l'utilisateur ne veut pas partager sa position / 2 -> pas de connexion / 3 -> timeout / 0 -> erreur autre | |
switch(e.code) { | |
case 1: text = "Tu veux pas me dire où tu es ? Ok, tant pis, m'en fou moi... :'(((("; break; | |
case 2: text = "Il semble qu'il y a un petit problème de connexion.. Tu es sûr d'avoir accès à Internet ?"; break; | |
case 3: text = "Hmm, tu es dans une grotte ? J'ai vraiment du mal à te trouver.. essaie de bouger pour voir."; break; | |
case 4: text = "Désolé, il y a un truc qui cloche mais je ne sais vraiment pas quoi sur ce coup..."; | |
} | |
$('#toastError').fadeIn().html('Erreur : <br>' + text); | |
setTimeout("$('#toastError').fadeOut();", 6000); | |
stopLocateMe(); | |
} | |
//recherche d'une adresse donnée en langage humain (conversion en coordonnées par l'api maps et affichage de point sur la carte) | |
function geocode(opts) { | |
function geocodeResult(response, status) { | |
if (status == google.maps.GeocoderStatus.OK && response[0] && smartMap.getBounds().contains(response[0].geometry.location)) { | |
smartMap.fitBounds(response[0].geometry.viewport); | |
console.log('ok'); | |
pos = response[0].geometry.location; | |
if (searchMarker != null) { | |
searchMarker.setPosition(pos); | |
infowindow.setContent('<p class="infos"><span style="font-weight: bold">Votre recherche :</span><br>' + response[0].formatted_address + '</p>'); | |
} | |
else { | |
var image = 'img/blue-dot.png'; | |
searchMarker = new google.maps.Marker({ | |
position: pos, | |
map: smartMap, | |
title:"Votre recherche", | |
icon: image, | |
animation: google.maps.Animation.BOUNCE | |
}); | |
setTimeout("searchMarker.setAnimation(null)", 2000); | |
infowindow = new google.maps.InfoWindow({ content: '<p class="infos"><span style="font-weight: bold">Votre recherche :</span><br>' + response[0].formatted_address + '</p>' }); | |
google.maps.event.addListener(searchMarker, 'click', function() { infowindow.open(smartMap,searchMarker); }); | |
} | |
} else { | |
$('#toast').fadeIn().html('Je ne trouve rien à cette adresse :/'); | |
setTimeout("$('#toast').fadeOut();", 6000); | |
} | |
} // trim leading and trailing space with trim capable browsers | |
if(opts.address && opts.address.trim) opts.address = opts.address.trim(); | |
if(opts.address || opts.latLng) geocoder.geocode(opts, geocodeResult); // no empty request | |
} | |
//on limite la map aux environs d'Angers | |
google.maps.event.addListener(smartMap,'center_changed',function() { checkAngersBounds(); }); | |
function checkAngersBounds() { | |
if(!angers.contains(smartMap.getCenter())) { | |
var C = smartMap.getCenter(); | |
var X = C.lng(); | |
var Y = C.lat(); | |
var AmaxX = angers.getNorthEast().lng(); | |
var AmaxY = angers.getNorthEast().lat(); | |
var AminX = angers.getSouthWest().lng(); | |
var AminY = angers.getSouthWest().lat(); | |
if (X < AminX) {X = AminX;} | |
if (X > AmaxX) {X = AmaxX;} | |
if (Y < AminY) {Y = AminY;} | |
if (Y > AmaxY) {Y = AmaxY;} | |
smartMap.setCenter(new google.maps.LatLng(Y,X)); | |
} | |
} | |
//on commence la localisation | |
function locateMe() { | |
if(navigator.geolocation) { | |
watchID = navigator.geolocation.watchPosition(updateLocation, handleError, { enableHighAccuracy: true, timeout: 40000 }); | |
if (marker != null) { | |
smartMap.setCenter(marker.getPosition()); | |
} | |
$("#localize").removeClass('off'); | |
$("#localize").addClass('on'); | |
$("#localize").attr('title', 'Cliquer pour désactiver la géolocalisation'); | |
$('#toast').fadeIn().html('Géolocalisation en cours'); | |
setTimeout("$('#toast').fadeOut();", 3000); | |
} | |
} | |
//on arrête la localisation | |
function stopLocateMe() { | |
if(navigator.geolocation) { | |
navigator.geolocation.clearWatch(watchID); | |
watchID = null; | |
/*if (marker != null) | |
marker.setMap(null); | |
marker = null; | |
if (circle != null) | |
circle.setMap(null); | |
circle = null;*/ | |
$("#localize").removeClass('on'); | |
$("#localize").addClass('off'); | |
$("#localize").attr('title', 'Cliquer pour activer la géolocalisation'); | |
$('#toast').fadeIn().html('Arrêt de la géolocalisation'); | |
setTimeout("$('#toast').fadeOut();", 3000); | |
} | |
} | |
//on lance la recherche d'une adresse donnée dans la barre de recherche | |
function searchLocation() { | |
var myAdress = $('#searchBox input').val() + ', Maine-et-Loire, Pays de la Loire, France'; | |
if ( $("#searchBox input").val() ) | |
geocode({address: myAdress, bounds: angers}); | |
} | |
var _gaq=[['_setAccount','UA-13184829-2'],['_trackPageview'],['_trackPageLoadTime']]; | |
(function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];g.async=1; | |
g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js'; | |
s.parentNode.insertBefore(g,s)}(document,'script')); | |
</script> | |
</body> | |
</html> |