2018年9月26日水曜日

OpenLayers5 Workshop - 2.7 Making it look nice

2 Vector Data
2.7 Making it look nice
見栄えを良くする

At this point we have a feature editor with basic import, editing, and export functionality. But we haven't spent any time trying to make the features look nice. When you create a vector layer in OpenLayers, you get a set of default styles. The editing interactions (draw and modify) also come with their own default styles. You may have noticed how geometries had a thicker stroke during editing. This behavior can be controlled by providing a style option to your vector layer and editing interactions.

このポイントは、基本的なインポートと編集、エクスポート機能があるフィーチャエディタがあります。しかし、フィーチャの見栄えを良くさせる試みに全く時間を使っていません。OpenLayers でベクタレイヤを作成するとき、一連のデフォルトスタイルを取得します。editing インストラクション(draw と modify)も、それら自身のデフォルトスタイルを備えています。ジオメトリは編集中により太いストロークをどのように持っていたか気がついているでしょう。この動作は、ベクタレイヤにスタイルオプションと editing インストラクションを提供することによって制御されます。

Static style
静的スタイル

If we wanted to give all features the same style, we could configure our vector layer like this:

もしすべてのフィーチャに同じスタイルを与えるなら、ベクタレイヤをこのように設定します:
const layer = new VectorLayer({
 source: source,
 style: new Style({
  fill: new Fill({
   color: 'red'
  }),
  stroke: new Stroke({
   color: 'white'
  })
 })
});
It is also possible to set the style property to an array of styles. This allows rendering of a cased line (a wide stroke below and a narrower one on top), for example.

スタイルプロパティをスタイルの配列に設定することも可能です。例えば、台形ライン(下が広く上が狭いストローク)の描画を許可します。

While there isn't really a good justification of it here, for the sake of this exercise we'll take advantage of dynamic styling.

その良い根拠はここには本当にないですが、この演習のために、動的スタイリングの有利な点を使用します。

Dynamic style
動的スタイル

When you want to make decisions about how each feature should get rendered based on something about the feature or the current view resolution, you can configure a vector layer with a style function. This function gets called with each feature at each render frame, so it is important to write an efficient function if you have many features and want to maintain good rendering performance.

各々のフィーチャがフィーチャと現在のビューの投影法を元に描画される方法について決定するとき、ベクタレイヤをスタイル(style)ファンクションで設定できます。このファンクションは各々の描画フレームの各々のフィーチャで呼び出されるので、多くのフィーチャがあり良好な描画パフォーマンスを維持したいなら効率的なファンクションを書くことが重要です。

Here is an example that renders features using one of two styles depending on whether the "name" attribute starts with "A-M" or "N-Z" (a completely contrived example).

ここに "name" 属性が "A-M" または "N-Z" で開始するかによる2つのスタイルの1つを使用してフィーチャを描画する(全く不自然な)例があります。
const layer = new VectorLayer({
 source: source,
 style: function(feature, resolution) {
  const name = feature.get('name').toUpperCase();
  return name < "N" ? style1 : style2; // assuming these are created elsewhere
 }
});
Styling based on geometry area
ジオメトリエリアを元とするスタイリング

To see how dynamic styling works, we'll create a style function that renders features based on the geometry area. To do this, we're going to make use of a colormap package on npm. We can add this to our dependencies like this:

動的スタイリングがどのように動作するかを確認するために、ジオメトリエリアを元とするフィーチャを描画するスタイルファンクションを作成します。これを実行するために、npm の colormap パッケージを使用します。これを依存関係にこのように追加します:

npm install colormap

Now, we need to import the style constructors, the colormap package, and ol/sphere for spherical area calculations.

では、スタイルコンストラクタと colormap パッケージ、球面の計算のための ol/sphere をインポートします。
import {Fill, Stroke, Style} from 'ol/style';
import {getArea} from 'ol/sphere';
import colormap from 'colormap';
Next we'll write a couple functions to determine a color based on the area of a geometry:

次に、ジオメトリの面積をもととする色を決定する対のファンクションを書きます:
const min = 1e8; // the smallest area
const max = 2e13; // the biggest area
const steps = 50;
const ramp = colormap({
 colormap: 'blackbody',
 nshades: steps
});
function clamp(value, low, high) {
 return Math.max(low, Math.min(value, high));
}
function getColor(feature) {
 const area = getArea(feature.getGeometry());
 const f = Math.pow(clamp((area - min) / (max - min), 0, 1), 1 / 2);
 const index = Math.round(f * (steps - 1));
 return ramp[index];
}
And now we can add a function that creates a style with a fill color based on the geometry area. Set this function as the style property of your vector layer:

それでは、ジオメトリの面積をもとに塗りつぶし色(fill color)でスタイルを作成するのファンクションを追加できます。このファンクションをベクタレイヤのスタイルプロパティとして設定します:
const layer = new VectorLayer({
 source: source,
 style: function(feature) {
  return new Style({
   fill: new Fill({
    color: getColor(feature)
   }),
   stroke: new Stroke({
    color: 'rgba(255,255,255,0.8)'
   })
  });
 }
});
Features colored by area

■□ Debian9 で試します■□
「Static style」の例を表示します。前回使用した main.js のバックアップを保存して次のように修正します。

user@deb9-vmw:~/openlayers-workshop-en$ cp main.js main.js_dawnload user@deb9-vmw:~/openlayers-workshop-en$ vim main.js
import 'ol/ol.css';
import GeoJSON from 'ol/format/GeoJSON':
import Map from 'ol/Map';
import VectorLayer from 'ol/layer/Vector';
import VectorSource from 'ol/source/Vector';
import View from 'ol/View';
import DragAndDrop from 'ol/interaction/DragAndDrop';
import Modify from 'ol/interaction/Modify';
import Draw from 'ol/interaction/Draw';
import Snap from 'ol/interaction/Snap';
import sync from 'ol-hashed';
import Style from 'ol/style/Style';
import Fill from 'ol/style/Fill';
import Stroke from 'ol/style/Stroke';
const map = new Map({
 target: 'map-container',
 view: new View({
  center: [0, 0],
  zoom: 2
 })
}); 
sync(map);
const source = new VectorSource();

const layer = new VectorLayer({
 source: source,
 style: new Style({
  fill: new Fill({
   color: 'red'
  }),
  stroke: new Stroke({
   color: 'white'
  })
 })
});
map.addLayer(layer);
map.addInteraction(new DragAndDrop({
 source: source,
 formatConstructors: [GeoJSON]
}));

map.addInteraction(new Modify({
 source: source
}));

map.addInteraction(new Draw({
 type: 'Polygon',
 source: source
}));

map.addInteraction(new Snap({
 source: source
}));
const clear = document.getElementById('clear');
clear.addEventListener('click', function() {
 source.clear();
});
const format = new GeoJSON({featureProjection: 'EPSG:3857'});
const download = document.getElementById('download');
source.on('change', function() {
 const features = source.getFeatures();
 const json = format.writeFeatures(features);
 download.href = 'data:text/json;charset=utf-8,' + json;
});
http://localhost:3000/ とブラウザでマップを開きます。(もし開かなければ、'npm start' を実行してください。


「Dynamic style」の例を表示します。main.js を次のように修正します。

user@deb9-vmw:~/openlayers-workshop-en$ vim main.js
import 'ol/ol.css';
import GeoJSON from 'ol/format/GeoJSON':
import Map from 'ol/Map';
import VectorLayer from 'ol/layer/Vector';
import VectorSource from 'ol/source/Vector';
import View from 'ol/View';
import DragAndDrop from 'ol/interaction/DragAndDrop';
import Modify from 'ol/interaction/Modify';
import Draw from 'ol/interaction/Draw';
import Snap from 'ol/interaction/Snap';
import sync from 'ol-hashed';
import Style from 'ol/style/Style';
import Fill from 'ol/style/Fill';
import Stroke from 'ol/style/Stroke';
const map = new Map({
 target: 'map-container',
 view: new View({
  center: [0, 0],
  zoom: 2
 })
}); 
sync(map);

const source = new VectorSource();
/**
 * const layer = new VectorLayer({
 *  source: source,
 *  style: new Style({
 *   fill: new Fill({
 *    color: 'red'
 *    }),
 *   stroke: new Stroke({
 *    color: 'white'
 *   })
 *  })
 * });
 */
const layer = new VectorLayer({
 source: source,
 style: function(feature, resolution) {
  const name = feature.get('name').toUpperCase();
   return name < "N" ? style1 : style2;
 }
});
const style1 = new Style({
 fill: new Fill({
  color: 'red'
  }),
 stroke: new Stroke({
  color: 'white'
 })
});
const style2 = new Style({
 fill: new Fill({
  color: 'blue'
  }),
 stroke: new Stroke({
  color: 'yellow'
 })
});
map.addLayer(layer);
map.addInteraction(new DragAndDrop({
 source: source,
 formatConstructors: [GeoJSON]
}));

map.addInteraction(new Modify({
 source: source
}));

map.addInteraction(new Draw({
 type: 'Polygon',
 source: source
}));

map.addInteraction(new Snap({
 source: source
}));
const clear = document.getElementById('clear');
clear.addEventListener('click', function() {
 source.clear();
});
const format = new GeoJSON({featureProjection: 'EPSG:3857'});
const download = document.getElementById('download');
source.on('change', function() {
 const features = source.getFeatures();
 const json = format.writeFeatures(features);
 download.href = 'data:text/json;charset=utf-8,' + json;
});
http://localhost:3000/ とブラウザでマップを開きます。


「Styling based on geometry area」の例を表示します。 colormap パッケージをインストールします。

npm install colormap

main.js を次のように修正します。

user@deb9-vmw:~/openlayers-workshop-en$ vim main.js
import 'ol/ol.css';
import GeoJSON from 'ol/format/GeoJSON':
import Map from 'ol/Map';
import VectorLayer from 'ol/layer/Vector';
import VectorSource from 'ol/source/Vector';
import View from 'ol/View';
import DragAndDrop from 'ol/interaction/DragAndDrop';
import Modify from 'ol/interaction/Modify';
import Draw from 'ol/interaction/Draw';
import Snap from 'ol/interaction/Snap';
import sync from 'ol-hashed';
import {Fill, Stroke, Style} from 'ol/style';
import {getArea} from 'ol/sphere';
import colormap from 'colormap'; 
const min = 1e8; // the smallest area
const max = 2e13; // the biggest area
const steps = 50;
const ramp = colormap({
 colormap: 'blackbody',
 nshades: steps
});
function clamp(value, low, high) {
 return Math.max(low, Math.min(value, high));
}
function getColor(feature) {
 const area = getArea(feature.getGeometry());
 const f = Math.pow(clamp((area - min) / (max - min), 0, 1), 1 / 2);
 const index = Math.round(f * (steps - 1));
 return ramp[index];
}
const map = new Map({
 target: 'map-container',
 view: new View({
  center: [0, 0],
  zoom: 2
 })
}); 
sync(map);

const source = new VectorSource();
/**
 * const layer = new VectorLayer({
 *  source: source,
 *  style: new Style({
 *   fill: new Fill({
 *    color: 'red'
 *    }),
 *   stroke: new Stroke({
 *    color: 'white'
 *   })
 *  })
 * });
 */
/**
 * const layer = new VectorLayer({
 *  source: source,
 *  style: function(feature, resolution) {
 *   const name = feature.get('name').toUpperCase();
 *    return name < "N" ? style1 : style2;
 *  }
 * });
 * const style1 = new Style({
 *  fill: new Fill({
 *   color: 'red'
 *   }),
 *  stroke: new Stroke({
 *   color: 'white'
 *  })
 * });
 * const style2 = new Style({
 *  fill: new Fill({
 *   color: 'blue'
 *   }),
 *  stroke: new Stroke({
 *   color: 'yellow'
 *  })
 * });
 */
const layer = new VectorLayer({
 source: source,
 style: function(feature) {
  return new Style({
   fill: new Fill({
    color: getColor(feature)
   }),
   stroke: new Stroke({
    color: 'rgba(255,255,255,0.8)'
   })
  });
 }
});
map.addLayer(layer);
map.addInteraction(new DragAndDrop({
 source: source,
 formatConstructors: [GeoJSON]
}));

map.addInteraction(new Modify({
 source: source
}));

map.addInteraction(new Draw({
 type: 'Polygon',
 source: source
}));

map.addInteraction(new Snap({
 source: source
}));
const clear = document.getElementById('clear');
clear.addEventListener('click', function() {
 source.clear();
});
const format = new GeoJSON({featureProjection: 'EPSG:3857'});
const download = document.getElementById('download');
source.on('change', function() {
 const features = source.getFeatures();
 const json = format.writeFeatures(features);
 download.href = 'data:text/json;charset=utf-8,' + json;
});
http://localhost:3000/ とブラウザでマップを開きます。


0 件のコメント: