Why isn't my renderer working on this StreamLayer

1234
5
01-05-2018 01:53 PM
JoshPritt
New Contributor III

We are using Javascript API 3.21 and trying to set the renderer for a StreamLayer.  Debugging through the chrome dev tools we can see that it's applying the renderer correctly to the layer but we see all the default blue circles disappear and none ever show.  But we can see the features actually streaming in over the network tab in the websocket connection frames.  Can someone verify this UniqueValueRenderer is valid on their stream layer?

{
    "type": "uniqueValue",
    "attributeField": "groupid",
    "visualVariables": [{
        "type": "rotationInfo",
        "field": "heading",
        "rotationType": "geographic"
    }],
    "defaultSymbol": {
        "color": [0, 0, 0, 255],
        "outline": {
            "color": [0, 0, 0, 255],
            "width": 1,
            "type": "esriSLS",
            "style": "esriSLSNull"
        },
        "type": "esriSFS",
        "style": "esriSFSNull"
    },
    "uniqueValueInfos": [{
            "value": "ASB",
            "symbol": {
                "color": [255, 0, 0, 255],
                "outline": {
                    "color": [0, 0, 0, 255],
                    "width": 1,
                    "type": "esriSLS",
                    "style": "esriSLSSolid"
                },
                "type": "esriSFS",
                "style": "esriSFSSolid"
            }
        },
        {
            "value": "WG",
            "symbol": {
                "color": [0, 0, 255, 255],
                "outline": {
                    "color": [0, 0, 0, 255],
                    "width": 1,
                    "type": "esriSLS",
                    "style": "esriSLSSolid"
                },
                "type": "esriSFS",
                "style": "esriSFSSolid"
            }
        }]
}
5 Replies
RobertScheitlin__GISP
MVP Emeritus

Josh,

   It looks fine as long are you are symbolizing Polygons (if you have a heading field I would wager that it is a point). If your stream layer is point then you are using the wrong symbol.

JoshPritt
New Contributor III

Oh yes, Simple Fill Symbol (SFS) is for polygons.  Of course!   OK how does this simple marker symbol (SMS) look?  I know the rotation won't work because they are just circles.  But this should work at least right?  Instead of completely not working at all like it does now.  We'll test it on Monday.  We'll look into getting the vector path arrow symbol working then too.

{
    "type": "uniqueValue",
    "attributeField": "groupid",
    "visualVariables": [{
        "type": "rotationInfo",
        "field": "heading",
        "rotationType": "geographic"
    }],
    "defaultSymbol": {
  "color": [100,255,50,64],
  "size": 12,
  "angle": 0,
  "xoffset": 0,
  "yoffset": 0,
  "type": "esriSMS",
  "style": "esriSMSCircle",
  "outline": {
    "color": [0,0,0,255],
    "width": 1,
    "type": "esriSLS",
    "style": "esriSLSSolid"
  }
},
    "uniqueValueInfos": [{
            "value": "ASB",
            "symbol": {
  "color": [0,255,0,64],
  "size": 12,
  "angle": 0,
  "xoffset": 0,
  "yoffset": 0,
  "type": "esriSMS",
  "style": "esriSMSCircle",
  "outline": {
    "color": [0,0,0,255],
    "width": 1,
    "type": "esriSLS",
    "style": "esriSLSSolid"
    }
}
        },
        {
            "value": "WG",
            "symbol": {
  "color": [0,0,255,64],
  "size": 12,
  "angle": 0,
  "xoffset": 0,
  "yoffset": 0,
  "type": "esriSMS",
  "style": "esriSMSCircle",
  "outline": {
    "color": [0,0,0,255],
    "width": 1,
    "type": "esriSLS",
    "style": "esriSLSSolid"
    }
              }
  }]
}
0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Josh,

  Yes that is good. I would just delete this part though:

    "visualVariables": [{
        "type": "rotationInfo",
        "field": "heading",
        "rotationType": "geographic"
    }],

since the symbols are just circles.

0 Kudos
LanceGoens
New Contributor III

I work with Josh and I just tried this renderer and it's starting to work, however it always uses the renderer's default symbol... a green mostly transparent circle with a black outline. I noticed a couple changes in the json property names between the 3.23 and 4.x APIs that I have modified. Namely, "uniqueValueInfos" is just "infos" at 3.23, "field" is "attributeField" at 3.23 etc. I'm not sure if I've found all of the differences and I'm fairly annoyed they are different! As Josh stated, we are required to use 3.21 - so if there are differences between 3.23 and 3.21 we may be in trouble as I can't find a 3.21 specific API reference.

As for the rotation concern, it has no affect if the "visualVariables" node is present or not in the renderer... it still shows the green default symbol like it could not match the groupid. One thing that has me curious is the location of the fields we need to key off of. The "groupid" field that determines the desired color of the renderer is nested in the "attributes" node of the stream output. I'm not familiar if these stream outputs are standardized in any way - how does the renderer know to look for "groupid" inside of "attributes" - do we need to specify that in the "infos" markup in the renderer (EG: use a JSON path expression)?

If it helps those reading, below is a sample from our stream output (scrubbed data).

ASB Group:

{
        "geometry": {
            "x": -99.9999999,
            "y": 99.9999999999999,
            "spatialReference": {
                "wkid": 4326
            }
        },
        "attributes": {
            "objectid": null,
            "deviceid": "9999999999",
            "x": -99.9999999,
            "y": 99.9999999999999,
            "speed": 0,
            "heading": 169.7,
            "ismoving": 0,
            "gpsstatus": 1,
            "gpstimestamp": 1515273625000,
            "userid": "XXXXX",
            "lastuserid": "",
            "idletime": 390,
            "userfullname": "REMOVED",
            "groupid": "ASB",
            "district": "REMOVED",
            "status": null,
            "onmdt": "REMOVED",
            "technicianid": 9999,
            "workassignment": null,
            "vehiclenumber": null,
            "insertdate": 1515273625395,
            "hdop": 0.9,
            "pdop": 1.2,
            "fixtype": "GPS Fix",
            "satellitecount": 10,
            "sequencenumber": 1122
        }
    }

WG Group:

{
        "geometry": {
            "x": -99.9999999,
            "y": 99.9999999999999,
            "spatialReference": {
                "wkid": 4326
            }
        },
        "attributes": {
            "objectid": null,
            "deviceid": "9999999999",
            "x": -99.9999999,
            "y": 99.9999999999999,
            "speed": 31,
            "heading": 41.1,
            "ismoving": 1,
            "gpsstatus": 1,
            "gpstimestamp": 1515273624000,
            "userid": "XXXXX",
            "lastuserid": "",
            "idletime": 0,
            "userfullname": "REMOVED",
            "groupid": "WG",
            "district": "REMOVED",
            "status": null,
            "onmdt": "REMOVED",
            "technicianid": 99999,
            "workassignment": null,
            "vehiclenumber": null,
            "insertdate": 1515273624814,
            "hdop": 0.9,
            "pdop": 1.2,
            "fixtype": "GPS Fix",
            "satellitecount": 10,
            "sequencenumber": 1122
        }
    }

Here is the renderer now that is showing default symbols (the defined green symbol, not esri's blue dots). It's using the properties specified for 3.23 as noted above.

{
    "type": "uniqueValue",
    "attributeField": "groupid",
    "visualVariables": [{
        "type": "rotationInfo",
        "field": "heading",
        "rotationType": "geographic"
    }],
    "defaultSymbol": {
        "color": [100,255,50,64],
        "size": 12,
        "xoffset": 0,
        "yoffset": 0,
        "type": "esriSMS",
        "style": "esriSMSCircle",
        "outline": {
            "color": [0,0,0,255],
            "width": 1,
            "type": "esriSLS",
            "style": "esriSLSSolid"
        }
    },
    "infos": [{
        "value": "ASB",
        "symbol": {
            "color": [255,0,0,100],
            "size": 12,
            "xoffset": 0,
            "yoffset": 0,
            "type": "esriSMS",
            "style": "esriSMSCircle",
            "outline": {
                "color": [0,0,0,255],
                "width": 1,
                "type": "esriSLS",
                "style": "esriSLSSolid"
            }
        }
    },
    {
        "value": "WG",
        "symbol": {
            "color": [0,0,255,100],
            "size": 12,
            "xoffset": 0,
            "yoffset": 0,
            "type": "esriSMS",
            "style": "esriSMSCircle",
            "outline": {
                "color": [0,0,0,255],
                "width": 1,
                "type": "esriSLS",
                "style": "esriSLSSolid"
            }
        }
    }]
}
RobertScheitlin__GISP
MVP Emeritus

Lance,

  Unfortunately the json for the renderer differs from the JS API property names. See the Rest API for the proper syntax:

http://resources.arcgis.com/en/help/arcgis-rest-api/#/Renderer_objects/02r30000019t000000/ 

Here is a sample that use a esri public StreamLayer and uses a UniqueValueRenederer based on a true false field in the layer. Notice the syntax that works is the exact syntax that they (esri) provides in their sample code:

<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no">
  <title>StreamLayer using ArcGIS API for JavaScript and ArcGIS Server Stream Service</title>
  <link rel="stylesheet" href="https://js.arcgis.com/3.21/dijit/themes/tundra/tundra.css">
  <link rel="stylesheet" href="https://js.arcgis.com/3.21/esri/css/esri.css">
  <style type="text/css">
    html,
    body {
      height: 100%;
      width: 100%;
      margin: 0;
      padding: 0;
    }

    body {
      background-color: #fff;
      overflow: hidden;
      font-family: sans-serif;
    }

    p {
      margin: 2px;
    }

    .controls {
      margin-left: 10px;
      padding-top: 10px;
    }

    #map {
      width: 100%;
      height: 80%;
    }
  </style>
  <script src="https://js.arcgis.com/3.21/"></script>
</head>

<body class="tundra">
  <div id="map"></div>
  <div class="controls">
    <span>Stream service url: </span><input type="text" id="txtStreamUrl" value="https://geoeventsample1.esri.com:6443/arcgis/rest/services/LABus/StreamServer" style="color:#ffffff; width:600px; background-color: #8b0000" /><br>
    <input type="button" id="cmdToggleStreamLayer" value="Make Stream Layer" />
  </div>
  <div id="divFilterControls" class="controls" style="display: none">
    <p>Draw extent to filter messages by a bounding box</p>
    <input type="button" id="cmdToggleSpatialFilter" value="Draw Extent" /><br>
  </div>
</body>
<script>
  require(["esri/map",
    "esri/toolbars/draw",
    "esri/layers/StreamLayer",
    "esri/InfoTemplate",
    "esri/graphic",
    "esri/symbols/SimpleFillSymbol",
    "esri/symbols/SimpleLineSymbol",
    "dojo/_base/Color",
    "esri/renderers/UniqueValueRenderer",
    "dojo/on",
    "dojo/domReady!"
  ], function(Map, Draw, StreamLayer, InfoTemplate, Graphic, SimpleFillSymbol,
    SimpleLineSymbol, Color, UniqueValueRenderer, on) {
    var map,
      drawTools,
      streamLayer;

    function init() {
      map = new Map("map", {
        basemap: "gray",
        center: [-117.98118, 34.00679],
        zoom: 10
      });

      drawTools = new Draw(map);

      //connect click events to UI buttons
      on(dojo.byId("cmdToggleStreamLayer"), "click", toggleStreamLayer);
      on(dojo.byId("cmdToggleSpatialFilter"), "click", toggleSpatialFilter);

      on(drawTools, "draw-end", function(evt) {
        drawTools.deactivate();
        setSpatialFilter(evt.geometry);
        dojo.byId("cmdToggleSpatialFilter").value = "Clear Spatial Filter";
      });
    }

    /*************************************************
     *
     * Functions to add and remove Stream Layer
     *
     *************************************************/
    function toggleStreamLayer() {
      if (streamLayer) {
        removeStreamLayer();
      } else {
        addStreamLayer();
      }
    }

    function addStreamLayer() {
      //url to stream service
      var svcUrl = dojo.byId("txtStreamUrl").value;

      //construct Stream Layer
      streamLayer = new StreamLayer(svcUrl, {
        purgeOptions: {
          displayCount: 10000
        },
        infoTemplate: new InfoTemplate("Attributes", "${*}")
      });
      var uvrJson = {
        "type": "uniqueValue",
        "field1": "predictable",
        "defaultSymbol": {
          "color": [255, 0, 0, 40],
          "size": 12,
          "xoffset": 0,
          "yoffset": 0,
          "type": "esriSMS",
          "style": "esriSMSCircle",
          "outline": {
            "color": [0, 0, 0, 255],
            "width": 1,
            "type": "esriSLS",
            "style": "esriSLSSolid"
          }
        },
        "uniqueValueInfos": [{
          "value": "true",
          "symbol": {
            "color": [255, 255, 0, 100],
            "size": 12,
            "xoffset": 0,
            "yoffset": 0,
            "type": "esriSMS",
            "style": "esriSMSCircle",
            "outline": {
              "color": [0, 0, 0, 255],
              "width": 1,
              "type": "esriSLS",
              "style": "esriSLSSolid"
            }
          }
        }, {
          "value": "false",
          "symbol": {
            "color": [0, 0, 255, 100],
            "size": 12,
            "xoffset": 0,
            "yoffset": 0,
            "type": "esriSMS",
            "style": "esriSMSCircle",
            "outline": {
              "color": [0, 0, 0, 255],
              "width": 1,
              "type": "esriSLS",
              "style": "esriSLSSolid"
            }
          }
        }]
      }
      var uvRend = new UniqueValueRenderer(uvrJson);
      streamLayer.setRenderer(uvRend);

      //When layer loads, register listeners for layer events and add layer to map
      streamLayer.on("load", function() {
        //Connect and Disconnect events
        streamLayer.on("connect", processConnect);
        streamLayer.on("disconnect", processDisconnect);

        //FilterChange event
        streamLayer.on("filter-change", processFilterChange);

        //Add layer to map
        map.addLayer(streamLayer);
      });
    }

    function removeStreamLayer() {
      if (streamLayer) {
        map.removeLayer(streamLayer);
        streamLayer = null;
        map.graphics.clear();
      }
    }

    /*********************************************************
     *
     * Stream layer event handlers
     *
     *********************************************************/
    function processConnect() {
      dojo.byId("cmdToggleStreamLayer").value = "Remove Stream Layer";
      dojo.byId("txtStreamUrl").style.backgroundColor = "#008000";
      dojo.byId("cmdToggleSpatialFilter").value = "Draw Extent";
      dojo.byId("divFilterControls").style.display = "block";
    }

    function processDisconnect() {
      dojo.byId("cmdToggleStreamLayer").value = "Add Stream Layer";
      dojo.byId("txtStreamUrl").style.backgroundColor = "#8b0000";
      dojo.byId("divFilterControls").style.display = "none";
    }

    function processFilterChange(evt) {
      //clear layer graphics
      streamLayer.clear();

      //the event contains a filter property that is the current filter set on the service
      //update map graphic to show current spatial filter
      var bbox = evt.filter.geometry;
      map.graphics.clear();
      if (bbox) {
        map.graphics.add(new Graphic(bbox,
          new SimpleFillSymbol(SimpleFillSymbol.STYLE_NULL,
            new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID,
              new Color([5, 112, 176]), 2),
            new Color([5, 112, 176, 0]))));
      }
    }

    /************************************************
     *
     * Functions to set and clear spatial filter
     *
     ************************************************/
    function toggleSpatialFilter() {
      var currentSpatialFilter = null;
      if (streamLayer) {
        currentSpatialFilter = streamLayer.getFilter().geometry;
      }
      if (!currentSpatialFilter) {
        drawTools.activate(Draw.EXTENT);
      } else {
        setSpatialFilter(null);
        dojo.byId("cmdToggleSpatialFilter").value = "Draw Extent";
      }
    }

    //Set spatial filter on stream layer. Setting to null clears filter
    function setSpatialFilter(bbox) {
      if (streamLayer) {
        streamLayer.setGeometryDefinition(bbox);
      }
    }

    init();
  });
</script>

</html>