Render list of CIM Symbols in Web Style

453
2
11-07-2022 01:32 PM
JoshGore
New Contributor III

I'd like to render a list of every symbol in a web style, similar to the sketch widget in the Map Viewer. I've tried creating a list of web style symbols and then using fetchCIMSymbol to get the related data, fetched symbols are then used by renderPreviewHTML.

Is there a better way of doing this? My current method is quite slow as each 'fetchCIMSymbol' call will go off and fetch the style item data, so the fetchCIMSymbol calls don't run in parallel.

 

const itemId = "1fbb242c54e4415d9b8e8a343ca7a9d0";
const item = new PortalItem({ id: itemId });
await item.load();
const itemData = await item.fetchData();
const symbolNames = itemData.items.map((item) => item.name);
const styleUrl =
  "https://local-maps.maps.arcgis.com/sharing/rest/content/items/1fbb242c54e4415d9b8e8a343ca7a9d0/data";
// const firstSymbol = await new WebStyleSymbol({
//   styleUrl,
//   name: symbolNames[0],
// }).fetchCIMSymbol();
const symbols = await Promise.all(
  symbolNames.map((name) => new WebStyleSymbol({ styleUrl, name }))
);

 




Tags (2)
0 Kudos
2 Replies
AnneFitz
Esri Regular Contributor

Hi @JoshGore - If your Web Style symbols have a thumbnail defined, you can just load those as the preview initially, and then convert the symbol to a CIMSymbol once the user selects the symbol in your styler widget. This might be faster than converting them all to CIM symbols initially.

function initializeWebStyles() {
  esriRequest(styleUrl + "/data", {
     responseType: "json"
  }).then(function (response) {
     response.data.items.forEach((item, index) => {
       let card = document.createElement("calcite-card");
       let cardImage = document.createElement("img");
       // use the webstyle symbol thumbnail to populate the card image
       cardImage.src=styleUrl + item.thumbnail.href.substring(1);
       cardImage.width = 50;
       card.appendChild(cardImage);
       card.style.width = "75px";
       // update the symbol when the item is clicked
       card.addEventListener("click", () => updateWebStyle(item.name));
       document.getElementById("styles").appendChild(card);
     });
   });
}

That snippet can be found in this sample in our documentation: https://developers.arcgis.com/javascript/latest/sample-code/cim-marker-placement/

 

0 Kudos
JoshGore
New Contributor III

Thanks Anne, I'd missed that sample!
I got around the above by using the undocumented "webStyleSymbolUtils" as follows:

 

  fetchSymbols = async () => {
    const data = await this.portalItem.fetchData();
    const symbols = await Promise.all(
      data.items.map(async item => {
        const webSymbol = new WebStyleSymbol({
          styleUrl: `${this.portalItem.itemUrl}/data`,
          name: item.name,
        });
        // const symbol = await webSymbol.fetchCIMSymbol();
        const symbol = await webStyleSymbolUtils.fetchSymbolFromStyle(
          {
            data,
            baseUrl: this.portalItem.itemUrl,
            styleUrl: `${this.portalItem.itemUrl}/data`,
          },
          item.name,
          { portal: this.portalItem.portal },
          'cimRef',
        );
        return { symbol, name: webSymbol.name };
      }),
    );
    return symbols;
  };
0 Kudos