Web AppBuilderカスタムウィジェット(3) 追加したレイヤーをレイヤーリストに表示する

前回追加したレイヤーが邪魔なので隠したいとき、GraphicsLayerのままだとレイヤーリストに表示されず、画面から操作できません。原因は追加したレイヤーがGraphicsLayerだからのようなので、FeatureLayerに切り替えれば解決できます。

Web AppBuilder for ArcGIS(Developer Edition)のカスタムウィジェットで、手元のCSVをアップロードして、地図上に表示するための開発の3回めです。

シリーズ一覧

今回のゴール

前回作ったところで、レイヤーリストウィジェットを表示してみると、以下のとおり追加したレイヤーが表示されません。

WS000001

この操作レイヤーに追加したCSV読込ウィジェットで追加したレイヤーを表示して、表示のオン/オフを自由に買えられるようにしたい。

調査

まずは、原因究明のため、ダウンロードした製品付属のLayerListウィジェットのWidget.jsを確認してみます。

特にレイヤー一覧を表示用に取得しているロジックを確認すると、

array.forEach(this.map.graphicsLayerIds, function(layerId) {
  var layer = this.map.getLayer(layerId);
  if (layer.isOperationalLayer) {
    operLayers.push({
      layerObject: layer,
      title: layer.label || layer.title || layer.name || layer.id || " ",isOperationalLayer
      id: layer.id || " "
    });
  }
}, this);

対象レイヤーの一覧らしき、「operLayers」変数に、layerオブジェクトを追加する際に「isOperationalLayer」プロパティをチェックしていますね。どうも前回作ったレイヤーではこれがオフ(false)のせいでレイヤーリストに表示されていない気がします。

APIドキュメントを漁ってみた限りでは、isOperationalLayerプロパティはなさそうですが……。

Layer

GraphicsLayer

FeatureLayer

ということで「WebAppBuilderForArcGIS\client\stemapp\」フォルダ内をプロパティ名でGrepしてみると、Drawというウィジェットでも使っていました。

このウィジェットには「マップの操作レイヤーとして描画を追加します」という設定があるのですが、名前から恐らくこれが、isOperationalLayerに相当するでしょう。

_initLayers: function(){
this._graphicsLayer = new GraphicsLayer();

if(this.config.isOperationalLayer){
    var layerDefinition = {
        "name": "",
        "geometryType": "",
        "fields": [{
            "name": this._objectIdName,
            "type": this._objectIdType,
            "alias": this._objectIdName
        }]
    };
    var pointDefinition = lang.clone(layerDefinition);
    pointDefinition.name = this.nls.points;//this.label + "_" +
    pointDefinition.geometryType = "esriGeometryPoint";
    this._pointLayer = new FeatureLayer({
        layerDefinition: pointDefinition,
        featureSet: null
    });

    var polylineDefinition = lang.clone(layerDefinition);
    polylineDefinition.name = this.nls.lines;
    polylineDefinition.geometryType = "esriGeometryPolyline";
    this._polylineLayer = new FeatureLayer({
        layerDefinition: polylineDefinition,
        featureSet: null
    });

    var polygonDefinition = lang.clone(layerDefinition);
    polygonDefinition.name = this.nls.areas;
    polygonDefinition.geometryType = "esriGeometryPolygon";
    this._polygonLayer = new FeatureLayer({
        layerDefinition: polygonDefinition,
        featureSet: null
    });

    var labelDefinition = lang.clone(layerDefinition);
    labelDefinition.name = this.nls.text;
    labelDefinition.geometryType = "esriGeometryPoint";
    this._labelLayer = new FeatureLayer({
        layerDefinition: labelDefinition,
        featureSet: null
    });

    var loading = new LoadingIndicator();

    loading.placeAt(this.domNode);

    LayerInfos.getInstance(this.map, this.map.itemInfo)
    .then(lang.hitch(this, function(layerInfos){
        if(!this.domNode){
            return;
        }

        loading.destroy();
        var layers = [this._polygonLayer, this._polylineLayer,
                      this._pointLayer, this._labelLayer];
        layerInfos.addFeatureCollection(layers, this.label + "_" + this.nls.results);
    }), lang.hitch(this, function(err){
        loading.destroy();
        console.error("Can not get LayerInfos instance", err);
    }));
}else{
    this._pointLayer = new GraphicsLayer();
    this._polylineLayer = new GraphicsLayer();
    this._polygonLayer = new GraphicsLayer();
    this._labelLayer = new GraphicsLayer();
    this.map.addLayer(this._polygonLayer);
    this.map.addLayer(this._polylineLayer);
    this.map.addLayer(this._pointLayer);
    this.map.addLayer(this._labelLayer);
}

操作レイヤーのとき→FeatueLayerを作って登録している

操作レイヤーでないとき→GraphicsLayerを作って登録している(前回私がやった方法)

ということで、FeatureLayerにすればいいのではないかという仮説を立てました。

ウィジェットで追加するレイヤーをFeatureLayerに変更

まずは、defineで読み込むクラスを変更します。

define(['dojo/_base/declare', 'jimu/BaseWidget', 'dojo/on', 'dojo/dom', 'dojo/_base/array', 
        'esri/geometry/Point', 'esri/layers/FeatureLayer', 'esri/graphic', 'esri/SpatialReference',
        'esri/Color','esri/symbols/SimpleMarkerSymbol'],
function(declare, BaseWidget, on, dom, array, Point, FeatureLayer, graphic, SpatialReference, 
         Color, SimpleMarkerSymbol) {

次にFeatureLayerを作成して登録。

GraphicsLayerなら、new GraphicsLayer()だけで住みますが、FeatureLayerのコンストラクタは、URLか、featureCollectionObjectを要求します。ここでいうURLはArcGIS for ServerのREST URLです。今は自分で作ったデータを登録しようとしているので、この方法は使えません。

必然的に、featureCollectionObjectを作る方法にします。featureCollectionObjectをつくのには今度はLayerDefinitionオブジェクトが必要です。細かいところは置いておいて、サンプルコードを参考に以下のように書きました。ポイント型のFeatureDefinitionをパラメータにFeatureLayerを作って、GraphicsLayerの代わりにMapに登録しています。

var pointDefinition = {
    "geometryType": "esriGeometryPoint",
    "fields": [{
        "name": "CSV読込",
        "type": "esriFieldTypeInteger"
    }]
};
this.myLayer = new FeatureLayer({
    layerDefinition: pointDefinition,
    featureSet: null
});
//this.myLayer = new GraphicsLayer();
this.map.addLayer(this.myLayer);

リロードして、CSV読込を実施し、レイヤーリストを表示すると、追加したgraphicsLayer2が表示されています。作成時に名前を指定していないので勝手に変な名前が振られています。

LayerListに出た

チェックボックスをオフにするとちゃんと消えました。
非表示にしたところ