電子国土APIを非プラグインモード(ブラウザのみ)で使っていて,はまった点についてまとめています.
電子国土APIの豆知識
2009-10-17 マウスを端に当てたときに自動スクロールする方法を追加しました
2009-05-24 場所から場所へ自動スクロールする方法を追加しました
IE6/7でJavaScriptエラー
[Q]
IE6,IE7で,リロード時やブラウザバックで戻ったときに,電子国土のJavaScript内でJavaScriptエラーが出る
[A]
ページの文字コードが,EUC-JP,UTF-8など,Shift-JIS以外の場合に発生する.
対処としては,電子国土JavaScriptの文字コードを,ページの文字コードに変換して使えばよい.
例えば,電子国土APIはShift_JISのページ専用か?を参照.
単純に,
- webtis.js
- webtis_limited.js
の文字コードを変換するだけでなく,webtis.jsの内容に以下の変更を加える必要があるので注意.
- インクルードしているwebtis_limited.jsのURLを書き換えて,文字コードを変換したwebtis_limited.jsをインクルードさせる
- スクリプトのcharsetを「Shift_JIS」に指定している箇所があるので,そこを新しい文字コード(EUC-JPなど)に置換する
地図上でクリックイベントが取れない
[Q]
ブラウザから地図上でクリックしても,クリックイベントが発生しない
[A]
確かに取れない.leftdown,leftup,moveイベントの組み合わせで実現すれば良い
コード例
var
lastdownpos = ''
;
function
app_main(){
・・・
top.map.event('leftdown'
, 'top.ev_leftdown'
);
top.map.event('move'
, 'top.ev_move'
);
top.map.event('leftup'
, 'top.ev_leftup'
);
}
function
ev_leftdown(x, y) {
var
d = x + " "
+ y;
lastdownpos = d;
}
function
ev_move(x, y) {
lastdownpos = ''
;
}
function
ev_leftup(x, y) {
var
d = x + " "
+ y;
if
(d == lastdownpos) {
ev_click(x, y);
}
}
function
ev_click(x, y) {
alert
("clicked. x="
+ x + ", y="
+ y);
}
カモランド内でも,いくつかのページでクリック処理を実装しています.
2枚以上の地図を同時に表示したい
[Q]
1ページに2枚以上の地図を表示するには,どうすればよい?
[A]
map_obj.htmを読み込むiframeのidとnameを,地図毎に変えれば良い.
また,app_main()による初期化時の横込みタイミングによって例外が発生することがあるので,
例外をcatchして握りつぶす対処を入れておく.
コード例
function
app_main(){
// 詳細マップの初期化
try
{
top.map1.setMapScale(18000);
top.map1.openMap();
} catch
(e) {
}
// 広域マップの初期化
try
{
top.map2.setMapScale(300000);
top.map2.openMap();
} catch
(e) {
}
// 全国マップの初期化
try
{
top.map3.setMapScale(10000000);
top.map3.openMap();
} catch
(e) {
}
}
・・・
<body onunload="map1.doUnload();map2.doUnload();map3.doUnload();"
>
<iframe id="imap3"
name="map3"
width="200"
height="200"
src="map_obj.htm"
scrolling="no"
></iframe>
<iframe id="imap2"
name="map2"
width="200"
height="200"
src="map_obj.htm"
scrolling="no"
></iframe>
<iframe id="imap1"
name="map1"
width="400"
height="400"
src="map_obj.htm"
scrolling="no"
></iframe>
詳しく言うと,app_main()は地図1の初期化,地図2の初期化...という風に地図の枚数と同じ回数呼び出されるが,
例えば最初の地図の初期化で呼び出されたタイミングでは,他の地図は準備ができていないため,app_main()で属性を設定しようとすると必ず例外が発生してしまう.
その例外を握りつぶすためのものである.
カモランド内では,緯度経度取得ツールで3枚の地図を連動させています.
場所から場所へ自動スクロールで移動したい
[Q]
ある場所から次の場所に移動するときに,画面をスクロールして移動するには?
[A]
startScroll()でスクロールを開始して,目的地に着いたらstopScroll()でスクロールを止めればよい.目的地に着いたかどうかの判定は,repaintイベントで行う.
しかしrepaintイベントはそう頻繁に発生するわけではないので,着いたかどうかの判定が多少面倒.
コード例
<script type="text/javascript"
>
var
moving = false
;
var
mov_dir = ''
;
var
to_x;
var
to_y;
var
mov_cnt = 0;
function
app_main(){
top.map.createScaleBar();
top.map.setMapCenter(139.148722, 35.911509, 18000);
top.map.openMap();
top.map.setMouseMode('pan'
);
top.map.event('repaint'
, 'top.ev_repaint'
);
top.map.event('dbclick'
, 'top.ev_dbclick'
);
}
function
ev_repaint(lx, by, rx, ty) {
if
(moving) {
var
x = top.map.getCx();
var
y = top.map.getCy();
if
(mov_dir.indexOf('左'
) >=0 && x <= to_x ||
mov_dir.indexOf('右'
) >=0 && x >= to_x ||
mov_dir.indexOf('上'
) >=0 && y >= to_y ||
mov_dir.indexOf('下'
) >=0 && y <= to_y) {
top.map.stopScroll();
moving = false
;
var
precision = top.map.getMapScale() / 100000000;
if
(Math
.abs(x - to_x) > precision || Math
.abs(y - to_y) > precision) {
if
(++mov_cnt < 10) {
continueMove(to_x, to_y);
} else
{
setPos(to_x, to_y);
}
}
}
}
}
function
ev_dbclick(x, y) {
if
(! moving) {
startMove(x, y);
}
}
function
startMove(x2, y2) {
mov_cnt = 0;
continueMove(x2, y2);
}
function
continueMove(x2, y2) {
var
x1 = top.map.getCx();
var
y1 = top.map.getCy();
var
precision2 = top.map.getMapScale() / 50000000;
mov_dir = ''
if
(Math
.abs(x2 - x1) > precision2) { mov_dir = (x2 > x1)? '右'
: '左'
; }
if
(Math
.abs(y2 - y1) > precision2) { mov_dir += (y2 > y1)? '上'
: '下'
; }
if
(mov_dir != ''
) {
to_x = x2;
to_y = y2;
moving = true
;
top.map.startScroll(mov_dir);
} else
{
setPos(x2, y2);
}
}
function
setPos(x, y) {
top.map.setMapCenter(x, y);
top.map.openMap();
}
</script>
</head>
<body onunload="map.doUnload();"
>
<iframe id="imap"
name="map"
width="350"
height="350"
src="map_obj.htm"
scrolling="no"
></iframe>
<iframe name="message"
style
="display:none"
></iframe>
<ol>
<li><a href="#"
onclick="startMove(139.120889, 35.89518)"
>橋小屋の頭</a>
<li><a href="#"
onclick="startMove(139.113222, 35.911622)"
>鳥首峠</a>
<li><a href="#"
onclick="startMove(139.148722, 35.911509)"
>名郷バス停</a>
</ol>
ミソは,
- ある程度近くに着いたら,スクロールをやめて座標を強制的に設定する
こうしないと,行ったり来たりのスクロールを永遠に繰り返すことに...
自動スクロールは,尾瀬(2008年9月)などの「地図と行程表」で使っています.
また,地図上でダブルクリックすると,その位置が中心になるようにスクロールします.(Google Mapの真似です)
マウスを端に当てたときに自動スクロールしたい
[Q]
マウスを地図の端に当てたときに,その方向に画面をスクロールするには?
例えば,右端の方にマウスを当てると,右方向に地図がスクロールする.
[A]
moveイベントでマウスの位置を調べて,端にあればstartScroll()でスクロールを開始すれば良い.
コード例
// app_main()内に追加する
top.map.event('move'
, 'top.ev_move'
);
// moveイベントのハンドラ
function
ev_move(x, y, k) {
var
dir = ''
;
var
cx = top.map.getCx();
var
cy = top.map.getCy();
var
wx = top.map.getRight() - cx;
var
wy = top.map.getTop() - cy;
if
(x > cx + wx * 0.75) {
dir = '右'
;
} else
if
(x < cx - wx * 0.75) {
dir = '左'
;
}
if
(y > cy + wy * 0.75) {
dir += '上'
;
} else
if
(y < cy - wy * 0.75) {
dir += '下'
;
}
if
(x > cx + wx * 0.95 || x < cx - wx * 0.95 ||
y > cy + wy * 0.95 || y < cy - wy * 0.95) {
dir = ''
;
}
if
(dir != ''
) {
top.map.startScroll(dir);
} else
{
top.map.stopScroll();
}
}