さて、本日も ArcGIS API for JavaScript について書いてみようと思います。今回はグラフィックを使ってジオメトリを作図してみようと思います。ただ、単純にグラフィックを使ってジオメトリを作図するだけなので、属性を付与したり、作図したジオメトリを保存したりはしません。一時作図のようなイメージでしょうか。
今回使用するソース
前回のエントリーをベースに今回使用する処理を書き足そうと思います。
www.gis-py.com
完成イメージ
作図ボタンを追加しました。
作図ボタンを押すとこのようにセレクトボックスが表示されます。作図するジオメトリの種類を選んで実行ボタンを押すと作図ができるようになります。
実行環境
ArcGIS API for JavaScript 4.13
Chrome
ポイントとなる処理
簡単にではありますが、以下の実装について解説していきます。
1.Draw クラスとGraphic クラスを使用
2.実行ボタン押下時の処理
3.ポイントの作図
4.ラインの作図
5.ポリゴンの作図
6.テキストの作図
Draw クラスとGraphic クラスを使用
今回の要件を満たすには Draw クラスとGraphic クラスを使用する必要があります。
1.Draw クラス
グラフィックを作図するためのクラスです。
var draw = new Draw({
view: view
});
2.Graphic クラス
グラフィックオブジェクトを作成するためのクラスです。
var graphic = new Graphic({
geometry: point,
symbol: {
type: "simple-marker",
style: "square",
color: "red",
size: "16px",
outline: {
color: [255, 255, 0],
width: 3
}
}
});
実行ボタン押下時の処理
セレクトボックスの選択肢によって以下のように分岐するようにしました。
var sketchToggle= document.getElementById("executeSketch");
on(sketchToggle, "click", function() {
var geometryType = document.getElementById("geometryType").value;
if(geometryType == "ポイント"){
enableCreatePoint();
} else if (geometryType == "ライン"){
enableCreateLine();
} else if (geometryType == "ポリゴン"){
enableCreatePolygon();
} else if (geometryType == "テキスト"){
enableCreateText();
}
});
ポイントの作図
draw.create("point")
でポイントを作図することができます。そして、最後に view.graphics.add(graphic);
で作図したポイントをマップビューに追加します。
function enableCreatePoint() {
var action = draw.create("point");
action.on("draw-complete", function (evt) {
createPointGraphic(evt.coordinates);
});
}
function createPointGraphic(coordinates){
var point = {
type: "point",
x: coordinates[0],
y: coordinates[1],
spatialReference: view.spatialReference
};
var graphic = new Graphic({
geometry: point,
symbol: {
type: "simple-marker",
style: "square",
color: "red",
size: "16px",
outline: {
color: [255, 255, 0],
width: 3
}
}
});
view.graphics.add(graphic);
}
ラインの作図
ポイントの作図と基本は同じです。ただ、ラインなのでクリックするごとにラインのセグメントを作成する必要があります。今回は実装上の都合上、ラインはマップ上に一つしか作図できません(二個目を作図しようとすると一個目は削除される)。
function enableCreateLine() {
var action = draw.create("polyline");
view.focus();
action.on(
[
"vertex-add",
"vertex-remove",
"cursor-update",
"draw-complete"
],
createPolylineGraphic
);
}
function createPolylineGraphic(event) {
var vertices = event.vertices;
view.graphics.removeAll();
var graphic = new Graphic({
geometry: {
type: "polyline",
paths: vertices,
spatialReference: view.spatialReference
},
symbol: {
type: "simple-line",
color: "red",
width: 4,
cap: "round",
join: "round"
}
});
view.graphics.add(graphic);
}
ポリゴンの作図
ラインの作図とほぼ同じです。なので、ここは共通化した方がいいかもしれないですね。こちらも実装上の都合でマップ上に一つのポリゴンのみが作図可能です。
function enableCreatePolygon() {
var action = draw.create("polygon");
view.focus();
action.on(
[
"vertex-add",
"vertex-remove",
"cursor-update",
"draw-complete"
],
createPolygonGraphic
);
}
function createPolygonGraphic(event) {
var vertices = event.vertices;
view.graphics.removeAll();
var graphic = new Graphic({
geometry: {
type: "polygon",
rings: vertices,
spatialReference: view.spatialReference
},
symbol: {
type: "simple-fill",
color: "red",
style: "solid",
outline: {
color: [255, 255, 0],
width: 3
}
}
});
view.graphics.add(graphic);
}
テキストの作図
基本はポイントの作図と同じです。今回はテキストの中身は「GIS奮闘記」固定にしましたが、テキストボックスを作ってそこの値をとってくるようにすれば完璧かと思います。
function enableCreateText() {
var action = draw.create("point");
action.on("draw-complete", function (evt) {
createTextGraphic(evt.coordinates);
});
}
function createTextGraphic(coordinates){
var point = {
type: "point",
x: coordinates[0],
y: coordinates[1],
spatialReference: view.spatialReference
};
var textSymbol = {
type: "text",
color: "red",
haloColor: "black",
haloSize: "1px",
text: "GIS奮闘記",
xoffset: 3,
yoffset: 3,
font: {
size: 20,
weight: "bold"
}
};
var graphic = new Graphic({
geometry: point,
symbol: textSymbol
});
view.graphics.add(graphic);
}
サンプルコード
以下に全コードを記載します。
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">
<title>レイヤ一覧表示</title>
<link rel="stylesheet" href="https://js.arcgis.com/4.12/esri/css/main.css">
<script src="https://js.arcgis.com/4.13/"></script>
<style>
html,
body,
#viewDiv {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
}
#layerToggle,#sketchToggle{
display: none;
top: 80px;
right: 20px;
position: absolute;
z-index: 99;
background-color: white;
border-radius: 8px;
padding: 10px;
opacity: 0.75;
}
#menu{
padding: 0;
margin: 0;
height:42px;
background-color:#eeeeee;
font-weight:bold;
}
#menu li {
height:42px;
margin-right: 2px;
display: inline-block;
}
#button,#buttonElevation,#buttonSketch,#geometryType {
left:0px;
width:164px;
height:42px;
}
#executeSketch {
left:0px;
width:82px;
height:42px;
}
</style>
<script>
require([
"esri/Map",
"esri/views/MapView",
"esri/layers/VectorTileLayer",
"esri/layers/FeatureLayer",
"esri/layers/MapImageLayer",
"esri/Graphic",
"esri/views/draw/Draw",
"dojo/on",
"dojo/domReady!"
],
function(
Map,
MapView,
VectorTileLayer,
FeatureLayer,
MapImageLayer,
Graphic,
Draw,
on
) {
var map = new Map({
basemap: "gray-vector"
});
var vectorTileLayer = new VectorTileLayer({
url:
"https://www.arcgis.com/sharing/rest/content/items/92c551c9f07b4147846aae273e822714/resources/styles/root.json",
id:"vectorTile"
});
var mapImageLayer = new MapImageLayer({
url: "https://content.esrij.com/arcgis/rest/services/Dosyasaigai/Dosyasaigai_Tile/MapServer",
id:"mapImage"
});
var boundary = new FeatureLayer({
url:"https://services.arcgis.com/P3ePLMYs2RVChkJx/arcgis/rest/services/JPN_Boundaries_ECM/FeatureServer",
id:"boundary",
opacity:0.5,
minScale:1500000,
maxScale:50000
});
map.add(vectorTileLayer);
map.add(mapImageLayer);
map.add(boundary);
var view = new MapView({
container: "viewDiv",
map: map,
center: [139.740286, 35.678601],
zoom: 15
});
var vectorTileToggle = document.getElementById("vectorTileLayer");
var mapImageToggle = document.getElementById("mapImageLayer");
var boundaryToggle = document.getElementById("boundary");
on(vectorTileToggle, "change", function() {
vectorTileLayer.visible = vectorTileToggle.checked;
});
on(mapImageToggle, "change", function() {
mapImageLayer.visible = mapImageToggle.checked;
});
on(boundaryToggle, "change", function() {
boundary.visible = boundaryToggle.checked;
});
view.on("click", function (event) {
if(elevation==1){
var data = { 'lon': event.mapPoint.longitude , 'lat': event.mapPoint.latitude };
var querystring = encodeQueryData(data);
var url = "http://cyberjapandata2.gsi.go.jp/general/dem/scripts/getelevation.php?" + querystring + "&outtype=JSON"
var request = new XMLHttpRequest();
request.open('GET', url);
request.onreadystatechange = function () {
var result = JSON.parse(request.responseText);
view.popup.open({
title: result.elevation,
content : result.elevation,
location: event.mapPoint
});
};
request.send(null);
}
});
function encodeQueryData(data) {
let ret = [];
for (let d in data)
ret.push(encodeURIComponent(d) + '=' + encodeURIComponent(data[d]));
return ret.join('&');
}
var sketchToggle= document.getElementById("executeSketch");
on(sketchToggle, "click", function() {
var geometryType = document.getElementById("geometryType").value;
if(geometryType == "ポイント"){
enableCreatePoint();
} else if (geometryType == "ライン"){
enableCreateLine();
} else if (geometryType == "ポリゴン"){
enableCreatePolygon();
} else if (geometryType == "テキスト"){
enableCreateText();
}
});
var draw = new Draw({
view: view
});
function enableCreatePoint() {
var action = draw.create("point");
action.on("draw-complete", function (evt) {
createPointGraphic(evt.coordinates);
});
}
function createPointGraphic(coordinates){
var point = {
type: "point",
x: coordinates[0],
y: coordinates[1],
spatialReference: view.spatialReference
};
var graphic = new Graphic({
geometry: point,
symbol: {
type: "simple-marker",
style: "square",
color: "red",
size: "16px",
outline: {
color: [255, 255, 0],
width: 3
}
}
});
view.graphics.add(graphic);
}
function enableCreateLine() {
var action = draw.create("polyline");
view.focus();
action.on(
[
"vertex-add",
"vertex-remove",
"cursor-update",
"draw-complete"
],
createPolylineGraphic
);
}
function createPolylineGraphic(event) {
var vertices = event.vertices;
view.graphics.removeAll();
var graphic = new Graphic({
geometry: {
type: "polyline",
paths: vertices,
spatialReference: view.spatialReference
},
symbol: {
type: "simple-line",
color: "red",
width: 4,
cap: "round",
join: "round"
}
});
view.graphics.add(graphic);
}
function enableCreatePolygon() {
var action = draw.create("polygon");
view.focus();
action.on(
[
"vertex-add",
"vertex-remove",
"cursor-update",
"draw-complete"
],
createPolygonGraphic
);
}
function createPolygonGraphic(event) {
var vertices = event.vertices;
view.graphics.removeAll();
var graphic = new Graphic({
geometry: {
type: "polygon",
rings: vertices,
spatialReference: view.spatialReference
},
symbol: {
type: "simple-fill",
color: "red",
style: "solid",
outline: {
color: [255, 255, 0],
width: 3
}
}
});
view.graphics.add(graphic);
}
function enableCreateText() {
var action = draw.create("point");
action.on("draw-complete", function (evt) {
createTextGraphic(evt.coordinates);
});
}
function createTextGraphic(coordinates){
var point = {
type: "point",
x: coordinates[0],
y: coordinates[1],
spatialReference: view.spatialReference
};
var textSymbol = {
type: "text",
color: "red",
haloColor: "black",
haloSize: "1px",
text: "GIS奮闘記",
xoffset: 3,
yoffset: 3,
font: {
size: 20,
weight: "bold"
}
};
var graphic = new Graphic({
geometry: point,
symbol: textSymbol
});
view.graphics.add(graphic);
}
});
function displayLayerList(){
var toggle = document.getElementById("layerToggle");
if(toggle.style.display=="block"){
toggle.style.display ="none";
}else{
toggle.style.display ="block";
}
}
var elevation = 0;
function getElevation(){
if(elevation==1){
elevation = 0;
}else{
elevation = 1;
}
}
function edit(){
var toggle = document.getElementById("sketchToggle");
if(toggle.style.display=="block"){
toggle.style.display ="none";
}else{
toggle.style.display ="block";
}
}
</script>
</head>
<body>
<ul id="menu">
<li id="menu">
<button id="button" type="button" onClick="displayLayerList()">レイヤー一覧</button>
</li>
<li>
<button id="buttonElevation" type="button" onClick="getElevation()">標高</button>
</li>
<li>
<button id="buttonSketch" type="button" onClick="edit()">作図</button>
</li>
</ul>
<div id="viewDiv"></div>
<div id="layerToggle">
<input type="checkbox" id="vectorTileLayer" checked/>背景<br>
<input type="checkbox" id="mapImageLayer" checked/>国土数値情報 災害情報<br>
<input type="checkbox" id="boundary" checked />平成 27 年国勢調査 都道府県界<br>
</div>
<div id="sketchToggle">
<select id="geometryType">
<option value=""></option>
<option value="ポイント">ポイント</option>
<option value="ライン">ライン</option>
<option value="ポリゴン">ポリゴン</option>
<option value="テキスト">テキスト</option>
</select>
<button id="executeSketch" type="button">実行</button>
</div>
</body>
</html>
それでは作図してみようと思います。
ポイント
ライン
ポリゴン
テキスト
ばっちりですね!ソースはそんなに複雑ではないのに ArcGIS API for JavaScript を使えば本当に色々なことができますね。これからは Web GIS が更に普及していくかと思いますので、もしまだ ArcGIS API for JavaScript を使ったことがないという方は使っておいて損はないかと思います。今回は Draw と Graphic クラスの基本的な使い方を紹介しましたが、今後、機会があればもう一歩踏み込んだ使い方を紹介できればと思います。本日は以上です。