Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
branch: master
Fetching contributors…

Cannot retrieve contributors at this time

executable file 452 lines (356 sloc) 13.434 kb
<!DOCTYPE HTML>
<html lang="en">
<head>
<title>MAPS</title>
<meta charset="utf-8">
<style type="text/css">
*{ margin: 0; padding: 0 }
body {
background-color: #000000;
margin: 0px;
overflow: hidden;
}
a{ color: inherit }
a:hover{ color: black }
header{ position: absolute; left: 0; top: 0; height: 50px; right: 0; padding: 5px; background-color: #aaa;
background: -moz-radial-gradient(circle, #eee, #aaa);
background: -webkit-gradient(radial, center center, 0, center center, 460, from(#eee), to(#aaa));
background: -webkit-radial-gradient(circle, #eee, #aaa);
text-shadow: 0 1px 0 rgba( 255, 255, 255, .8 );
font: normal 12px/14px tahoma; color: #444
}
input[type=submit], input[type=text]{ font: normal 12px/12px tahoma, sans-serif; padding: 3px 10px }
input[type=text]:focus{ width: 20em }
#map{ position: absolute; left: 0; top: 60px; width: 400px; height: 100%; bottom: 0 }
#pano{ position: absolute; left: 400px; top: 60px; bottom: 0; right: 0 }
#frame{ position: absolute; left: 400px; top: 60px; bottom: 0; right: 0; -moz-box-shadow: inset 0 0 20px #000; -webkit-box-shadow:inset 0 0 20px #000; z-index: 1000 }
#texture{ display: none }
#map_settings{ position: absolute; right: 5px; top: 5px; text-align: right }
.settings *{float: left }
.settings span{ padding: 6px 5px }
.settings input[type=radio]{ margin-left: 10 px }
#pano_settings{ position: absolute; right: 10px; top: 30px; text-align: right }
#status{ position: absolute; top: 0px; left: 350px; margin: 10px }
#title{ position: absolute; top: 5px; left: 10px }
h1{ font: normal 18px/24px tahoma, sans-serif; color: black }
h2{ font: normal 18px/14px tahoma, sans-serif }
</style>
</head>
<body>
<header>
<div id="title">
<h1>clickto<b>release</b></b> | <a href="http://twitter.com/thespite" >@thespite</a></h1>
<h2>webgl | <a href="https://github.com/mrdoob/three.js">three.js</a> google street viewer</h2>
<p style="display:none"><span id="fps" ></span> FPS</p>
</div>
<div id="status" >
<div id="message" ></div>
<div id="error" ></div>
</div>
<div id="map_settings" class="settings">
<span>Search for address:</span>
<form id="map_form">
<input type="text" name="address" id="address" />
<input type="submit" value="Search" id="searchButton" />
</form>
<span>or</span>
<input type="submit" value="Use my location" id="myLocationButton" />
</div>
<div id="pano_settings" class="settings">
<span>Change zoom/quality (each tile is 512x512):</span>
<form id="pano_form" style="margin-top: 6px">
<input type="radio" name="scale" value="1" id="scale1"></input> <label for="scale1">1 (2 tiles)</label>
<input type="radio" name="scale" value="2" checked="checked" id="scale2"></input> <label for="scale2">2 (8 tiles)</label>
<input type="radio" name="scale" value="3" id="scale3"></input> <label for="scale3">3 (32 tiles)</label>
<input type="radio" name="scale" value="4" id="scale4"></input> <label for="scale4">4 (128 tiles!)</label>
</form>
</div>
</header>
<div id="map"></div>
<div id="pano" ></div>
<div id="frame" ></div>
<script type="text/javascript" src="js/Tween.js"></script>
<script type="text/javascript" src="js/Three.js"></script>
<script type="text/javascript" src="js/FPS.js"></script>
<script type="text/javascript" src="js/RequestAnimationFrame.js"></script>
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
<script type="text/javascript">
var map;
var canvas;
var ctx;
var marker = null;
var container, mesh, renderer, camera, frame;
var fov = 70;
var lat = 0, lon = 0;
var zoom;
var geocoder;
var error;
var message;
var cd = new Date();
var time = cd.getTime();
var position = { x: 0, y: 0 }
if (!('bind' in Function.prototype)) {
Function.prototype.bind= function(owner) {
var that= this;
var args= Array.prototype.slice.call(arguments, 1);
return function() {
return that.apply(owner,
args.length===0? arguments : arguments.length===0? args :
args.concat(Array.prototype.slice.call(arguments, 0))
);
};
};
}
var isWebGL = false;
function adaptTextureToZoom() {
canvas.width = 416 * Math.pow( 2, zoom );
canvas.height = ( 416 * Math.pow( 2, zoom - 1 ) );
// .55 planet
// .85 elevated
texture = new THREE.Texture( canvas );
texture.minFilter = THREE.LinearFilter;
texture.magFilter = THREE.LinearFilter;
texture.needsUpdate = true
mesh.materials[ 0 ].map = texture;
}
function initialize() {
canvas = document.createElement( 'canvas' );
ctx = canvas.getContext( '2d' );
container = document.getElementById( 'pano' );
frame = document.getElementById( 'frame' );
camera = new THREE.Camera( fov, window.innerWidth / window.innerHeight, 1, 1100 );
scene = new THREE.Scene();
try {
isWebGL = !!window.WebGLRenderingContext && !!document.createElement('canvas').getContext('experimental-webgl');
}catch(e){
}
if( isWebGL ) renderer = new THREE.WebGLRenderer();
else renderer = new THREE.CanvasRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
var faces = 50;
if( !isWebGL ) faces = 12;
mesh = new THREE.Mesh( new THREE.Sphere( 500,faces,faces ), new THREE.MeshBasicMaterial( { wireframe: false, map: THREE.ImageUtils.loadTexture( 'disturgb.jpg' ) } ) );
mesh.scale.x = -1;
if( !isWebGL ) mesh.overdraw = true;
scene.addObject( mesh );
container.appendChild( renderer.domElement );
var myLatlng = new google.maps.LatLng(51.507887908892954,-0.11672961132808268);
var myOptions = {
zoom: 14,
center: myLatlng,
mapTypeId: google.maps.MapTypeId.ROADMAP,
streetViewControl: false
}
map = new google.maps.Map(document.getElementById("map"), myOptions);
google.maps.event.addListener(map, 'click', function(event) {
addMarker(event.latLng);
});
geocoder = new google.maps.Geocoder();
if( isWebGL ) {
frame.addEventListener( 'mousedown', onDocumentMouseDown, false );
} else {
frame.style.display = 'none';
pano.addEventListener( 'mousedown', onDocumentMouseDown, false );
}
window.addEventListener( 'mousemove', onDocumentMouseMove, false );
window.addEventListener( 'mouseup', onDocumentMouseUp, false );
window.addEventListener( 'resize', onWindowResized, false );
frame.addEventListener( 'mousewheel', onDocumentMouseWheel, false );
frame.addEventListener( 'DOMMouseScroll', onDocumentMouseWheel, false);
onWindowResized( null );
var el = document.getElementById( 'myLocationButton' );
el.addEventListener( 'click', function( event ) {
event.preventDefault();
navigator.geolocation.getCurrentPosition(function(position) {
var currentLocation = new google.maps.LatLng( position.coords.latitude, position.coords.longitude );
map.panTo( currentLocation );
addMarker( currentLocation );
});
}, false );
el = document.getElementById( 'searchButton' );
el.addEventListener( 'click', function( event ) {
event.preventDefault();
findAddress( document.getElementById("address").value );
}, false );
errorDiv = document.getElementById( 'error' );
messageDiv = document.getElementById( 'message' );
showMessage( 'Ready. <b>Click a street in the map.</b>' );
addMarker( myLatlng );
animate();
}
window.addEventListener( 'load', initialize, false );
function findAddress( address ) {
showMessage( 'Getting coordinates...' );
geocoder.geocode( { 'address': address}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
map.setCenter(results[0].geometry.location);
showMessage( 'Address found.' );
addMarker( results[0].geometry.location );
} else {
showError("Geocode was not successful for the following reason: " + status);
}
});
}
function showError( message ) {
errorDiv.innerHTML = message;
}
function showMessage( message ) {
showError('');
messageDiv.innerHTML = message;
}
function onWindowResized( event ) {
renderer.setSize( container.clientWidth, container.clientHeight );
camera.projectionMatrix = THREE.Matrix4.makePerspective( fov, container.clientWidth / container.clientHeight, 1, 1100 );
}
var isUserInteracting = false;
var onPointerDownPointerX, onPointerDownPointerY, onPointerDownLon, onPointerDownLat;
function onDocumentMouseDown( event ) {
event.preventDefault();
isUserInteracting = true;
onPointerDownPointerX = event.clientX;
onPointerDownPointerY = event.clientY;
onPointerDownLon = lon;
onPointerDownLat = lat;
}
function onDocumentMouseMove( event ) {
if ( isUserInteracting ) {
lookSpeed = .15;
var f = fov / 500;
var dx = ( onPointerDownPointerX - event.clientX ) * f;
var dy = ( event.clientY - onPointerDownPointerY ) * f;
var olon = lon; var olat = lat;
position.x = dx + onPointerDownLon;
position.y = dy + onPointerDownLat;
}
}
function onDocumentMouseWheel( event ) {
event = event ? event : window.event;
var nfov = fov - ( event.detail ? event.detail * -5 : event.wheelDelta / 8 );
var tween = new TWEEN
.Tween( window )
.to( { fov: nfov }, 200 )
.easing(TWEEN.Easing.Cubic.EaseInOut)
.onUpdate( function() {
camera.projectionMatrix = THREE.Matrix4.makePerspective( fov, container.clientWidth / container.clientHeight, 1, 1100 );
} )
.start();
}
function update() {
console.debug( position );
}
function onDocumentMouseUp( event ) {
isUserInteracting = false;
}
function addMarker(location) {
console.log('addMarker(%o)',location);
if( marker ) marker.setMap( null );
marker = new google.maps.Marker({
position: location,
map: map
});
marker.setMap( map );
loadPanorama( location );
}
var panoramas = [];
var circle = null;
var copyright;
function loadPanorama( location ) {
var values = document.forms[ 'pano_form' ].scale;
for( i = 0, m = values.length; i < m; i++ ) {
if( values[ i ].checked == true ) zoom = values[ i ].value;
}
adaptTextureToZoom();
showMessage( 'Loading panorama for zoom ' + zoom + '...' );
copyright = '';
if( circle ) circle.setMap( null );
panoramas = [];
var panoClient = new google.maps.StreetViewService();
panoClient.getPanoramaByLocation( location, 50, function( result, status ) {
if (status == google.maps.StreetViewStatus.OK) {
showMessage( 'Panorama OK. Loading and composing tiles...' );
copyright = result.copyright;
composePanorama( result.location.pano, zoom );
console.log( result );
circle = new google.maps.Circle( {
map: map,
radius: 2,
center: result.location.latLng,
strokeColor: "#FF0000",
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: "#FF0000",
fillOpacity: 0.35
} );
} else {
showError("Could not retrieve panorama for the following reason: " + status);
}
} );
}
function composeFromTile( x, y, img ) {
ctx.drawImage( img, x * 512, y * 512 );
texture.needsUpdate = true;
count++;
var p = Math.round( count * 100 / total );
showMessage( 'Loading and composing tiles ' + p + '%' );
if( count == total ) {
showMessage( 'Panorama tiles loaded. <b>Click and drag the panorama viewer</b>' );
showError( 'The images are ' + copyright );
} else processQueue();
}
var count = 0;
var total = 0;
var queue = [];
function composePanorama( id, zoom ) {
queue = [];
// 512 x 512
var w = Math.pow( 2, zoom );
var h = Math.pow( 2, zoom - 1 );
count = 0;
total = 0;
for( var y = 0; y < h; y++ ) {
for( var x = 0; x < w; x++ ) {
var url = 'http://maps.google.com/cbk?output=tile&panoid=' + id + '&zoom=' + zoom + '&x=' + x + '&y=' + y;
//queue.push( { url: url, x: x, y: y } );
var img = new Image();
img.onload = composeFromTile.bind( null, x, y, img );
img.src = url;
total++;
}
}
processQueue();
}
function processQueue() {
if( queue.length ) {
var e = queue.pop();
var img = new Image();
img.onload = composeFromTile.bind( null, e.x, e.y, img );
img.src = e.url;
}
}
function animate() {
requestAnimationFrame( animate );
render();
}
var ellapsedTime;
function render() {
var cd = new Date();
ctime = cd.getTime();
ellapsedTime = ( ctime - time );
ellapsedFactor = ellapsedTime / 16;
var olon = lon, olat = lat;
var s = .15 * ellapsedFactor;
lon = lon + ( position.x - olon ) * s;
lat = lat + ( position.y - olat ) * s;
lat = Math.max( - 85, Math.min( 85, lat ) );
phi = ( 90 - lat ) * Math.PI / 180;
theta = lon * Math.PI / 180;
camera.target.position.x = 500 * Math.sin( phi ) * Math.cos( theta );
camera.target.position.y = 500 * Math.cos( phi );
camera.target.position.z = 500 * Math.sin( phi ) * Math.sin( theta );
renderer.render( scene, camera );
fps.tick();
time = ctime;
}
</script>
</body>
</html>
Jump to Line
Something went wrong with that request. Please try again.