Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
420 lines (381 sloc) 16.3 KB
<!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("&nbsp;&nbsp;?&nbsp;&nbsp;");
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 &copy 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>