次のコードは、基本的に必要なことを行います。現在地 (GPS による) から目的地までの距離と方位を計算し、コンパスを使用して現在の方向を決定します。現在の進行方向と目的地までの方位との差が、矢印の角度です。
アセットとコンパイルされた Android APK を含むコードは、http: //ge.tt/4Kb2oQv/v/0からダウンロードできます。
これがコードです。お役に立てば幸いです。
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Compass test</title>
<script type="text/javascript" src="phonegap.js"></script>
<script type="text/javascript" src ="jquery-1.7.1.min.js">//</script> <!--http://code.jquery.com/jquery-1.7.1.min.js -->
<script type="text/javascript" src ="latlon.js">//</script> <!-- based on http://www.movable-type.co.uk/scripts/latlong.html -->
<style type="text/css">
#error, #results{
display: none;
}
#arrow{
position: absolute;
width: 30px;
height: 30px;
background: 50% 50% no-repeat;
background-size: 30px 30px;
background-image: url('arrow.png');
top: 0;
left: 50%;
margin: 30px 0 0 -15px;
}
#results .text{
margin-top: 100px;
}
</style>
<script type="text/javascript" >
var destinationPosition;
var destinationBearing;
var positionTimerId;
var currentPosition;
var prevPosition;
var prevPositionError;
var compassTimerId;
var currentHeading;
var prevHeading;
var prevCompassErrorCode;
$(document).on("deviceready", function() {
minPositionAccuracy = 50; // Minimum accuracy in metres to accept as a reliable position
minUpdateDistance = 1; // Minimum number of metres to move before updating distance to destination
$targetLat = $('#target-lat');
$targetLon = $('#target-lon');
$error = $('#error');
$results = $('#results');
$distance = $('#distance');
$bearing = $('#bearing');
$heading = $('#heading');
$difference = $('#difference');
$arrow = $('#arrow');
watchPosition();
watchCompass();
// Set destination
$targetLat.change(updateDestination);
$targetLon.change(updateDestination);
updateDestination();
});
function watchPosition(){
if(positionTimerId) navigator.geolocation.clearWatch(positionTimerId);
positionTimerId = navigator.geolocation.watchPosition(onPositionUpdate, onPositionError, {
enableHighAccuracy: true,
timeout: 1000,
maxiumumAge: 0
});
}
function watchCompass(){
if(compassTimerId) navigator.compass.clearWatch(compassTimerId);
compassTimerId = navigator.compass.watchHeading(onCompassUpdate, onCompassError, {
frequency: 100 // Update interval in ms
});
}
function onPositionUpdate(position){
if(position.coords.accuracy > minPositionAccuracy) return;
prevPosition = currentPosition;
currentPosition = new LatLon(position.coords.latitude, position.coords.longitude);
if(prevPosition && prevPosition.distanceTo(currentPosition)*1000 < minUpdateDistance) return;
updatePositions();
}
function onPositionError(error){
watchPosition();
if(prevPositionError && prevPositionError.code == error.code && prevPositionError.message == error.message) return;
$error.html("Error while retrieving current position. <br/>Error code: " + error.code + "<br/>Message: " + error.message);
if(!$error.is(":visible")){
$error.show();
$results.hide();
}
prevPositionError = {
code: error.code,
message: error.message
};
}
function onCompassUpdate(heading){
prevHeading = currentHeading;
currentHeading = heading.trueHeading >= 0 ? Math.round(heading.trueHeading) : Math.round(heading.magneticHeading);
if(currentHeading == prevHeading) return;
updateHeading();
}
function onCompassError(error){
watchCompass();
if(prevCompassErrorCode && prevCompassErrorCode == error.code) return;
var errorType;
switch(error.code){
case 1:
errorType = "Compass not supported";
break;
case 2:
errorType = "Compass internal error";
break;
default:
errorType = "Unknown compass error";
}
$error.html("Error while retrieving compass heading: "+errorType);
if(!$error.is(":visible")){
$error.show();
$results.hide();
}
prevCompassErrorCode = error.code;
}
function updateDestination(){
destinationPosition = new LatLon($targetLat.val(), $targetLon.val());
updatePositions();
}
function updatePositions(){
if(!currentPosition) return;
if(!$results.is(":visible")){
$results.show();
$error.hide();
}
destinationBearing = Math.round(currentPosition.bearingTo(destinationPosition));
$distance.html(Math.round(currentPosition.distanceTo(destinationPosition)*1000));
$bearing.html(destinationBearing);
updateDifference();
}
function updateHeading(){
$heading.html(currentHeading);
updateDifference();
}
function updateDifference(){
var diff = destinationBearing - currentHeading;
$difference.html(diff);
$arrow.css("-webkit-transform", "rotate("+diff+"deg)");
}
</script>
</head>
<body>
<div id="results">
<div id="arrow"></div>
<div class="text">
<p>Distance to destination: <span id="distance"></span> metres</p>
<p>Bearing to destination: <span id="bearing"></span> degrees</p>
<p>Current heading: <span id="heading"></span> degrees</p>
<p>Difference in heading and bearing: <span id="difference"></span> degrees</p>
</div>
</div>
<p id="error"></p>
<h2>Destination</h2>
<div>
<label for="target-lat">Latitude: </label>
<input id="target-lat" value="50.623966949462" />
</div>
<div>
<label for="target-lon">Longitude: </label>
<input id="target-lon" value="-4.7256830197787" />
</div>
</body>
</html>