How can I use a dynamic SVG as graphic in FeatureLayer (ArcGIS JS API 4.x)

2362
6
04-13-2021 09:41 AM
RoelGarcia08
New Contributor II

Hi All,

I am trying to use a SVG dynamically (based on attributes) as graphic in FeatureLayer with version 4.x . I have an example that uses 3.x overriding the renderer.getSymbol method.

3.x sample.

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">
<title>FeatureLayer 3.x</title>

<link rel="stylesheet" href="https://js.arcgis.com/3.22/esri/css/esri.css">
<script src="https://js.arcgis.com/3.22/"></script>

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

<script>
require([
    "esri/map",
    "esri/layers/FeatureLayer",
    "esri/renderers/SimpleRenderer",
    "esri/symbols/PictureMarkerSymbol",
    "dojo/domReady!"
  ],
  function(
    Map,
    FeatureLayer,
    SimpleRenderer,
    PictureMarkerSymbol
  ) {
    // THIS SHOULD BE DYNAMIC SVG BASED ON THE GRAPHIC ATTRIBUTES
    var svg = `data&colon;image/svg+xml;base64,PHN2ZyB3aWR0aD0nMTY4JyBoZWlnaHQ9JzUwJyB2aWV3Qm94PScwIDAgMTEwIDYyJyBmaWxsPSdub25lJyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnPgogICAgICA8c3R5bGU+CiAgICAgICAuYmcgewogICAgICAgIHRyYW5zZm9ybTogc2NhbGVYKDAuNzUpCiAgICAgICB9CiAgICAgIDwvc3R5bGU+CiAgICAgIDxnIGZpbHRlcj0ndXJsKCNmaWx0ZXIwX2QpJyBjbGFzcz0nYmcnPgogICAgICAgIDxwYXRoIGZpbGwtcnVsZT0nZXZlbm9kZCcgY2xpcC1ydWxlPSdldmVub2RkJyBkPSdNMTQgOEMxMS43OTA5IDggMTAgOS43OTA4NiAxMCAxMlY0MS44NjNDMTAgNDQuMDcyMSAxMS43OTA5IDQ1Ljg2MyAxNCA0NS44NjNINzAuNjM1NUw3NC44OTEyIDUxLjAyNzRDNzQuOTkzMiA1MS4xNTExIDc1LjEyOCA1MS4yNTY0IDc1LjI4NjUgNTEuMzM2Qzc1Ljg5ODkgNTEuNjQzOCA3Ni43MTQ4IDUxLjUwNTYgNzcuMTA4OSA1MS4wMjc0TDgxLjM2NDcgNDUuODYzSDEzNEMxMzYuMjA5IDQ1Ljg2MyAxMzggNDQuMDcyMSAxMzggNDEuODYzVjEyQzEzOCA5Ljc5MDg2IDEzNi4yMDkgOCAxMzQgOEgxNFonIGZpbGw9JyNGRkZGRkYnIC8+CiAgICAgIDwvZz4KICAgICAgCiAgICA8c3R5bGU+LmxhYmVsIHsKICBmb250LWZhbWlseTogQXJpYWwsIEhlbHZldGljYSwgc2Fucy1zZXJpZjsKICBmb250LXdlaWdodDogNTAwOwogIGZvbnQtc3R5bGU6IG5vcm1hbDsKICBmb250LXNpemU6IDEzcHg7CiAgbGluZS1oZWlnaHQ6IDE4cHg7CiAgYWxpZ24taXRlbXM6IGNlbnRlcjsKICB0ZXh0LWFsaWduOiBjZW50ZXI7CiAgbGV0dGVyLXNwYWNpbmc6IDFweDsKICB0ZXh0LXRyYW5zZm9ybTogdXBwZXJjYXNlOwogZmlsbDogIzAwMDAwMH08L3N0eWxlPgogICAgPHRleHQgeD0nNjAnIHk9JzMwJyB0ZXh0LWFuY2hvcj0nbWlkZGxlJyBjbGFzcz0nbGFiZWwnPkVGLVVJPC90ZXh0PgogIAogICAgICA8c3ZnIHg9Jy05Jz4KICAgICAgICA8cGF0aCBkPSdNMzIuMDE0OSAyMC42MjExSDIzLjAwNjVDMjIuNzM5NiAyMC42MjExIDIyLjQ4MzYgMjAuNzM2MyAyMi4yOTQ4IDIwLjk0MTRDMjIuMTA2IDIxLjE0NjUgMjIgMjEuNDI0NiAyMiAyMS43MTQ2VjI5Ljc3NDJDMjIgMjkuOTE3NyAyMi4wMjYxIDMwLjA1OTcgMjIuMDc2NyAzMC4xOTIyQzIyLjEyNzMgMzAuMzI0NyAyMi4yMDE1IDMwLjQ0NTEgMjIuMjk1IDMwLjU0NjRDMjIuMzg4NSAzMC42NDc3IDIyLjQ5OTUgMzAuNzI3OSAyMi42MjE2IDMwLjc4MjZDMjIuNzQzNyAzMC44MzcyIDIyLjg3NDUgMzAuODY1MSAyMy4wMDY1IDMwLjg2NDdIMjQuNTg1TDI0LjYxMzEgMzAuNzg4NUMyNC43MjU0IDMwLjQ0MTYgMjQuOTM0IDMwLjE0MTEgMjUuMjEwMiAyOS45Mjg1QzI1LjQ4NjUgMjkuNzE1OSAyNS44MTY2IDI5LjYwMTcgMjYuMTU1MSAyOS42MDE3QzI2LjQ5MzYgMjkuNjAxNyAyNi44MjM4IDI5LjcxNTkgMjcuMSAyOS45Mjg1QzI3LjM3NjMgMzAuMTQxMSAyNy41ODQ5IDMwLjQ0MTYgMjcuNjk3MiAzMC43ODg1TDI3LjcyMjQgMzAuODY0N0gzMi4wMjMzQzMyLjA2NDQgMzAuODY3NyAzMi4xMDU2IDMwLjg2NzcgMzIuMTQ2NyAzMC44NjQ3SDMzLjAyOTlWMjMuNDYzVjIxLjcyNjhDMzMuMDMxNCAyMS41ODE0IDMzLjAwNjIgMjEuNDM3MiAzMi45NTU3IDIxLjMwMjVDMzIuOTA1MyAyMS4xNjc4IDMyLjgzMDYgMjEuMDQ1NCAzMi43MzYxIDIwLjk0MjRDMzIuNjQxNiAyMC44Mzk1IDMyLjUyOTEgMjAuNzU4IDMyLjQwNTMgMjAuNzAyOUMzMi4yODE1IDIwLjY0NzcgMzIuMTQ4OCAyMC42MTk5IDMyLjAxNDkgMjAuNjIxMVonIGZpbGw9JyNCREJEQkQnLz4KICA8cGF0aCBkPSdNMjYuMTY1OSAzMi43MzU5QzI2LjgzOTUgMzIuNzM1OSAyNy4zODU1IDMyLjE0MjcgMjcuMzg1NSAzMS40MTA5QzI3LjM4NTUgMzAuNjc5MiAyNi44Mzk1IDMwLjA4NTkgMjYuMTY1OSAzMC4wODU5QzI1LjQ5MjMgMzAuMDg1OSAyNC45NDYzIDMwLjY3OTIgMjQuOTQ2MyAzMS40MTA5QzI0Ljk0NjMgMzIuMTQyNyAyNS40OTIzIDMyLjczNTkgMjYuMTY1OSAzMi43MzU5WicgZmlsbD0nI0JEQkRCRCcvPgogIDxwYXRoIGQ9J00zNi4zNzM5IDMyLjczNTlDMzcuMDQ3NSAzMi43MzU5IDM3LjU5MzUgMzIuMTQyNyAzNy41OTM1IDMxLjQxMDlDMzcuNTkzNSAzMC42NzkyIDM3LjA0NzUgMzAuMDg1OSAzNi4zNzM5IDMwLjA4NTlDMzUuNzAwMyAzMC4wODU5IDM1LjE1NDMgMzAuNjc5MiAzNS4xNTQzIDMxLjQxMDlDMzUuMTU0MyAzMi4xNDI3IDM1LjcwMDMgMzIuNzM1OSAzNi4zNzM5IDMyLjczNTlaJyBmaWxsPScjQkRCREJEJy8+CiAgPHBhdGggZmlsbC1ydWxlPSdldmVub2RkJyBjbGlwLXJ1bGU9J2V2ZW5vZGQnIGQ9J00zMy43NTEgMjMuNDYzMlYzMC44NTI5SDM0Ljc1MkwzNC43NzQ0IDMwLjc4ODlDMzQuODkwNiAzMC40MzMgMzUuMTA1NCAzMC4xMjQ5IDM1LjM4OTQgMjkuOTA3QzM1LjY3MzMgMjkuNjg5MSAzNi4wMTIzIDI5LjU3MjEgMzYuMzYgMjkuNTcyMUMzNi43MDc2IDI5LjU3MjEgMzcuMDQ2NiAyOS42ODkxIDM3LjMzMDYgMjkuOTA3QzM3LjYxNDUgMzAuMTI0OSAzNy44MjkzIDMwLjQzMyAzNy45NDU1IDMwLjc4ODlMMzcuOTY3OSAzMC44NTI5SDM5LjczOTlDMzkuODA4NSAzMC44NTI5IDM5Ljg3NDQgMzAuODIzNCAzOS45MjMyIDMwLjc3MUMzOS45NzIxIDMwLjcxODUgMzkuOTk5OSAzMC42NDcyIDQwLjAwMDYgMzAuNTcyNlYyNy4zODM1QzQwLjAwMDkgMjcuMzEyMSAzOS45NzU3IDI3LjI0MzQgMzkuOTMwNSAyNy4xOTE2TDM3LjQ2ODggMjMuNjczNUMzNy40MDk0IDIzLjYwMyAzNy4zMzcgMjMuNTQ2OCAzNy4yNTY0IDIzLjUwODVDMzcuMTc1NyAyMy40NzAzIDM3LjA4ODYgMjMuNDUwNyAzNy4wMDA2IDIzLjQ1MTJIMzMuNzUxVjIzLjQ2MzJaJyBmaWxsPScjQkRCREJEJy8+CiAgICAgIDwvc3ZnPgogICAgICA8ZWxsaXBzZSBjeD0nOTMnIGN5PScyNi45MzA2JyByeD0nNScgcnk9JzUuMjU4NzUnICBmaWxsPScjQkRCREJEJy8+CiAgICAgIDxkZWZzPgogICAgICAgIDxmaWx0ZXIgaWQ9J2ZpbHRlcjBfZCcgeD0nMCcgeT0nMCcgd2lkdGg9JzE2OCcgaGVpZ2h0PSc1MCcgZmlsdGVyVW5pdHM9J3VzZXJTcGFjZU9uVXNlJyBjb2xvci1pbnRlcnBvbGF0aW9uLWZpbHRlcnM9J3NSR0InPgogICAgICAgICAgPGZlRmxvb2QgZmxvb2Qtb3BhY2l0eT0nMCcgcmVzdWx0PSdCYWNrZ3JvdW5kSW1hZ2VGaXgnLz4KICAgICAgICAgIDxmZUNvbG9yTWF0cml4IGluPSdTb3VyY2VBbHBoYScgdHlwZT0nbWF0cml4JyB2YWx1ZXM9JzAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDEyNyAwJy8+CiAgICAgICAgICA8ZmVPZmZzZXQgZHk9JzInLz4KICAgICAgICAgIDxmZUdhdXNzaWFuQmx1ciBzdGREZXZpYXRpb249JzUnLz4KICAgICAgICAgIDxmZUNvbG9yTWF0cml4IHR5cGU9J21hdHJpeCcgdmFsdWVzPScwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwLjIgMCcvPgogICAgICAgICAgPGZlQmxlbmQgbW9kZT0nbm9ybWFsJyBpbjI9J0JhY2tncm91bmRJbWFnZUZpeCcgcmVzdWx0PSdlZmZlY3QxX2Ryb3BTaGFkb3cnLz4KICAgICAgICAgIDxmZUJsZW5kIG1vZGU9J25vcm1hbCcgaW49J1NvdXJjZUdyYXBoaWMnIGluMj0nZWZmZWN0MV9kcm9wU2hhZG93JyByZXN1bHQ9J3NoYXBlJy8+CiAgICAgICAgPC9maWx0ZXI+CiAgICAgIDwvZGVmcz4KICAgIDwvc3ZnPg==`;
    var map = new Map("map", {
      basemap: "hybrid",
      center: [-82.44109, 35.6122],
      zoom: 17
    });

    var featureLayer = new FeatureLayer("https://services.arcgis.com/V6ZHFr6zdgNZuVG0/arcgis/rest/services/Landscape_Trees/FeatureServer/0");

    map.addLayer(featureLayer);
    
    var renderer = new SimpleRenderer();
    renderer.getSymbol = function(graphic){
      var sym = new PictureMarkerSymbol(svg, 240, 50);
      return sym;
    }
    
    featureLayer.setRenderer(renderer);
  });
</script>
</head>

<body>
  <div id="map"></div>
</body>

</html>


I would appreciate any guidance on how I can do the same in version 4.x.

Thank you so much!!,

Roel

0 Kudos
6 Replies
UndralBatsukh
Esri Regular Contributor

Hi there, 

This should work as long as you are NOT using animated svg. Please take a look at the known limitation for PictureMarkerSymbol for svg limitations. If you are using animated svg... then it will not work as stated in the known limitation. You can instead use animated png or webp formats.

In any case, the svg you provided is not working. You can do it as shown below:

 

 

const featureLayer = new FeatureLayer({
          url:
            "https://sampleserver6.arcgisonline.com/arcgis/rest/services/USA/MapServer/0",
          renderer: {
            type: "simple",
            symbol: {
              type: "picture-marker",
              url:
                "data&colon;image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjwhLS0gR2VuZXJhdG9yOiBBZG9iZSBJbGx1c3RyYXRvciAxNi4wLjAsIFNWRyBFeHBvcnQgUGx1Zy1JbiAuIFNWRyBWZXJzaW9uOiA2LjAwIEJ1aWxkIDApICAtLT4NCjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+DQo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9IkxheWVyXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4Ig0KCSB3aWR0aD0iMTI2cHgiIGhlaWdodD0iMTI2cHgiIHZpZXdCb3g9IjAgMCAxMjYgMTI2IiBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDAgMCAxMjYgMTI2IiB4bWw6c3BhY2U9InByZXNlcnZlIj4NCjxnPg0KCTxyZWN0IHg9IjEuMDk1IiB5PSI5OC4yMjQiIHdpZHRoPSIxMjMuODEiIGhlaWdodD0iMTkuMjc1Ii8+DQoJPHJlY3QgeD0iMS4wOTUiIHk9Ijg1Ljc0IiB3aWR0aD0iMTIzLjgxIiBoZWlnaHQ9IjUuMjA1Ii8+DQoJPHBhdGggZD0iTTE4LjQwNCw5NS43MjFjMC43NjcsMCwxLjM4OS0wLjYyMywxLjM4OS0xLjM5cy0wLjYyMi0xLjM4OC0xLjM4OS0xLjM4OEgzLjQ4MWMtMC43NjcsMC0xLjM4OCwwLjYyMS0xLjM4OCwxLjM4OA0KCQlzMC42MjIsMS4zOSwxLjM4OCwxLjM5SDE4LjQwNHoiLz4NCgk8cGF0aCBkPSJNNDQuNDMzLDk1LjcyMWMwLjc2NywwLDEuMzg4LTAuNjIzLDEuMzg4LTEuMzlzLTAuNjIyLTEuMzg4LTEuMzg4LTEuMzg4SDI5LjUxYy0wLjc2NywwLTEuMzg5LDAuNjIxLTEuMzg5LDEuMzg4DQoJCXMwLjYyMiwxLjM5LDEuMzg5LDEuMzlINDQuNDMzeiIvPg0KCTxwYXRoIGQ9Ik03MC40NjEsOTUuNzIxYzAuNzY3LDAsMS4zODgtMC42MjMsMS4zODgtMS4zOXMtMC42MjItMS4zODgtMS4zODgtMS4zODhINTUuNTM5Yy0wLjc2NywwLTEuMzg4LDAuNjIxLTEuMzg4LDEuMzg4DQoJCXMwLjYyMiwxLjM5LDEuMzg4LDEuMzlINzAuNDYxeiIvPg0KCTxwYXRoIGQ9Ik05Ni40OSw5NS43MjFjMC43NjcsMCwxLjM4OS0wLjYyMywxLjM4OS0xLjM5cy0wLjYyMi0xLjM4OC0xLjM4OS0xLjM4OEg4MS41NjdjLTAuNzY3LDAtMS4zODgsMC42MjEtMS4zODgsMS4zODgNCgkJczAuNjIyLDEuMzksMS4zODgsMS4zOUg5Ni40OXoiLz4NCgk8cGF0aCBkPSJNMTIyLjUxOSw5NS43MjFjMC43NjcsMCwxLjM4OS0wLjYyMywxLjM4OS0xLjM5cy0wLjYyMi0xLjM4OC0xLjM4OS0xLjM4OGgtMTQuOTIzYy0wLjc2NywwLTEuMzg4LDAuNjIxLTEuMzg4LDEuMzg4DQoJCXMwLjYyMiwxLjM5LDEuMzg4LDEuMzlIMTIyLjUxOXoiLz4NCgk8cGF0aCBkPSJNNy40MSw4MC45aDUzLjQ0MmMwLjg2MywwLDEuNTYyLTAuNjk5LDEuNTYyLTEuNTYyVjM5LjU0M2MwLTAuODYyLTAuNjk5LTEuNTYzLTEuNTYyLTEuNTYzSDQ1LjMxNHYtNi41MzkNCgkJYzAtMC44NjEtMC42OTgtMS41NjItMS41NjEtMS41NjJIMjMuNDI4Yy0wLjg2MywwLTEuNTYyLDAuNy0xLjU2MiwxLjU2MnY2LjU0SDcuNDFjLTAuODYyLDAtMS41NjIsMC43LTEuNTYyLDEuNTYzdjM5Ljc5NQ0KCQlDNS44NDgsODAuMjAxLDYuNTQ3LDgwLjksNy40MSw4MC45eiBNMzQuNDkyLDU3Ljg3NGgtMS43OTZ2LTYuNzY4aDEuNzk2VjU3Ljg3NHogTTI2LjU2MywzNC41NzRoMTQuMDU1djMuNDA2SDI2LjU2M1YzNC41NzR6DQoJCSBNMTAuNTQ0LDQyLjY3OGg0Ny4xNzN2MTEuOThIMzYuOTQydi00LjAwNmMwLTAuODYzLTAuNjk5LTEuNTYzLTEuNTYyLTEuNTYzaC0zLjU4MmMtMC44NjMsMC0xLjU2MiwwLjY5OS0xLjU2MiwxLjU2M3Y0LjAwNg0KCQlIMTAuNTQ0VjQyLjY3OHoiLz4NCgk8cGF0aCBkPSJNNjguNzM0LDgwLjloNDkuOTU4YzAuODA3LDAsMS40Ni0wLjY1MywxLjQ2LTEuNDZWMTcuNTM0YzAtMC44MDYtMC42NTMtMS40NTktMS40Ni0xLjQ1OWgtMTQuNTI0VjkuOTYxDQoJCWMwLTAuODA3LTAuNjUzLTEuNDYtMS40Ni0xLjQ2aC0xOWMtMC44MDcsMC0xLjQ2LDAuNjUzLTEuNDYsMS40NnY2LjExNUg2OC43MzRjLTAuODA3LDAtMS40NiwwLjY1My0xLjQ2LDEuNDU5Vjc5LjQ0DQoJCUM2Ny4yNzQsODAuMjQ3LDY3LjkyNyw4MC45LDY4LjczNCw4MC45eiBNODYuNjM4LDEyLjg5aDEzLjEzOXYzLjE4Nkg4Ni42MzhWMTIuODl6Ii8+DQo8L2c+DQo8L3N2Zz4NCg==",
              height: "32px",
              width: "32px"
            }
          }
        });

 

 

0 Kudos
RoelGarcia08
New Contributor II

Hi UndralBatsukh,

Thank you for replying to my post. I would like to create the SVG dynamically (on the fly) based on some attributes. 

Here some examples:

sample 1.JPG

sample 2.JPG

 * Increase the Width based on the label length

 * Displaying of different graphics based on some attributes (type, status, etc) 

Thank you so much!!

0 Kudos
ReneRubalcava
Frequent Contributor

This is something that would be better suited for CIMSymbol, as it can be defined based on attributes. This blog post covers some of this in more detail.

RoelGarcia08
New Contributor II

Hi Rene,

Do you have an example (Code) more specific for what I like to do?

Thank you,

Roel

0 Kudos
UndralBatsukh
Esri Regular Contributor

Hi there, 

You maybe better of using DictionaryRenderer in this case. Here is a sample that shows how to use dictionary renderer: https://developers.arcgis.com/javascript/latest/sample-code/visualization-dictionary/

RoelGarcia08
New Contributor II

Hi Undral,

Do you have an example more specific for what I like to do? Can we increase the width of the web style (shape, background icon) dynamically based on the label or text?

Like this:

RoelGarcia08_1-1618413295333.png

 

Thank you so much!!

Roel

0 Kudos