Merged in feature/MAPG-4-show-the-real-position-on-a-map-after-the-guess (pull request #4)

Feature/MAPG-4 show the real position on a map after the guess
This commit is contained in:
Bence Pőcze 2020-05-19 14:33:33 +00:00
commit 1d4bfd75d8
5 changed files with 189 additions and 56 deletions

View File

@ -5,8 +5,8 @@ require '../main.php';
// very basic routing // very basic routing
$url = $_SERVER['REQUEST_URI']; $url = $_SERVER['REQUEST_URI'];
switch($url) { switch($url) {
case '/': case '/game':
$controller = new MapGuesser\Controller\GuessController(); $controller = new MapGuesser\Controller\GameController();
break; break;
case '/getNewPosition.json': case '/getNewPosition.json':
$controller = new MapGuesser\Controller\GetNewPosition(); $controller = new MapGuesser\Controller\GetNewPosition();

View File

@ -1,9 +1,53 @@
* {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
vertical-align: baseline;
}
html, body { html, body {
height: 100%; height: 100%;
margin: 0; margin: 0;
padding: 0; padding: 0;
} }
p, button {
font-family: 'Roboto', sans-serif;
}
p {
font-weight: 300;
font-size: 12px;
}
.bold {
font-weight: 500;
}
button {
cursor: pointer;
font-size: 15px;
font-weight: 500;
color: #ffffff;
background-color: #5e77aa;
padding: 8px 15px;
border: none;
border-radius: 3px;
}
button:hover, button:focus {
background-color: #29457f;
outline: none;
}
button:disabled {
cursor: no-drop;
color: #dddddd;
background-color: #808080;
opacity: 0.7;
}
#panorama { #panorama {
height: 100%; height: 100%;
width: 100%; width: 100%;
@ -18,6 +62,7 @@ html, body {
height: 150px; height: 150px;
opacity: 0.5; opacity: 0.5;
z-index: 2; z-index: 2;
visibility: visible;
transition-property: width, height, opacity; transition-property: width, height, opacity;
transition-duration: 0.1s; transition-duration: 0.1s;
transition-delay: 0.8s; transition-delay: 0.8s;
@ -26,7 +71,7 @@ html, body {
#guess:hover { #guess:hover {
width: 500px; width: 500px;
height: 350px; height: 350px;
opacity: 1.0; opacity: 0.95;
transition-delay: 0s; transition-delay: 0s;
} }
@ -50,26 +95,39 @@ html, body {
} }
#guessButton { #guessButton {
cursor: pointer; padding: 0;
font-size: 14px;
font-weight: bold;
color: #ffffff;
background-color: #5e77aa;
border: none;
border-radius: 3px;
width: 100%; width: 100%;
height: 100%; height: 100%;
box-sizing: border-box; box-sizing: border-box;
} }
#guessButton:hover, #guessButton:focus { #result {
background-color: #29457f; position: absolute;
outline: none; top: 50px;
left: 50px;
right: 50px;
bottom: 50px;
opacity: 0.95;
z-index: 2;
visibility: hidden;
background-color: #ffffff;
border-radius: 3px;
} }
#guessButton:disabled { #resultMap {
cursor: no-drop; height: 70%;
color: #dddddd; width: 100%;
background-color: #808080; }
opacity: 0.7;
#resultInfo {
height: 30%;
width: 100%;
padding: 20px;
text-align: center;
box-sizing: border-box;
}
#resultInfo p {
margin-bottom: 20px;
font-size: 24px;
} }

View File

@ -22,6 +22,18 @@ var Util = {
); );
return angle * Util.EARTH_RADIUS_IN_METER; return angle * Util.EARTH_RADIUS_IN_METER;
},
printDistanceForHuman: function (distance) {
if (distance < 1000) {
return Number.parseFloat(distance).toFixed(0) + ' m';
} else if (distance < 10000) {
return Number.parseFloat(distance / 1000).toFixed(2) + ' km';
} else if (distance < 100000) {
return Number.parseFloat(distance / 1000).toFixed(1) + ' km';
} else {
return Number.parseFloat(distance / 1000).toFixed(0) + ' km';
}
} }
}; };
@ -49,11 +61,11 @@ var realPosition;
var panorama; var panorama;
var guessMap; var guessMap;
var guessMarker; var guessMarker;
var resultMap;
var resultMarkers = { guess: null, real: null };
var googleLink; var googleLink;
function initialize() { function initialize() {
getNewPosition();
guessMap = new google.maps.Map(document.getElementById('guessMap'), { guessMap = new google.maps.Map(document.getElementById('guessMap'), {
disableDefaultUI: true, disableDefaultUI: true,
clickableIcons: false, clickableIcons: false,
@ -71,41 +83,21 @@ function initialize() {
guessMarker = new google.maps.Marker({ guessMarker = new google.maps.Marker({
map: guessMap, map: guessMap,
position: e.latLng, position: e.latLng,
draggable: true clickable: false,
draggable: true,
label: {
color: '#ffffff',
fontFamily: 'Roboto',
fontSize: '18px',
fontWeight: '500',
text: '?'
}
}); });
document.getElementById('guessButton').disabled = false; document.getElementById('guessButton').disabled = false;
}); });
}
function getNewPosition() {
var xhr = new XMLHttpRequest();
xhr.responseType = 'json';
xhr.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
realPosition = this.response.position;
var sv = new google.maps.StreetViewService();
sv.getPanorama({ location: this.response.position, preference: google.maps.StreetViewPreference.BEST }, loadPano);
}
};
xhr.open('GET', 'getNewPosition.json', true);
xhr.send();
}
function loadPano(data, status) {
if (status !== google.maps.StreetViewStatus.OK) {
getNewPosition();
return;
}
if (panorama) {
panorama.setPano(data.location.pano);
return;
}
panorama = new google.maps.StreetViewPanorama(document.getElementById('panorama'), { panorama = new google.maps.StreetViewPanorama(document.getElementById('panorama'), {
pano: data.location.pano,
disableDefaultUI: true, disableDefaultUI: true,
linksControl: true, linksControl: true,
showRoadLabels: false showRoadLabels: false
@ -118,6 +110,37 @@ function loadPano(data, status) {
panorama.addListener('pov_changed', function () { panorama.addListener('pov_changed', function () {
MapManipulator.rewriteGoogleLink(); MapManipulator.rewriteGoogleLink();
}); });
resultMap = new google.maps.Map(document.getElementById('resultMap'), {
disableDefaultUI: true,
clickableIcons: false,
});
getNewPosition();
}
function getNewPosition() {
var xhr = new XMLHttpRequest();
xhr.responseType = 'json';
xhr.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
realPosition = this.response.position;
var sv = new google.maps.StreetViewService();
sv.getPanorama({ location: this.response.position, preference: google.maps.StreetViewPreference.NEAREST }, loadPano);
}
};
xhr.open('GET', 'getNewPosition.json', true);
xhr.send();
}
function loadPano(data, status) {
if (status !== google.maps.StreetViewStatus.OK) {
getNewPosition();
return;
}
panorama.setPano(data.location.pano);
} }
document.getElementById('guessButton').onclick = function () { document.getElementById('guessButton').onclick = function () {
@ -126,14 +149,58 @@ document.getElementById('guessButton').onclick = function () {
} }
var guessedPosition = guessMarker.getPosition(); var guessedPosition = guessMarker.getPosition();
var distance = Util.calculateDistance(realPosition, { lat: guessedPosition.lat(), lng: guessedPosition.lng() });
alert('You were ' + (Math.round(distance) / 1000) + ' km close!');
this.disabled = true; this.disabled = true;
guessMarker.setMap(null); guessMarker.setMap(null);
guessMarker = null; guessMarker = null;
//TODO: fit to the same size as on init
var distance = Util.calculateDistance(realPosition, { lat: guessedPosition.lat(), lng: guessedPosition.lng() });
document.getElementById('guess').style.visibility = 'hidden';
document.getElementById('result').style.visibility = 'visible';
var resultBounds = new google.maps.LatLngBounds();
resultBounds.extend(realPosition);
resultBounds.extend(guessedPosition);
resultMap.fitBounds(resultBounds);
resultMarkers.real = new google.maps.Marker({
map: resultMap,
position: realPosition,
clickable: true,
draggable: false
});
resultMarkers.guess = new google.maps.Marker({
map: resultMap,
position: guessedPosition,
clickable: false,
draggable: false,
label: {
color: '#ffffff',
fontFamily: 'Roboto',
fontSize: '18px',
fontWeight: '500',
text: '?'
}
});
resultMarkers.real.addListener('click', function () {
window.open('https://www.google.com/maps/search/?api=1&query=' + realPosition.lat + ',' + realPosition.lng, '_blank');
});
document.getElementById('distance').innerHTML = Util.printDistanceForHuman(distance);
}
document.getElementById('continueButton').onclick = function () {
resultMarkers.real.setMap(null);
resultMarkers.real = null;
resultMarkers.guess.setMap(null);
resultMarkers.guess = null;
document.getElementById('guess').style.visibility = 'visible';
document.getElementById('result').style.visibility = 'hidden';
guessMap.fitBounds(guessMapBounds); guessMap.fitBounds(guessMapBounds);
getNewPosition(); getNewPosition();

View File

@ -6,7 +6,7 @@ use MapGuesser\View\HtmlView;
use MapGuesser\View\ViewBase; use MapGuesser\View\ViewBase;
use mysqli; use mysqli;
class GuessController implements ControllerInterface class GameController implements ControllerInterface
{ {
public function run(): ViewBase public function run(): ViewBase
{ {
@ -30,6 +30,6 @@ class GuessController implements ControllerInterface
$bounds = Bounds::createDirectly($map['bound_south_lat'], $map['bound_west_lng'], $map['bound_north_lat'], $map['bound_east_lng']); $bounds = Bounds::createDirectly($map['bound_south_lat'], $map['bound_west_lng'], $map['bound_north_lat'], $map['bound_east_lng']);
$data = compact('bounds'); $data = compact('bounds');
return new HtmlView('guess', $data); return new HtmlView('game', $data);
} }
} }

View File

@ -3,7 +3,8 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<title>MapGuesser</title> <title>MapGuesser</title>
<link rel="stylesheet" type="text/css" href="static/css/mapguesser.css"> <link href="static/css/mapguesser.css" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;500&display=swap" rel="stylesheet">
</head> </head>
<body> <body>
<div id="panorama"></div> <div id="panorama"></div>
@ -13,6 +14,13 @@
<button id="guessButton" disabled>Guess</button> <button id="guessButton" disabled>Guess</button>
</div> </div>
</div> </div>
<div id="result">
<div id="resultMap"></div>
<div id="resultInfo">
<p>You were <span id="distance" class="bold"></span> close.</p>
<button id="continueButton">Continue</button>
</div>
</div>
<script> <script>
var guessMapBounds = <?= $bounds->toJson() ?>; var guessMapBounds = <?= $bounds->toJson() ?>;
</script> </script>