さて、本日は TypeScript を使って Web マップにカスタムウィジェットを配置してみようと思います。みなさんは TypeScript を使っていますでしょうか?おそらく日本ではまだ馴染みのない言語の一つかもしれません。ただ、近年人気が高まってきており、近い将来はメジャーな言語の一つになるのではないかと思っています。
TypeScript とは
TypeScript はマイクロソフトによって開発され、メンテナンスされているフリーでオープンソースのプログラミング言語である。TypeScript は JavaScriptに対して、省略も可能な静的型付けとクラスベースオブジェクト指向を加えた厳密なスーパーセットとなっている(Wikipedia より抜粋)。
簡単に言うと JavaScript の進化版といったところでしょうか。そして、TypeScript で書いたコードをコンパイルすると JavaScript のコードに変換することができます。もっと細かいことを知りたい方は以下 Web サイトに記載されているので、読んでみてください。
なぜ TypeScript を使ってみようと思ったのか
以下のように JavaScript → TypeScript への流れに取り残されないようにするためでしょうか。やはりエンジニアの端くれとして新しいことにチャレンジし続けたいですね。
- Google が TypeScript を社内の標準言語に採用するなど、TypeScript の存在感は年々高まってきているため
- 米国Esri が TypeScript を推しているため(将来的には 全てのコードが TypeScript になるかも?!)
- 個人的に将来を見据えて新しいことに挑戦したかったため
準備
まずは環境を準備しなくてはいけませんね。こちらは ESRIジャパンさんのブログなのですが、TypeScript の環境構築から簡単なサンプルコードを載せてくれています。こちらを参考にさせてもらいます。
また、TypeScript でのカスタムウィジェット作成に関しては、ESRIジャパンさんが公開しているカスタムウィジェット ハンズオンを参考にしてみました。
今回チャレンジすること
概観図をカスタムウィジェットとして作ってみようと思います。概観図とは以下の画像の右上にある地図のことです。メインのマップの概観を表示させるものですね。
概観図の JavaScript 用のサンプルコードが以下に公開されているので、今回はこれを TypeScript に書き換えてみようと思います。 developers.arcgis.com
作ったもの
上記に記載したリソースをもとに以下のような構成でカスタムウィジェットつきのWeb マップを作ってみました。
サンプルコード
「OverView.tsx」「index.html」のサンプルコードです。
OverView.tsx
import Map from "esri/Map"; import MapView from "esri/views/MapView"; import Graphic from "esri/Graphic"; import * as watchUtils from "esri/core/watchUtils"; import {subclass, declared, property} from "esri/core/accessorSupport/decorators"; import Widget = require("esri/widgets/Widget"); import { renderable, tsx } from "esri/widgets/support/widget"; @subclass("esri.widgets.OverView") class OverView extends declared(Widget) { constructor() { super(); this._overViewChange = this._overViewChange.bind(this); } @property() @renderable() map: Map; @property() @renderable() mainView: MapView; @property() @renderable() mapView: MapView; @property() @renderable() graphic: Graphic; // postInitialize メソッドの追加 postInitialize() { var overviewMap = new Map({ basemap: "topo" }); this.mapView = new MapView({ container: "overviewDiv", map: overviewMap, center: [139.740286, 35.678601], zoom: 10, constraints: { rotationEnabled: false } }); this.mapView.ui.components = []; var graphicSymbol = { type: "simple-fill", color: [100, 0, 0, 0.5] }; this.graphic = new Graphic({ geometry: null, symbol: graphicSymbol }); this.mapView.graphics.add(this.graphic); watchUtils.init(this, "mainView.extent", () => this._overViewChange()); } private _overViewChange () { if (this.mainView.stationary) { this.mapView .goTo({ center: this.mainView.center, scale: this.mainView.scale * 2 * Math.max( this.mainView.width / this.mapView.width, this.mainView.height / this.mapView.height ) }) .catch(function(error) { if (error.name != "view:goto-interrupted") { console.error(error); } }); } this.graphic.geometry = this.mainView.extent; } render() { return ( <div bind={this}> </div> ); } } export = OverView;
index.html
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta name="概観図" content="initial-scale=1,maximum-scale=1,user-scalable=no" /> <title>Overview map - 4.15</title> <style> html, body, #viewDiv { padding: 0; margin: 0; height: 100%; width: 100%; } #overviewDiv { position: absolute; top: 12px; right: 12px; width: 600px; height: 200px; border: 1px solid black; z-index: 1; overflow: hidden; } </style> <link rel="stylesheet" href="https://js.arcgis.com/4.15/esri/themes/light/main.css" /> <script> /* dojoConfig の設定 */ var locationPath = location.pathname.replace(/\/[^\/]+$/, ""); window.dojoConfig = { packages: [ { name: "app", location: locationPath + "/app" } ] }; </script> <script src="https://js.arcgis.com/4.15/"></script> <script> require([ "esri/Map", "esri/views/MapView", "app/OverView" ], function(Map, MapView, OverView) { var mainMap = new Map({ basemap: "hybrid" }); var mainView = new MapView({ container: "viewDiv", map: mainMap, center: [139.740286, 35.678601], zoom: 15 }); mainView.when(function() { /* ウィジェットのインスタンス化 */ overView = new OverView({ map:mainMap, mainView:mainView }); mainView.ui.add(overView, "top-right"); }); }); </script> </head> <body> <div id="viewDiv" class="esri-widget"></div> <div id="overviewDiv"></div> </body> </html>
TypeScript に関してはほとんど素人同然なので変な書き方をしているかもしれませんが、完成させることができたのでひとまずほっとしております。
以下のように概観図がマップに配置されていることが確認できました。
メインのマップを移動させると概観図の赤枠(メインのマップの表示箇所)も移動することがわかります。
TypeScript を使ってみた感想
最初は書き方や TypeScript 独特のコンセプトに戸惑うこともあったのですが、慣れの問題かと思います。色々使ってみる中で感じたのは、やはり型が使えるというのが JavaScript に比べて大きなアドバンテージかなと思いました(今回はあまりそのメリットを享受していないのですが)。まだまだ知らないことも多いのですが、色々触りながら勉強してみようと思います。本日は以上です。