2014年9月9日火曜日

OpenLayers 3 を使ってみよう (その2:地図の不透明度を変える)

これはOpenLayers 3 を使ってみよう(その1:マウスクリックのイベント処理)からの続きである。
OpenLayers 3 を使ってみよう(その0:はじめに:地理院地図を表示)に目次がある。
ここでは OpenLayers 3.7.0 を使っている。
 前回(その1:マウスクリックのイベント処理)では, マウスをクリックした際のイベント処理の方法を記述した。
今回は地図画像の不透明度(Opacity)を変える方法を示そう。

 地図の不透明度を変えるには,地図を構成している layer(ここでは cyberJ という変数で定義された Tile Layer)の不透明度を変えればよい。 そのためここでは layer の変数 cyberJ をグローバルに定義(init_map() 関数の外で定義)している。ちなみに不透明度(opacity)は,0.0~1.0 の間の数値を取らなければならない。

 まず,いつものように以下に web ページのソースを載せる。 ここでは前回からの変更箇所の色を変えている。 説明はソースコードに下に書こう。
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta http-equiv="content-style-type" content="text/css">
<meta http-equiv="content-script-type" content="text/javascript">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<link rel="stylesheet" href="http://openlayers.org/en/v3.7.0/css/ol.css" type="text/css">
<script src="http://openlayers.org/en/v3.7.0/build/ol.js" type="text/javascript"></script>
<style type="text/css">
   div.fill {width: 100%; height: 100%;}
   body {padding: 0; margin: 0}
   html, body, #map {height: 100%; width: 100%;}

   .ol-attribution {
     padding: 3px;  position: absolute;  background-color:#ffffff;
     background-color:rgba(230,255,255,0.7);
     right: 3px;  bottom:5px;  font-size:12px;
   }
   .ol-attribution ul { padding: 0px;  line-height: 14px;  margin: 0px; }
   .ol-attribution li { line-height: inherit;  display: inline;  list-style: none outside none; }

   .ol-zoom .ol-zoom-out { margin-top: 202px; }
   .ol-zoomslider { background-color: transparent; top: 2.3em; }
   .ol-touch .ol-zoom .ol-zoom-out { margin-top: 212px; }
   .ol-touch .ol-zoomslider { top: 2.75em; }
</style>
<title>OpenLayers 3 Example: Change Opacity</title>
<script src="ol3ex2.js" type="text/javascript"></script>
</head>

<body onload="init_map()">
  <div id="map_canvas" style="float:left; width:76%; height:100%;"></div>
  <div id="control_panel" style="float:right;width:24%;text-align:left;padding-top:10px;font-size:85%">
    <div style="font-size:100%">
      &nbsp;不透明度:<a title="decrease opacity" href="javascript: directSetOpacity(0.1);">0.1</a> 
      <a title="decrease opacity" href="javascript: directSetOpacity(0.5);">0.5</a> 
      <a title="decrease opacity" href="javascript: directSetOpacity(1.0); ">1.0</a><br>

      &nbsp;<b>不透明度 Δ=±0.2:
      <a title="decrease opacity" href="javascript: changeOpacity(-0.2);">&lt;&lt;</a>
      <span id="opacity_control"></span>
      <a title="increase opacity" href="javascript: changeOpacity(0.2);">&gt;&gt;</a></b>
      <br>
      &nbsp;clicked coordinate:<span id="outStr"></span>
    </div>
  </div>
</body>
</html>
 今回は Opacity(不透明度)を変更できるようにしたいので,クリックで不透明度が変えられるようにしている。 そのため,地図の描画領域を web ページの左側 76% にし,右に文字を書くスペースを確保している。 また web の要素から directSetOpacity(); と changeOpacity(); という関数を呼び出している。 これらの関数は以下に示す ol3ex2.js の中で定義されている。

 次に JavaScript を載せよう。ここでも変更箇所の色を変え,説明は web ページのソースと同じくこの下に書いておく。
// ===================================================================
var cyberJ = null;   // 地理院地図用の変数

var center_lon = 135.100303888; // 中心の経度(須磨浦公園)
var center_lat = 34.637674639; // 中心の緯度(須磨浦公園)

var initZoom = 10; // ズームの初期値
var MinZoom  = 6;   // ズームの最小値(最も広い範囲)
var MaxZoom  = 17;  // ズームの最大値(最も狭い範囲)
var initPrecision = 8; // 座標表示の小数点以下の桁数の初期値

var initOpacity = 1.0; // 不透明度の初期値
var gMaxOpacity = 1.0; // 不透明度の最大値
var gMinOpacity = 0.0; // 不透明度の最小値
// *******************************************************************
function init_map() {
// 表示用の view 変数の定義。
    var view = new ol.View({ projection: "EPSG:3857",
        maxZoom: MaxZoom,
        minZoom: MinZoom
   })

// cyberJ(地理院地図)用の変数
    cyberJ = new ol.layer.Tile({
        opacity: initOpacity,
        source: new ol.source.XYZ({
            attributions: [ new ol.Attribution({ html: "<a href='http://maps.gsi.go.jp/development/ichiran.html' target='_blank'>国土地理院</a>" }) ],
            url: "http://cyberjapandata.gsi.go.jp/xyz/std/{z}/{x}/{y}.png",
            projection: "EPSG:3857"
        })
    })

// 地図変数 (map 変数) の定義。地理院地図を表示するように指定している。
    var map = new ol.Map({
        target: document.getElementById('map_canvas'),
        layers: [cyberJ],
        view: view,
        renderer: ['canvas', 'dom'],
        controls: ol.control.defaults().extend([new ol.control.ScaleLine()]),
        interactions: ol.interaction.defaults()
    });

// 地図をクリックした際に,座標を書き出す。小数点以下の桁数は initPrecision で指定。メルカトル座標 (EPSG:3857) を WGS84 (EPSG:4326) に変換している。
    map.on('click', function(evt) {
      var coordinate = evt.coordinate;
      var stringifyFunc = ol.coordinate.createStringXY(initPrecision);
      var outstr = stringifyFunc(ol.proj.transform(coordinate, "EPSG:3857", "EPSG:4326"));
      document.getElementById('outStr').innerHTML = outstr;
    });

// zoom slider の追加
    map.addControl(new ol.control.ZoomSlider());

// 中心の指定。view に対して指定。transform を忘れないこと。
    view.setCenter(ol.proj.transform([center_lon, center_lat], "EPSG:4326", "EPSG:3857"));

// zoom の指定。view に対して指定する。
    view.setZoom(initZoom);

// span opacity_control (地理院地図の不透明度) に初期値(実数)を入れる。
    document.getElementById('opacity_control').innerHTML = initOpacity.toFixed(1);
} // function init_map()
// ===================================================================
// 地理院地図 (var cyberJ) の opacity(この場合は不透明度) を変える
// DOM の指定で,document.getElementById('opacity_control').innerHTML とすると,うまくいかず。jQuery と干渉してのかな?
function changeOpacity(opacity) {
    var newOpacity = (parseFloat(document.getElementById('opacity_control').innerHTML) + opacity).toFixed(1); // 新しい opacity の値を求める
    newOpacity = Math.min(gMaxOpacity, Math.max(gMinOpacity, newOpacity)); // 最大値と最小値の範囲を超えないように
    cyberJ.setOpacity(newOpacity); // 地理院地図の opacity の変更
    document.getElementById('opacity_control').innerHTML = newOpacity.toFixed(1); // opacity の数字の表示書き換え
}

function directSetOpacity(opacity) {
    cyberJ.setOpacity(opacity);
    document.getElementById('opacity_control').innerHTML = opacity.toFixed(1);
}
// *******************************************************************
 変更点としては,
 (1) 変数定義の所で,cyberJ,initOpacity,gMaxOpacity,gMinOpacity を定義している。
    cyberJ は,init_map() 関数の外にある changeOpacity() 関数や directSetOpacity() 関数で使えるように
    global な変数として定義してある。中身は init_map() の中で設定するので,ここでは null として定義してある。

 (2) init_map() 関数の中の cyberJ 変数の定義が「var cyberJ = ...」から「cyberJ = ...」となり「var」がなくなっている。
    これは,cyberJ 変数がこれより手前で global に定義されているので,ここでは「var」はつけてはいけないためである。
    また,cyberJ の定義の中に「opacity(不透明度)」の設定が追加されている。

 (3) init_map() 関数の最後の方で「id = 'opacity_control'」の web 要素(span 要素)に不透明度の初期値を書き込んでいる。
    span 要素の場合は「document.getElementById('xxx').innerHTML = 文字列」のように書き込む。
    また,数字は小数点以下1桁にするために「toFixed() 関数」を用いている。

 (4) init_map() 関数の外で「changeOpacity() 関数」と「directSetOpacity() 関数」を定義している。
    それぞれ「cyberJ.setOacity() 関数」を使って Tile Layer の不透明度を変え,結果として地図の不透明度を変えている。
    changeOpacity() 関数では,Opacity が指定した最大値と最小値を超えないようにしている。

 「その2」のサンプルを具体的な web ページとして用意したので,具体的な表示を見てみて欲しい。(ちなみにサンプルページはアクセスログを取るルーチンを組み込んでいます)

その3:地図上に折線を引くに続く

0 件のコメント: