Select to view content in your preferred language

Replacing FeatureLayer graphic with a D3.js object

1245
4
09-29-2017 12:25 PM
Jay_Gregory
Regular Contributor

Does anyone know how to replace graphics in a FeatureLayer with a D3.js object.  I'm not interested in simply using an SVG path, but actually replacing the node in which the graphic is rendered with a node from a d3 object.  I have little experience with d3, but from looking at Esri's documentation and digging into the console, I figure this shouldn't be too difficult.  I've included a simple example I would like to get working, but ideally I would eventually use a more complicated d3 object, constructed from feature attributes.  

 require(["esri/map", "esri/layers/FeatureLayer", "dojo/domReady!"], function(Map, FeatureLayer) {
            map = new Map("map", {
                basemap: "topo", 
                center: [-97, 38], 
                zoom: 5
            });
            var svg = createD3Circle();
            console.log(svg);
            var featureLayer = new FeatureLayer("myfeatureserviceurl");
            featureLayer.on('graphic-draw', function(graphic) {
                console.log(graphic);
                graphic.node = svg;
                console.log(graphic);
                //is there anything I can do here to replace each graphic with my svg object.
                //or possibly before the graphic even draws
            });
            map.addLayer(featureLayer);

            featureLayer.on('load', function() {
                var sType = featureLayer.surfaceType;
                console.log(sType);
            });
         
            function createD3Circle() {
                var svgContainer = d3.select("body").append("svg")
                    .attr("width", 200)
                    .attr("height", 200);
                var circle = svgContainer.append("circle")
                    .attr("cx", 30)
                    .attr("cy", 30)
                    .attr("r", 20);
                return circle;
            }


        });‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
0 Kudos
4 Replies
ThomasSolow
Regular Contributor

It's been a little while since I looked at d3.  Is a d3 object an SVG?  You can use a Picture Marker Symbol whose URL points to an SVG, you aren't just limited to passing in a path.  For example (click the map to add a graphic whose symbol is taken from an SVG): JS Bin - Collaborative JavaScript Debugging 

The easiest way to do this sort of thing with a feature layer is to make your own SimpleRenderer and override the getSymbol method.  getSymbol takes a graphic as an argument and should return a symbol.  You can use d3 to create an SVG and then create a PictureMarkerSymbol from that SVG inside getSymbol.

0 Kudos
ThomasSolow
Regular Contributor

Here's another sample showing how you might do this with d3 and a simple renderer: JS Bin - Collaborative JavaScript Debugging 

0 Kudos
Jay_Gregory
Regular Contributor

Thanks!  This was very helpful.  The library I'm using ends up creating an svg dom node that I would like to use as the symbol.  Unfortunately referencing innerHTML of the dom node isn't sufficient, as not all svg properties are captured (although I have no idea why).  Do you know, more generally, if there is a way to set a symbol to be a simple dom element in any of Esri's JS symbol classes?

0 Kudos
ThomasSolow
Regular Contributor

Do you know, more generally, if there is a way to set a symbol to be a simple dom element in any of Esri's JS symbol classes?

I don't think so, I believe the closest thing you can get here is an SVG.  I'm not sure the best way to stringify an SVG, using innerHTML seems a little hacky.

Using google, I came across this which might be useful:

var xml = new XMLSerializer().serializeToString(mySVGElement);‍‍

You could probably create one XMLSerializer and perform all the "serializeToString" operations you need using it.

0 Kudos