2011年02月28日
Google Maps をジオラマ風にしてみた
Google Maps をジオラマ写真風にすると印象が変わる、というアイディアが チルトシフトの新しい使い方 その2 に書いてあった。
おもしろそうなのでリアルタイムに Google Maps をジオラマ風に表示するものを作ってみた。
好きな場所を表示できるので、地球全体がジオラマになってしまった。
簡単な使い方:
- 上部の検索欄に英語で入力して移動
- 左のコントロールは Google Maps と同じ
- Shift+ドラッグで視点移動
日本各地を巡ってみた
東京駅前
車がミニチュア風でかわいい。

京都御所
箱庭になりました。

大阪駅上空
線路と高速道路とビル群。鉄道模型みたい。

どうぞご利用ください
あなたの街をジオラマ風に!
ソースコード
チルトシフトのエフェクトは「彩度をあげる」「周りをぼかす」「周りを暗くする」ことで実現している。
ソースコードは以下に(map_1_20.swc、minimalcomps、Tweener を利用)。
// Diorama Google Maps
//-------------------------------------------------------------------
// This flash changes google maps to tilt-shift photography.
// inspired by http://reinit.info/blog/archive/2011/02/23/tiltshift_2/
package {
import flash.events.*;
import flash.display.*;
import flash.geom.*;
import flash.filters.*;
import com.google.maps.*;
import com.google.maps.geom.*;
import com.google.maps.controls.*;
import com.google.maps.services.*;
import com.bit101.components.*;
import caurina.transitions.Tweener;
public class DioramaGoogleMaps extends Sprite {
private static var WIDTH:Number = 475;
private static var HEIGHT:Number = 475;
private static var BLUR_PARAM:Number = 160;
private static var CONTROL_ALPHA:Number = 0.3;
private var maps:Array = [];
private var controls:Sprite;
public function DioramaGoogleMaps():void {
stage.scaleMode = "noScale";
stage.align = "TL";
stage.stageFocusRect = false;
// blurred map
var map1:Map3D = createMap(true);
map1.filters = [new BlurFilter(6, 6), getSaturationFilter(2.8)];
addChild(map1);
// normal map
var map2:Map3D = createMap(false);
map2.filters = [getSaturationFilter(1.8)];
map2.cacheAsBitmap = true;
addChild(map2);
var msk:Sprite = new Sprite();
msk.graphics.beginFill(0);
msk.graphics.drawEllipse(-WIDTH * 0.5, -HEIGHT * 0.3, WIDTH * 1.0, HEIGHT * 0.6);
msk.graphics.endFill();
msk.x = WIDTH * 0.5
msk.y = HEIGHT * 0.5
msk.filters = [new BlurFilter(BLUR_PARAM, BLUR_PARAM)];
msk.cacheAsBitmap = true;
addChild(msk);
map2.mask = msk;
maps = [map1, map2];
// limb darkening
filters = [new GlowFilter(0, 0.3, BLUR_PARAM, BLUR_PARAM, 1, 1, true)];
// add control
initControl();
}
private function initControl():void{
controls = new Sprite();
var search:Sprite = new Sprite();
search.x = 240; search.y = 10;
search.scaleX = search.scaleY = 1.5;
// text
var txt:InputText = new InputText(controls, 0, 0);
txt.width = 100;
txt.addEventListener("keyDown", function(event:KeyboardEvent):void{
if (event.keyCode == 13) { btn.dispatchEvent(new Event("click")); }
});
search.addChild(txt);
// button
var btn:PushButton = new PushButton(search, 100, 0, "Search", function(event:Event):void{
var geo:ClientGeocoder = new ClientGeocoder();
geo.geocode(txt.text);
geo.addEventListener("geocodingsuccess", function(event:GeocodingEvent):void{
var marks:Array = event.response.placemarks;
var map:Map3D = maps[0] as Map3D;
if (marks.length > 0){
map.flyTo(marks[0].point, 15, new Attitude(20, 30, 0), 1);
}
});
geo.addEventListener("geocodingfailure", function(event:GeocodingEvent):void{
txt.text = "NOT FOUND";
});
});
btn.width = 50; btn.height = txt.height;
controls.addChild(search);
addChild(controls);
controls.alpha = CONTROL_ALPHA;
controls.addEventListener("mouseOver", function(event:Event):void { Tweener.addTween(controls, {alpha: 0.9, time: 0.5 }); });
controls.addEventListener("mouseOut", function(event:Event):void { Tweener.addTween(controls, {alpha: CONTROL_ALPHA, time: 0.5 }); })
}
// create a map
private function createMap(isBlur:Boolean):Map3D{
var map:Map3D = new Map3D();
map.key = "ABQIAAAA6de2NwhEAYfH7t7oAYcX3xRWPxFShKMZYAUclLzloAj2mNQgoRQZnk8BRyG0g_m2di3bWaT-Ji54Lg";
map.sensor = "false";
map.setSize(new Point(WIDTH, HEIGHT));
map.addEventListener(MapEvent.MAP_PREINITIALIZE, function(event:Event):void{
map.setInitOptions(new MapOptions({
zoom: 16.6,
center: new LatLng(48.873847, 2.29502),
mapType: MapType.SATELLITE_MAP_TYPE,
viewMode: View.VIEWMODE_ORTHOGONAL,
attitude: new Attitude(20, 30, 0),
doubleClickMode: MapAction.ACTION_PAN_ZOOM_IN,
mouseClickRange: 2
}));
});
map.addEventListener(MapEvent.MAP_READY, function(event:Event):void{
if (!isBlur){
var control:NavigationControl = new NavigationControl(new NavigationControlOptions({
position: new ControlPosition(ControlPosition.ANCHOR_TOP_LEFT, 5)
}));
map.addControl(control);
// move to control sprite
var obj:DisplayObject = control.getDisplayObject();
if (obj.parent){
obj.parent.removeChild(obj);
controls.addChild(obj);
}
}
});
map.addEventListener("mapevent_movestep", changeHandler);
map.addEventListener("mapevent_moveend", changeHandler);
map.addEventListener("mapevent_zoomend", changeHandler);
map.addEventListener("mapevent_attitudechangeend", changeHandler);
map.addEventListener("mapevent_attitudechangestep", changeHandler);
return map;
}
// sync two map
private function changeHandler(event:Event):void{
if(maps.length != 2) return;
var me:Map3D = event.target as Map3D;
var other:Map3D = (me == maps[0] ? maps[1] : maps[0]) as Map3D;
var c1:LatLng = me.getCenter();
var z1:Number = me.getZoom();
var a1:Attitude = me.getAttitude();
if(!c1.equals(other.getCenter())){
other.setCenter(c1);
}
if(z1 != other.getZoom()){
other.setZoom(z1);
}
if(!a1.equals(other.getAttitude())){
other.setAttitude(a1)
}
}
private static var LUMINANCE_R:Number = 0.212671;
private static var LUMINANCE_G:Number = 0.715160;
private static var LUMINANCE_B:Number = 0.072169;
private function getSaturationFilter(saturation:Number):BitmapFilter{
var sf:Number = saturation;
var nf:Number = 1-sf;
var nr:Number = LUMINANCE_R * nf;
var ng:Number = LUMINANCE_G * nf;
var nb:Number = LUMINANCE_B * nf;
return new ColorMatrixFilter([
nr+sf, ng, nb, 0, 0,
nr, ng+sf, nb, 0, 0,
nr, ng, nb+sf, 0, 0,
0, 0, 0, 1, 0
]);
}
}
}