Select to view content in your preferred language

how to control polyline width in FeatureLayer

886
2
Jump to solution
05-27-2022 03:32 AM
zhedream
Emerging Contributor

zhedream_0-1653645295376.png 

There are some polylines here. I want to click it to highlight it and make it wider. I have found a method to highlight it, but I don't know how to make this polyline wider 

https://codepen.io/zhedream/pen/WNMdMOW?editors=1000 

 


// 渲染器
let renderer = jsonUtils.fromJSON({
"type": "classBreaks",
"field": "Name",
"defaultSymbol": {
"type": "esriSLS",
"color": [0, 0, 0, 255],
"width": 6
},
"visualVariables": [
{
"type": "color",
"field": "value",
"stops": [
{
width: 10,
"color": [0, 255, 0, 255],
"value": 0
},
{
width: 20,
"color": [163, 255, 52, 255],
"value": 20
},
{
width: 30,
"color": [236, 255, 18, 255],
"value": 30
}
]
}
]
});
Spoiler


// generate polyline
let data = [
{ value: 1, width: 6, active: 1 },
{ value: 10, width: 6, active: 0 },
{ value: 20, width: 6, active: 0 },
{ value: 30, width: 6, active: 0 }
];
let firstCoor = [-111.3, 52.68];
let polylineList = [];
data.forEach((v, index) => {

let nextCoor = [firstCoor[0] + 1, firstCoor[1] + 1];

polylineList.push({
geometry: {
type: "polyline", // autocasts as new Polyline()
paths: [
firstCoor,
nextCoor
]
},
// symbol: lineSymbol, // i think this is the symbol should override the renderer symbol, but not
attributes: {
value: v.value,
width: v.width,
active: v.active
}
});

firstCoor = nextCoor.slice(0);

});



// 图层
let fLayer = new FeatureLayer({
fields: fields,
objectIdField: "objectId",
source: polylineList,
geometryType: "polyline",
title: "layerId",
id: "layerId",
spatialReference: {
wkid: 4326
},
renderer: renderer
});

 

 

zhedream_1-1653646846951.png

 

 I tried applyEdits.updateFeatures to modify it, but it didn't work 

// is ok
map.layers.items[0].source.items[0].geometry = {
type: "polyline",
paths: [
[-111.3, 52.68],
[-120, 49.5]
]
};

// width not work
graphic = map.layers.items[0].source.items[0];
graphic.symbol = {
type: "simple-line", // autocasts as SimpleLineSymbol()
width: 40
};

 

 

0 Kudos
1 Solution

Accepted Solutions
JeffreyWilkerson
Frequent Contributor

I'm not sure if you can mess with what's already there, but you could add a temporary graphic over the top, and remove it if the click is anywhere else. This works but could use some help in making it the same color scheme:

<html>
<head>
  <meta charset="utf-8" />
  <meta
    content="initial-scale=1,maximum-scale=1,user-scalable=no"
    name="viewport"
  />
  <title>Intro to graphics | Sample | ArcGIS API for JavaScript 4.23</title>

  <link
    href="https://js.arcgis.com/4.23/esri/themes/light/main.css"
    rel="stylesheet"
  />
  <script src="https://js.arcgis.com/4.23/"></script>

  <style>
      html,
      body,
      #viewDiv {
          padding: 0;
          margin: 0;
          height: 100%;
          width: 100%;
      }
  </style>

  <script>
    var liness;
    require([
      "esri/Map",
      "esri/views/MapView",
      "esri/Graphic",
      "esri/layers/FeatureLayer",
      "esri/renderers/support/jsonUtils",
      "dojo/_base/connect"
    ], (Map, MapView, Graphic, FeatureLayer, jsonUtils, dc) => {
      window.map = new Map({
        basemap: "hybrid"
      });

      window.view = new MapView({
        center: [-80, 35],
        container: "viewDiv",
        map: map,
        zoom: 3
      });

      /****************************
       * Create a polyline graphic
       ****************************/

      const polyline = {
        type: "polyline", // autocasts as new Polyline()
        paths: [
          [-111.3, 52.68],
          [-98, 49.5]
        ]
      };

      // 样式符号
      var lineSymbol = {
        type: "simple-line", // autocasts as SimpleLineSymbol()
        color: [226, 119, 40],
        width: 20
      };
      liness = lineSymbol;
      console.log(lineSymbol);

      // generate polyline
      let data = [
        { value: 1, width: 6, active: 1 },
        { value: 10, width: 6, active: 0 },
        { value: 20, width: 6, active: 0 },
        { value: 30, width: 6, active: 0 }
      ];
      let firstCoor = [-111.3, 52.68];
      let polylineList = [];
      data.forEach((v, index) => {

        let nextCoor = [firstCoor[0] + 1, firstCoor[1] + 1];

        polylineList.push({
          geometry: {
            type: "polyline", // autocasts as new Polyline()
            paths: [
              firstCoor,
              nextCoor
            ]
          },
          // symbol: lineSymbol, // i think this is the symbol should override the renderer symbol, but not
          attributes: {
            value: v.value,
            width: v.width,
            active: v.active
          }
        });

        firstCoor = nextCoor.slice(0);

      });

      // 渲染器 style
      let renderer = jsonUtils.fromJSON({
        "type": "classBreaks",
        "field": "Name",
        "defaultSymbol": {
          "type": "esriSLS",
          "color": [0, 0, 0, 255],
          "width": 6
        },
        "visualVariables": [
          {
            "type": "color",
            "field": "value",
            "stops": [
              {
                width: 10,
                "color": [0, 255, 0, 255],
                "value": 0
              },
              {
                width: 20,
                "color": [163, 255, 52, 255],
                "value": 20
              },
              {
                width: 30,
                "color": [236, 255, 18, 255],
                "value": 30
              }
            ]
          }
        ]
      });
      // 属性字段
      let fields = [
        {
          name: "objectId",
          alias: "objectId",
          type: "oid"
        },
        {
          name: "value",
          alias: "value",
          type: "double"
        },
        {
          name: "active",
          alias: "active",
          type: "integer"
        }
      ];
      // 图层
      let fLayer = new FeatureLayer({
        fields: fields,
        objectIdField: "objectId",
        source: polylineList,
        geometryType: "polyline",
        title: "layerId",
        id: "layerId",
        spatialReference: {
          wkid: 4326
        },
        renderer: renderer
      });
      
      let polylineHighlightSymbol = {
        type: "simple-line",  // autocasts as SimpleLineSymbol()
        color: [226, 119, 40],
        width: 10
      };

      map.add(fLayer);

      // dc.connect(fLayer, "onMouseOver", () => {
      //   console.log("asdasd");
      // });

      let unHighLight = null;
      var highlightGraphic;
      view.on("click", (e) => {

        if (unHighLight && unHighLight.remove) {
          unHighLight.remove();
        }
        view.hitTest(e).then(function(response) {
          let results = response.results;
          console.log("results", results);
          if (highlightGraphic != null) {
            view.graphics.remove(highlightGraphic);
          }
          if (results.length > 0) {
            let graphic = results[0].graphic;
            highlightGraphic = new Graphic({
              geometry: graphic.geometry,
              symbol: polylineHighlightSymbol
            });
            view.graphics.add(highlightGraphic);
            
            view.whenLayerView(graphic.layer).then(function(viewLayer) {
              unHighLight = viewLayer.highlight(graphic);
            });

            console.log(graphic.attributes);
          }
          else {
            view.graphics.remove(highlightGraphic);
          }
        });


      });

      fLayer.when(() => {
        console.log("loaded");
      });

    });
  </script>
</head>

<body>
<div id="viewDiv" style="height: calc(100vh - 100px)"></div>
<button onclick="change()">change first polyline</button>

<script>


  function change() {


    map.layers.items[0].source.items[0].setAttribute("value", 19);


    map.layers.items[0].source.items[0].setAttribute("width", 20);
    map.layers.items[0].source.items[0].setAttribute("active", 1);
    map.layers.items[0].source.items[0].visible = false;



    // is ok
    map.layers.items[0].source.items[0].geometry = {
      type: "polyline",
      paths: [
        [-111.3, 52.68],
        [-120, 49.5]
      ]
    };

    // not work
    graphic = map.layers.items[0].source.items[0];
    graphic.symbol = {
      type: "simple-line", // autocasts as SimpleLineSymbol()
      width: 40
    };


    map.layers.items[0].applyEdits({
      // deleteFeatures: [
      //   {
      //     objectId: 1
      //   }
      // ]
      updateFeatures: map.layers.items[0].source.items
      // updateFeatures: [
      //   {
      //     objectId: 1,
      //     geometry: {
      //       type: "polyline",
      //       paths: [
      //         [-111.3, 52.68],
      //         [-100, 49.5]
      //       ]
      //     }
      //   }
      // ]
    });

  }


</script>
</body>
</html>

View solution in original post

2 Replies
JeffreyWilkerson
Frequent Contributor

I'm not sure if you can mess with what's already there, but you could add a temporary graphic over the top, and remove it if the click is anywhere else. This works but could use some help in making it the same color scheme:

<html>
<head>
  <meta charset="utf-8" />
  <meta
    content="initial-scale=1,maximum-scale=1,user-scalable=no"
    name="viewport"
  />
  <title>Intro to graphics | Sample | ArcGIS API for JavaScript 4.23</title>

  <link
    href="https://js.arcgis.com/4.23/esri/themes/light/main.css"
    rel="stylesheet"
  />
  <script src="https://js.arcgis.com/4.23/"></script>

  <style>
      html,
      body,
      #viewDiv {
          padding: 0;
          margin: 0;
          height: 100%;
          width: 100%;
      }
  </style>

  <script>
    var liness;
    require([
      "esri/Map",
      "esri/views/MapView",
      "esri/Graphic",
      "esri/layers/FeatureLayer",
      "esri/renderers/support/jsonUtils",
      "dojo/_base/connect"
    ], (Map, MapView, Graphic, FeatureLayer, jsonUtils, dc) => {
      window.map = new Map({
        basemap: "hybrid"
      });

      window.view = new MapView({
        center: [-80, 35],
        container: "viewDiv",
        map: map,
        zoom: 3
      });

      /****************************
       * Create a polyline graphic
       ****************************/

      const polyline = {
        type: "polyline", // autocasts as new Polyline()
        paths: [
          [-111.3, 52.68],
          [-98, 49.5]
        ]
      };

      // 样式符号
      var lineSymbol = {
        type: "simple-line", // autocasts as SimpleLineSymbol()
        color: [226, 119, 40],
        width: 20
      };
      liness = lineSymbol;
      console.log(lineSymbol);

      // generate polyline
      let data = [
        { value: 1, width: 6, active: 1 },
        { value: 10, width: 6, active: 0 },
        { value: 20, width: 6, active: 0 },
        { value: 30, width: 6, active: 0 }
      ];
      let firstCoor = [-111.3, 52.68];
      let polylineList = [];
      data.forEach((v, index) => {

        let nextCoor = [firstCoor[0] + 1, firstCoor[1] + 1];

        polylineList.push({
          geometry: {
            type: "polyline", // autocasts as new Polyline()
            paths: [
              firstCoor,
              nextCoor
            ]
          },
          // symbol: lineSymbol, // i think this is the symbol should override the renderer symbol, but not
          attributes: {
            value: v.value,
            width: v.width,
            active: v.active
          }
        });

        firstCoor = nextCoor.slice(0);

      });

      // 渲染器 style
      let renderer = jsonUtils.fromJSON({
        "type": "classBreaks",
        "field": "Name",
        "defaultSymbol": {
          "type": "esriSLS",
          "color": [0, 0, 0, 255],
          "width": 6
        },
        "visualVariables": [
          {
            "type": "color",
            "field": "value",
            "stops": [
              {
                width: 10,
                "color": [0, 255, 0, 255],
                "value": 0
              },
              {
                width: 20,
                "color": [163, 255, 52, 255],
                "value": 20
              },
              {
                width: 30,
                "color": [236, 255, 18, 255],
                "value": 30
              }
            ]
          }
        ]
      });
      // 属性字段
      let fields = [
        {
          name: "objectId",
          alias: "objectId",
          type: "oid"
        },
        {
          name: "value",
          alias: "value",
          type: "double"
        },
        {
          name: "active",
          alias: "active",
          type: "integer"
        }
      ];
      // 图层
      let fLayer = new FeatureLayer({
        fields: fields,
        objectIdField: "objectId",
        source: polylineList,
        geometryType: "polyline",
        title: "layerId",
        id: "layerId",
        spatialReference: {
          wkid: 4326
        },
        renderer: renderer
      });
      
      let polylineHighlightSymbol = {
        type: "simple-line",  // autocasts as SimpleLineSymbol()
        color: [226, 119, 40],
        width: 10
      };

      map.add(fLayer);

      // dc.connect(fLayer, "onMouseOver", () => {
      //   console.log("asdasd");
      // });

      let unHighLight = null;
      var highlightGraphic;
      view.on("click", (e) => {

        if (unHighLight && unHighLight.remove) {
          unHighLight.remove();
        }
        view.hitTest(e).then(function(response) {
          let results = response.results;
          console.log("results", results);
          if (highlightGraphic != null) {
            view.graphics.remove(highlightGraphic);
          }
          if (results.length > 0) {
            let graphic = results[0].graphic;
            highlightGraphic = new Graphic({
              geometry: graphic.geometry,
              symbol: polylineHighlightSymbol
            });
            view.graphics.add(highlightGraphic);
            
            view.whenLayerView(graphic.layer).then(function(viewLayer) {
              unHighLight = viewLayer.highlight(graphic);
            });

            console.log(graphic.attributes);
          }
          else {
            view.graphics.remove(highlightGraphic);
          }
        });


      });

      fLayer.when(() => {
        console.log("loaded");
      });

    });
  </script>
</head>

<body>
<div id="viewDiv" style="height: calc(100vh - 100px)"></div>
<button onclick="change()">change first polyline</button>

<script>


  function change() {


    map.layers.items[0].source.items[0].setAttribute("value", 19);


    map.layers.items[0].source.items[0].setAttribute("width", 20);
    map.layers.items[0].source.items[0].setAttribute("active", 1);
    map.layers.items[0].source.items[0].visible = false;



    // is ok
    map.layers.items[0].source.items[0].geometry = {
      type: "polyline",
      paths: [
        [-111.3, 52.68],
        [-120, 49.5]
      ]
    };

    // not work
    graphic = map.layers.items[0].source.items[0];
    graphic.symbol = {
      type: "simple-line", // autocasts as SimpleLineSymbol()
      width: 40
    };


    map.layers.items[0].applyEdits({
      // deleteFeatures: [
      //   {
      //     objectId: 1
      //   }
      // ]
      updateFeatures: map.layers.items[0].source.items
      // updateFeatures: [
      //   {
      //     objectId: 1,
      //     geometry: {
      //       type: "polyline",
      //       paths: [
      //         [-111.3, 52.68],
      //         [-100, 49.5]
      //       ]
      //     }
      //   }
      // ]
    });

  }


</script>
</body>
</html>
zhedream
Emerging Contributor

 

      view.on("click", (e) => {
        if (unHighLight) {
          unHighLight();
          unHighLight = null;
        }
        view.hitTest(e).then(function(response) {
          let results = response.results;
          let graphics = results.filter(function(result) {
            // check if the graphic belongs to the layer of interest
            return result.graphic.layer === fLayer;
          })
      
          if (graphics.length > 0) {
            let graphic = graphics[0].graphic;
            highlightGraphic = new Graphic({
              geometry: graphic.geometry,
              symbol: polylineHighlightSymbol
            });
            view.graphics.add(highlightGraphic);
            view.whenLayerView(graphic.layer).then(function(viewLayer) {
              // let highLight = viewLayer.highlight(graphic);
              unHighLight = () => {
                // highLight.remove();
                if (highlightGraphic) {
                  view.graphics.remove(highlightGraphic);
                  highlightGraphic = null;
                }
              }
            });
          } else {}
        });
      });

This is a very good idea. It can basically achieve the effect I want - to overwrite the original figure with a new figure 

There's a little problem. I don't know how to highlight the new graphics. It would be perfect if I could

0 Kudos