<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>超巨大富士山AR - 10m固定版</title>
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
<script src="https://aframe.io/releases/1.5.0/aframe.min.js"></script>
<script src="https://raw.githack.com/AR-js-org/AR.js/master/aframe/build/aframe-ar-nft.js"></script>
<style>
#info {
position: fixed;
top: 10px;
left: 10px;
background: rgba(0,0,0,0.8);
color: white;
padding: 15px;
font-family: sans-serif;
font-size: 14px;
z-index: 9999;
border-radius: 5px;
}
</style>
</head>
<body style="margin: 0; overflow: hidden;">
<div id="info">
🗻 富士山の方向:西南西<br>
📍 位置情報取得中...
</div>
<a-scene
id="ar-scene"
vr-mode-ui="enabled: false"
renderer="logarithmicDepthBuffer: true"
arjs='sourceType: webcam;
sourceWidth:1280; sourceHeight:960;
displayWidth: 1280; displayHeight: 960;
debugUIEnabled: false;
trackingMethod: best;
videoTexture: true;'
device-orientation-permission-ui
loading-screen="enabled: false"
embedded>
<a-camera
id="camera"
gps-new-camera="gpsMinDistance: 5"
look-controls="magicWindowTrackingEnabled: false;"
far="1000000"> </a-camera>
<a-entity id="fujisan-ar-container">
<a-cone
material="color: #ff6b6b; opacity: 0.9"
radius-bottom="2"
radius-top="0.4"
height="3"
position="0 0 -10"
rotation="0 0 0">
</a-cone>
<a-cone
material="color: white; opacity: 0.9"
radius-bottom="1"
radius-top="0.2"
height="1.5"
position="0 1.5 -10"
rotation="0 0 0">
</a-cone>
<a-text value="富士山 AR (固定表示)" position="0 3 -10" align="center" color="white" scale="1 1 1"></a-text>
</a-entity>
</a-scene>
<script>
const infoDiv = document.getElementById('info');
const fujiAR = document.getElementById('fujisan-ar-container');
// 富士山の現実の座標
const fujiLat = 35.360556;
const fujiLon = 138.727778;
// 2点間の距離を計算(Haversine formula)
function calcDistance(lat1, lon1, lat2, lon2) {
const R = 6371; // 地球の半径(km)
const dLat = (lat2 - lat1) * Math.PI / 180;
const dLon = (lon2 - lon1) * Math.PI / 180;
const a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) *
Math.sin(dLon/2) * Math.sin(dLon/2);
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
return R * c;
}
// 方角を計算
function calcBearing(lat1, lon1, lat2, lon2) {
const dLon = (lon2 - lon1) * Math.PI / 180;
const y = Math.sin(dLon) * Math.cos(lat2 * Math.PI / 180);
const x = Math.cos(lat1 * Math.PI / 180) * Math.sin(lat2 * Math.PI / 180) -
Math.sin(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) * Math.cos(dLon);
const bearing = Math.atan2(y, x) * 180 / Math.PI;
return (bearing + 360) % 360;
}
// 方角を日本語に変換
function bearingToJapanese(bearing) {
const directions = ['北', '北北東', '北東', '東北東', '東', '東南東', '南東', '南南東',
'南', '南南西', '南西', '西南西', '西', '西北西', '北西', '北北西'];
const index = Math.round(bearing / 22.5) % 16;
return directions[index];
}
if (navigator.geolocation) {
navigator.geolocation.watchPosition(
(position) => {
const lat = position.coords.latitude;
const lon = position.coords.longitude;
const acc = position.coords.accuracy.toFixed(1);
const distance = calcDistance(lat, lon, fujiLat, fujiLon).toFixed(1);
const bearing = calcBearing(lat, lon, fujiLat, fujiLon);
const direction = bearingToJapanese(bearing);
// 修正点 2: 富士山ARオブジェクトの回転を計算し、カメラのY軸回転を設定
// 富士山ARオブジェクトはカメラから10m前に固定されているため、
// カメラ自体を富士山の方向(bearing)に回転させることで、ARオブジェクトが正しい方向に見えるようにする。
// (bearing - 180) はカメラが向くべき方向(オブジェクトの逆方向)を計算
const cameraRotationY = (bearing - 180) % 360;
document.getElementById('camera').setAttribute('rotation', `0 ${cameraRotationY} 0`);
infoDiv.innerHTML = `
🗻 <strong>富士山AR (10m固定)</strong><br>
<br>
📍 現在地<br>
緯度: ${lat.toFixed(6)}<br>
経度: ${lon.toFixed(6)}<br>
精度: ${acc}m<br>
<br>
🎯 富士山まで<br>
距離: <strong>${distance}km</strong><br>
方角: <strong>${direction}</strong> (${bearing.toFixed(0)}°)<br>
<br>
👀 <strong>富士山は常に10m先に表示中</strong>
`;
},
(error) => {
infoDiv.innerHTML = `❌ エラー: ${error.message}<br><br>設定→Safari(Chrome)→位置情報を許可`;
},
{
enableHighAccuracy: true,
maximumAge: 0,
timeout: 5000
}
);
}
// A-Frameの読み込み完了を確認
document.querySelector('a-scene').addEventListener('loaded', () => {
console.log('AR Scene loaded successfully');
});
</script>
</body>
</html>