Can't create a Graphic with a PictureMarkerSymbol

270
4
02-22-2024 08:42 AM
JMMFIRE
New Contributor II

ESRI v4.27

I have an array of JSON I'm using to create an array of Graphics to add to my FeatureLayer. The basic structure looks like this: 

 

{
    "geometry": {
        "x": -8174819.943309489,
        "y": 5027492.84864396,
        "spatialReference": {
            "wkid": 102100,
            "latestWkid": 3857
        }
    },
    "attributes": {
        "groupId": 16,
        "Crash graphic": 17
    },
    "symbol": {
        "angle": 0,
        "xoffset": 0,
        "yoffset": 0,
        "type": "esriPMS",
        "url": "https://crsms-dev.uconn.edu/collision-diagram-images/icons/CrashSymbols/Black/FrontToRear.png",
        "width": 45,
        "height": 45
    }
}

 

 

I use this data to create a Graphic like so 

 

 

    private getGraphicFromLocal(graphic: any): Graphic {

        const markerSymbol = new PictureMarkerSymbol({
            width: graphic.symbol.width,
            height: graphic.symbol.height,
            url: graphic.symbol.url.replace('https://my-dev-server/collision-diagram-images/', '/assets/collision-diagram/'),
        })

        const localGraphic = {
            ...graphic,
            geometry: {
                ...graphic.geometry,
                type: 'point'
            },
            symbol: markerSymbol
        };

        return new Graphic(localGraphic);
    }

 

 

The URLs resolve fine but for some reason I get a simple point symbol instead of the image stored at the URL. Any insight?

Some background context - I was initially creating a GraphicsLayer instead of a FeatureLayer but because the Editor class isn't compatible with GraphicsLayers I chose to switch.

0 Kudos
4 Replies
ReneRubalcava
Frequent Contributor

When using graphics in a FeatureLayer, you can't apply symbology to the individual graphics, you need to use a renderer. More info in the Visualization guide.

https://developers.arcgis.com/javascript/latest/visualization/location-styles/#points

JMMFIRE
New Contributor II

I also messed with this approach like so and get the following result: 

const symbol = {
            type: 'picture-marker',
            url: '/assets/collision-diagram/icons/CrashSymbols/Black/SideswipeOppositeDirection.png',
            width: '24px',
            height: '24px' 
        };

        const crashRenderer = {
            type: 'unique-value',
            field: 'groupId',
            uniqueValueInfos: [{
                value: '16',
                symbol: symbol
            }]
        }

        const featureLayerProperties: __esri.FeatureLayerProperties = {
            source: graphicsArr,
            id: 'groupLayer',
            title: 'Group Layer',
            objectIdField: 'Crash graphic',
            renderer: crashRenderer as __esri.RendererProperties
        };


        this.collisionMap.addFeatureLayer(featureLayerProperties, mapView).catch((error: any) => console.error(error));

 

JMMFIRE_0-1708625162350.png


The symbol that's rendered is not the image the URL points to. Am I going about this wrong?

0 Kudos
ReneRubalcava
Frequent Contributor

Should it be changing that little red dot under New Haven? Tough to tell, it could be a path issue. You might want to look at the network tab and see if there are any errors. You might need to normalize the url to point to the real path with location.href or maybe import.meta.url, depending on your tooling.

0 Kudos
JMMFIRE
New Contributor II

Sorry for the confusion, here's the map with the other layers removed: 

JMMFIRE_0-1708628675174.png


The call to fetch the image is successful so that's working. I still can't figure out why the renderer isn't assigning the symbol to the feature. I modified my code a bit to create a new attribute that better describes each unique value. 

public addCollisionGraphicLayer(mapView: __esri.MapView): void {
        const graphicsArr = [];

        const groupJsonArr = this.mapStateObj.groupJson;

        console.log(groupJsonArr);


        groupJsonArr.forEach((graphic: string) => {
            const parsedGraphic = JSON.parse(graphic)
            if (this.environment.production) {
                graphicsArr.push(Graphic.fromJSON(parsedGraphic.shownGraphic));
            } else {
                const devGraphic = this.getGraphicFromLocal(parsedGraphic);
                console.log('dev graphic', devGraphic);


                graphicsArr.push(devGraphic);
            }

        });

        const symbol: __esri.PictureMarkerSymbolProperties = {
            url: '/assets/collision-diagram/icons/CrashSymbols/Black/FrontToRear.png',
            width: '200px',
            height: '200px' 
        };

        const crashRenderer = {
            type: 'unique-value',
            field: 'symbolType',
            uniqueValueInfos: [{
                value: 'Front to Rear',
                symbol: new PictureMarkerSymbol(symbol)
            }]
        }

        const featureLayerProperties: __esri.FeatureLayerProperties = {
            source: graphicsArr,
            id: 'groupLayer',
            title: 'Group Layer',
            objectIdField: 'crashId',
            renderer: crashRenderer as __esri.RendererProperties
        };


        this.collisionMap.addFeatureLayer(featureLayerProperties, mapView).catch((error: any) => console.error(error));
    }

private getGraphicFromLocal(graphic: any): Graphic {
        console.log('graphic symbol', graphic);


        // Create a new Point geometry
        const pointGeometry = new Point({
            x: graphic.shownGraphic.geometry.x,
            y: graphic.shownGraphic.geometry.y,
            spatialReference: graphic.shownGraphic.geometry.spatialReference
        });

        // Create a new graphic object
        const localGraphic = new Graphic({
            geometry: pointGeometry,
            // symbol: graphic.shownGraphic.symbol,
            attributes: {
                ...graphic.shownGraphic.attributes,
                symbolType: graphic.symbol
            }
        });

        return localGraphic;
    }
0 Kudos