graphic.getShape() always return null

4706
6
Jump to solution
10-06-2014 10:55 AM
XuejinRuan
New Contributor III

According to the ArcGIS Javascript API documentation for Graphic object, Graphic has a getShape() or getDojoShape() method, which:

Returns the Dojo gfx shape of the ESRI graphic.

graphic-amd | API Reference | ArcGIS API for JavaScript

 

It seems for older version of the Javascript API, it actuallly returns an object. However, in the newer version of Javascript API, it always return null for my point graphic object or polygon graphic object.

 

What I want to do is to implement a draggable marker, namely drag graphics point and drop at a new location using dojox.gfx.Moveable tool, something like:

 

var dojoShape = graphic.getDojoShape();   //or graphic.getShape();

var moveable = new dojox.gfx.Moveable(dojoShape);

 

//Update the geometry at the end of move 

var moveStopToken = dojo.connect(moveable, "onMoveStop", function(mover) { 

   // Get the transformation that was applied to  

  // the shape since the last move 

       var tx = dojoShape.getTransform(); 

      var startPoint = graphic.geometry; 

      var endPoint = map.toMap(map.toScreen(startPoint).offset(tx.dx, tx.dy)); 

     // clear out the transformation 

     dojoShape.setTransform(null); 

      // update the graphic geometry 

      graphic.setGeometry(endPoint); 

}); 

0 Kudos
1 Solution

Accepted Solutions
RiyasDeen
Occasional Contributor III

Hi Aaron,

Not sure where you are trying to access the dojo shape. The gfx object representing your graphic should be be created in the DOM before you can access it,

In the below fiddle, I'm using graphic-node-add event to identify if gfx DOM has been created.

Edit fiddle - JSFiddle

View solution in original post

6 Replies
TimWitt2
MVP Alum

You could also use the edit toolbar to move a graphic, this might be easier.

edit-amd | API Reference | ArcGIS API for JavaScript

AaronHeyman
New Contributor III

When issues like that come up it can be caused by calling a function on a layer that has not yet finished loading.  Try adding your function call to happen after the on load.

yourLayer.on("load", functionToYourCodeAbove or inline here);

XuejinRuan
New Contributor III

Hi Aaron,

Actually in this case the layer is loaded, and the graphic object is created. But the shape of the graphic seems to be empty if I use current version of ArcGIS javascript API. But if I use an older version of javascript API, the shape of the graphic object is not null. Please refer to the jsfiddle example below:

User ArcGIS javascript API, version 2.2, things are working fine:

Edit fiddle - JSFiddle

But if I use version 3.10 of the JavaScript API, graphic.getShape() is null:

Edit fiddle - JSFiddle

Not sure how ESRI has changed their implementation of the Graphic class.

Thanks,

Xuejin

0 Kudos
XuejinRuan
New Contributor III

Thanks Tim, that could be an option.

0 Kudos
KenBuja
MVP Esteemed Contributor

It doesn't always return a null. I was testing a script by Riyas Deen‌ from this discussion‌ and discovered the getShape method actually returned a dojox.gfx Shape (see lines 254 and 303).

I haven't figured out why it works correctly in this script but not on something like this sample, however.

<!DOCTYPE html>

<html>

<head>

    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">

    <!--The viewport meta tag is used to improve the presentation and behavior of the samples

        on iOS devices-->

    <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no">

    <title>Sliding Info Panel</title>

    <link rel="stylesheet" href="https://community.esri.com//js.arcgis.com/3.11/dijit/themes/tundra/tundra.css">

    <link rel="stylesheet" href="http://js.arcgis.com/3.11/esri/css/esri.css">

    <link rel="stylesheet" type="text/css" href="http://fonts.googleapis.com/css?family=Open Sans">

    <style type="text/css">

        html,

        body {

            height: 100%;

            width: 100%;

            margin: 0;

            padding: 0;

            margin: 0;

            font-family: "Open Sans";

        }

        #leftPane {

            width: 20%;

            margin: 10px;

            -webkit-box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.6);

            -moz-box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.6);

            box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.6);

            background-color: white;

            border: solid 1px gray;

        }

        #map {

            padding: 0;

            -webkit-box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.6);

            -moz-box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.6);

            box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.6);

            border: solid 1px gray;

            margin: 10px;

            overflow: hidden;

            position: relative;

        }

        #header {

            text-align: center;

            height: 40px;

            margin: 10px;

            background-color: whitesmoke;

        }

        #footer {

            -webkit-box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.6);

            -moz-box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.6);

            box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.6);

            border: solid 1px gray;

            border-radius: 8px;

            text-align: center;

            margin: 10px;

            height: 50px;

            background-color: white;

        }

        #sliderDiv {

            top: 0;

            left: -120px;

            background-color: steelblue;

            position: absolute;

            z-index: 9999;

            -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.6);

            -moz-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.6);

            box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.6);

            border: solid 1px gray;

            color: white;

            padding: 5px;

        }

        #mainWindow {

            width: 100%;

            height: 100%;

            background-color: whitesmoke;

        }

    </style>

    <style>

        @import url(http://fonts.googleapis.com/css?family=Norican);

        html, body {

            margin: 0;

            background: #45c2c5;

        }

        h1 {

            display: block;

            font-size: 50px;

            font-family: 'Norican', cursive;

            color: white;

            position: absolute;

            top: 50%;

            left: 50%;

            width: 40px;

            line-height: 40px;

            margin: -20px 0 0 -20px;

            text-shadow: 0 2px 0 #8ed2d4,2px 3px 15px rgba(0,0,0,0.5);

        }

        .ripple, .ripple:before, .ripple:after {

            display: block;

            border-radius: 2px;

            width: 2px;

            height: 2px;

            -webkit-animation: rip 2s infinite;

            -moz-animation: rip 2s infinite;

        }

        .ripple {

            position: absolute;

            z-index: 1000;

            top: 10px;

            left: 15px;

        }

            .ripple:before, .ripple:after {

                content: '';

                position: absolute;

            }

            .ripple:before {

                -webkit-animation-delay: .1s;

                -moz-animation-delay: .2s;

                top: 5px;

                left: 0px;

            }

            .ripple:after {

                -webkit-animation-delay: .2s;

                -moz-animation-delay: .2s;

                top: 5px;

                left: 0;

            }

        @-webkit-keyframes rip {

            0% {

                box-shadow: 0 0 0 0 transparent, 0 0 0 0 transparent, 0 0 0 0 transparent, 0 0 0 0 transparent;

            }

            5% {

                box-shadow: 0 0 0 0 transparent, 0 0 0 0 rgba(69,194,197,0.5), 0 0 0 0 transparent, 0 0 0 0 rgba(0,0,0,0.1);

            }

            100% {

                box-shadow: 0 0 40px 300px transparent, 0 0 10px 310px transparent, 0 0 30px 320px transparent, 0 0 5px 330px transparent;

            }

        }

        @-moz-keyframes rip {

            0% {

                box-shadow: 0 0 0 0 transparent, 0 0 0 0 transparent, 0 0 0 0 transparent, 0 0 0 0 transparent;

            }

            5% {

                box-shadow: 0 0 0 0 transparent, 0 0 0 0 rgba(69,194,197,0.5), 0 0 0 0 transparent, 0 0 0 0 rgba(0,0,0,0.1);

            }

            100% {

                box-shadow: 0 0 10px 75px transparent, 0 0 20px 75px transparent, 0 0 30px 75px transparent, 0 0 40px 75px transparent;

            }

        }

    </style>

    <script src="http://js.arcgis.com/3.11/"></script>

    <script>

        var map, mapGLayer;

        require([

            "esri/map",

            "esri/layers/FeatureLayer",

            "esri/layers/GraphicsLayer",

            "esri/tasks/query",

            "esri/geometry/Circle",

            "esri/graphic",

            "esri/InfoTemplate",

            "esri/symbols/SimpleMarkerSymbol",

            "esri/symbols/SimpleLineSymbol",

            "esri/symbols/SimpleFillSymbol",

            "esri/renderers/SimpleRenderer",

            "esri/config",

            "esri/Color",

            "dojo/dom",

            "dojo/on",

            "dojo/_base/connect",

            "dojo/parser",

            "dijit/registry",

            'dojo/_base/html',

            "esri/domUtils",

            "dojo/fx",

            "dojo/dom-construct",

            "dijit/layout/BorderContainer",

            "dijit/layout/ContentPane",

            "dojo/domReady!"

        ], function (

          Map, FeatureLayer, GraphicsLayer,

          Query, Circle,

          Graphic, InfoTemplate, SimpleMarkerSymbol,

          SimpleLineSymbol, SimpleFillSymbol, SimpleRenderer,

          esriConfig, Color, dom, on, connect, parser, registry, html, domUtils, fx, domConstruct

        ) {

            // use a proxy page if a URL generated by this page is greater than 2000 characters

            //

            // this should not be needed as nearly all query & select functions are performed on the client

            //esriConfig.defaults.io.proxyUrl = "http://gislap183/Proxy/proxy.ashx";

            parser.parse();

            map = new Map("map", {

                basemap: "streets",

                center: [-95.249, 38.954],

                zoom: 14,

                slider: false

            });

            map.infoWindow.set("popupWindow", false);

            //add the census block points in on demand mode. Note that an info template has been defined so when

            //selected features are clicked a popup window will appear displaying the content defined in the info template.

            var featureLayer = new FeatureLayer("http://sampleserver6.arcgisonline.com/arcgis/rest/services/Census/MapServer/0", {

                infoTemplate: new InfoTemplate("Block: ${BLOCK}", "${*}"),

                outFields: ["POP2000", "HOUSEHOLDS", "HSE_UNITS", "TRACT", "BLOCK"]

            });

            function displayPopupContent(feature) {

                if (feature) {

                    if (dojo.marginBox("sliderDiv").l < 0) {

                        slideIt(120);

                    }

                    var content = feature.getContent();

                    dom.byId("sliderDiv").innerHTML = content;

                }

            }

            function slideIt(amt) {

                var slideArgs = {

                    node: "sliderDiv",

                    top: (dojo.marginBox("sliderDiv").t).toString(),

                    left: (dojo.marginBox("sliderDiv").l + amt).toString(),

                    unit: "px"

                };

                var animation = fx.slideTo(slideArgs);

                animation.play();

            }

            function createRipple() {

                domConstruct.destroy("rippleDraggable");

                // RIYAS: Assumption is, ripple will be created on default map graphics layer and there will be only one graphics

                try {

                    var rippleGraphic = map.graphics.graphics[0];

                    console.log("Ripple shape");

                    console.log(rippleGraphic.getShape());

                    if (rippleGraphic.visible) {

                        var screenCoordinates = map.toScreen(rippleGraphic.geometry);

                        var draggable = domConstruct.create("h1", { id: "rippleDraggable", class: "draggable", style: { zIndex: "1000", position: "absolute", left: (screenCoordinates.x + 6) + "px", top: (screenCoordinates.y + 6) + "px" } }, map.__container);

                        var ripple = domConstruct.create("div", { class: "ripple" }, draggable);

                    }

                }

                catch (e) { }

            }

            var symbol = new SimpleMarkerSymbol(

              SimpleMarkerSymbol.STYLE_CIRCLE,

              12,

              new SimpleLineSymbol(

                SimpleLineSymbol.STYLE_NULL,

                new Color([247, 34, 101, 0.9]),

                1

              ),

              new Color([207, 34, 171, 0.5])

            );

            featureLayer.setSelectionSymbol(symbol);

            map.addLayers([featureLayer]);

            var popup = map.infoWindow;

            map.on("extent-change", function () {

                createRipple();

            });

            map.on("layers-add-result", function () {

                //set up the SVG animation for infoWindow selected features

                mapGLayer = new GraphicsLayer();

                mapGLayer = map.graphics;

                mapGLayer.styled = false;

                if (mapGLayer.surfaceType === "svg") {

                    on(mapGLayer, "graphic-draw", function (evt) {

                        createRipple();

                    });

                }

            });

            //when the selection is cleared remove the popup content from the side panel.

            connect.connect(popup, "onClearFeatures", function () {

                setTimeout(function () {

                    var graphic = popup.getSelectedFeature();

                    console.log("Clear Features shape ");

                    console.log(graphic.getShape());

                    if (graphic) {

                        displayPopupContent(popup.getSelectedFeature());

                    } else {

                        slideIt(-120);

                        dom.byId("sliderDiv").innerHTML = "";

                    }

                }, 500);

            });

            on(map, "ready", function () {

                mapGLayer = new GraphicsLayer();

                mapGLayer = map.graphics;

                mapGLayer.styled = false;

                on(mapGLayer, "graphic-draw", function (evt) {

                    alert(mapGLayer.surfaceType);

                    if (mapGLayer.surfaceType === "svg") {

                        alert(mapGLayer.surfaceType);

                        evt.node.setAttribute("class", "ripple");

                    }

                });

            });

        });

    </script>

</head>

<body class="tundra">

    <div id="mainWindow" dojotype="dijit.layout.BorderContainer" design="headline" gutters="false">

        <div id="leftPane" dojotype="dijit.layout.ContentPane" region="left">

            This space for rent

        </div>

        <div id="map" dojotype="dijit.layout.ContentPane" region="center">

            <div id="sliderDiv" style="height: 98%; width: 100px;"></div>

        </div>

    </div>

</body>

</html>

RiyasDeen
Occasional Contributor III

Hi Aaron,

Not sure where you are trying to access the dojo shape. The gfx object representing your graphic should be be created in the DOM before you can access it,

In the below fiddle, I'm using graphic-node-add event to identify if gfx DOM has been created.

Edit fiddle - JSFiddle