How to get map coordinates for HTML5 drag drop

2935
2
Jump to solution
10-09-2013 11:52 AM
KenBowen1
New Contributor
I have an SVG I want to drag to the map and drop at a given location.  However, the mouse event on the drop operation does not contain th needed mapPoint.  So is there another way to drag an SVG to the map and drop it at a location?

<!DOCTYPE html> <html> <head>     <meta http-equiv="Content-Type" content="text/html; charset=utf-8">     <meta http-equiv="X-UA-Compatible" content="IE=edge">     <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no">     <title></title>      <link rel="stylesheet" href="http://js.arcgis.com/3.7/js/esri/css/esri.css">     <link rel='stylesheet' href='https://community.esri.com/Content/bootstrap.css' />   <script>      // Instead of using data-dojo-config, we???re creating a dojoConfig object      // *before* we load dojo.js; they???re functionally identical.      var dojoConfig = {          async: true,          // This code registers the correct location of the "demo" package          // so we can load Dojo from the CDN whilst still being able to          // load local modules          paths: {              extras: location.pathname.replace(/\/[^/]*$/, '') + "/scripts/dojo"          }      };  </script>         <script src="http://js.arcgis.com/3.7/"></script>        <script>         var map;         require(["esri/map", "extras/demot1", "dojo/domReady!"], function (Map, demot1) {              map = new Map("mapDiv", {                 center: [-56.049, 38.485],                 zoom: 3,                 basemap: "streets"             });               map.on("mouse-move", showCoordinates);             map.on("mouse-drag", showCoordinates);             map.on("dragover", showCoordinates);              setupDropZone();              var startNode = dojo.byId("sensorDiv");             dojo.connect(startNode, "dragstart", handleStartDrag);                function setupDropZone() {                 // Let's verify that we have proper browser support, before                 // moving ahead. You can also use a library like Modernizr                 // to detect browser cappabilities:                 // http://www.modernizr.com/                  var node = dojo.byId("mapDiv");                 // Reference                 // http://www.html5rocks.com/features/file                 // http://www.html5rocks.com/tutorials/dnd/basics/                 // https://developer.mozilla.org/En/DragDrop/Drag_Operations                 dojo.connect(node, "dragenter", function (evt) {                     // If we don't prevent default behavior here, browsers will                     // perform the default action for the file being dropped i.e,                     // point the page to the file.                     evt.preventDefault();                 });                  dojo.connect(node, "dragover", function (evt) {                     evt.preventDefault();                 });                 dojo.connect(node, "drop", handleDrop);             }              function handleDrop(evt) {                 console.log("Drop: ", evt);                 evt.preventDefault();                 var iconPath = evt.dataTransfer.getData("text/plain");                 var mp = esri.geometry.webMercatorToGeographic(evt.mapPoint);                  demot1.placeIcon(map, mp, iconPath);              }              function handleStartDrag(evt) {                 console.log("Start Drag");                 var iconPath = dojo.query("path", evt.target)[0].attributes["d"].value;                 evt.dataTransfer.setData('text/plain', iconPath);                        }               function showCoordinates(evt) {                 console.log("show");                 //get mapPoint from event                 //The map is in web mercator - modify the map point to display the results in geographic                 var mp = esri.geometry.webMercatorToGeographic(evt.mapPoint);                 //display mouse coordinates                 dojo.byId("info").innerHTML = mp.x.toFixed(3) + ", " + mp.y.toFixed(3);             }           });     </script>        </head>  <body class="claro">     <h1 id="greeting">Hello</h1>     <div class="container">         <div class="row">             <div class="span11">                 <div id="mapDiv">                     <span id="info" style="position:absolute; left:15px; bottom:5px; color:#000; z-index:50;"></span>                 </div>             </div>             <div class="span1">                 <div id="sensorDiv" draggable="true">                     <svg id="sensor1" height="40" version="1.1" width="40" xmlns="http://www.w3.org/2000/svg" style="overflow: hidden;" >                         <desc style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);">Created with Raphaël 2.1.2</desc>                         <defs style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);">                             <linearGradient id="29290-_0050af-_002c62" x1="0" y1="1" x2="6.123031769111886e-17" y2="0" gradientTransform="matrix(1,0,0,1,-4,-4)" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);">                                 <stop offset="0%" stop-color="#0050af" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></stop>                                 <stop offset="100%" stop-color="#002c62" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></stop>                             </linearGradient>                         </defs>                         <path fill="url(#29290-_0050af-_002c62)" stroke="none" d="M16,1.466C7.973,1.466,1.466,7.973,1.466,16C1.466,24.027,7.973,30.534,16,30.534C24.027,30.534,30.534,24.027,30.534,15.999999999999998C30.534,7.973,24.027,1.466,16,1.466ZM16,28.792C14.451,28.792,13.193999999999999,27.536,13.193999999999999,25.986S14.45,23.18,16,23.18C17.55,23.18,18.806,24.436,18.806,25.986S17.55,28.792,16,28.792ZM16,21.087L8.142,14.524999999999999H11.610999999999999V5.747H20.39V14.525H23.858L16,21.087Z" transform="matrix(1,0,0,1,4,4)" opacity="1" fill-opacity="1" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); opacity: 1; fill-opacity: 1;"></path>                         <rect x="0" y="0" width="32" height="32" r="0" rx="0" ry="0" fill="#000000" stroke="#000" opacity="0" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); opacity: 0;"></rect>                     </svg>                 </div>             </div>          </div>     </div>   </body>   </html>     </body>
0 Kudos
1 Solution

Accepted Solutions
ReneRubalcava
Frequent Contributor
I did something similar a while ago. You can use dojo/dom-geometry to get get the needed points and convert them to a geometry.
Project is here
https://github.com/odoe/AGSDragDropHandler

You can read comments in the CoffeeScript file
https://github.com/odoe/AGSDragDropHandler/blob/master/src/DragDropHandler.coffee
Generated JavaScript
https://github.com/odoe/AGSDragDropHandler/blob/master/src/DragDropHandler.js

Here is a sample
https://github.com/odoe/AGSDragDropHandler/tree/master/example/src

Relevant code
// create a new instance of the DragDropHandler handler = new DragDropHandler(); // listen for custom "itemdrop" event handler.on("itemdrop", function(evt) {           var data;           console.log('item dropped', evt);           data = {             pt: new esri.geometry.Point(evt.x, evt.y),             url: domAttr.get(evt.dragsource, 'src'),             id: domAttr.get(evt.dragsource, 'id')           };           console.log('add to map', data);           return mapView.addPoint(data);         });


The mapView.addPoint function
addPoint: function(data) {         var graphic, mp, pms, template;         console.log('data', data);         mp = esri.geometry.toMapGeometry(this.map.extent, this.map.width, this.map.height, data.pt); // convert to map geometry         pms = new esri.symbol.PictureMarkerSymbol();         pms.setUrl(data.url);         /*               # Set width and heigth accordingly.               # If you need to set an offset for a               # pin type marker, do that also         */         pms.setWidth(24);         pms.setHeight(24);         /*               # Normally, I would et the attribute data from another, non-spatial data source,               # and link it via an id or some other attribute, for now, I'll just use a simple               # id field. I'll leave this up to you how you want to populate attributes         */         template = new esri.InfoTemplate("Type of Point", "Type: ${TYPE}");         graphic = new esri.Graphic(mp, pms, {           TYPE: data.id         }, template);         return this.map.graphics.add(graphic);       }


The esri.geometry.toMapGeometry is what will convert screen geometry to map geometry.
https://developers.arcgis.com/en/javascript/jsapi/namespace_geometry-amd.html#toMapGeometry

I put up a blog post about some issues with getting the correct screen point if your map doesn't take up the whole window of the browser, and who dojo/dom-geometry just worked as intended.
http://odoe.net/blog/?p=371

And here is a demo.
http://www.odoe.net/apps/dndeditdemo/

View solution in original post

0 Kudos
2 Replies
ReneRubalcava
Frequent Contributor
I did something similar a while ago. You can use dojo/dom-geometry to get get the needed points and convert them to a geometry.
Project is here
https://github.com/odoe/AGSDragDropHandler

You can read comments in the CoffeeScript file
https://github.com/odoe/AGSDragDropHandler/blob/master/src/DragDropHandler.coffee
Generated JavaScript
https://github.com/odoe/AGSDragDropHandler/blob/master/src/DragDropHandler.js

Here is a sample
https://github.com/odoe/AGSDragDropHandler/tree/master/example/src

Relevant code
// create a new instance of the DragDropHandler handler = new DragDropHandler(); // listen for custom "itemdrop" event handler.on("itemdrop", function(evt) {           var data;           console.log('item dropped', evt);           data = {             pt: new esri.geometry.Point(evt.x, evt.y),             url: domAttr.get(evt.dragsource, 'src'),             id: domAttr.get(evt.dragsource, 'id')           };           console.log('add to map', data);           return mapView.addPoint(data);         });


The mapView.addPoint function
addPoint: function(data) {         var graphic, mp, pms, template;         console.log('data', data);         mp = esri.geometry.toMapGeometry(this.map.extent, this.map.width, this.map.height, data.pt); // convert to map geometry         pms = new esri.symbol.PictureMarkerSymbol();         pms.setUrl(data.url);         /*               # Set width and heigth accordingly.               # If you need to set an offset for a               # pin type marker, do that also         */         pms.setWidth(24);         pms.setHeight(24);         /*               # Normally, I would et the attribute data from another, non-spatial data source,               # and link it via an id or some other attribute, for now, I'll just use a simple               # id field. I'll leave this up to you how you want to populate attributes         */         template = new esri.InfoTemplate("Type of Point", "Type: ${TYPE}");         graphic = new esri.Graphic(mp, pms, {           TYPE: data.id         }, template);         return this.map.graphics.add(graphic);       }


The esri.geometry.toMapGeometry is what will convert screen geometry to map geometry.
https://developers.arcgis.com/en/javascript/jsapi/namespace_geometry-amd.html#toMapGeometry

I put up a blog post about some issues with getting the correct screen point if your map doesn't take up the whole window of the browser, and who dojo/dom-geometry just worked as intended.
http://odoe.net/blog/?p=371

And here is a demo.
http://www.odoe.net/apps/dndeditdemo/
0 Kudos
KenBowen1
New Contributor
Thanks!

Its too bad that map position does not come in on the mouse event.   It was kind of funny that you mentioned the positioning problem.  I am looking at your post on the problem now to see if I can fix up my drag/drop.

I too am working with the idea of a dojo only implementation and not mixing solutions. Its hard because I already know jquery and bootstrap so having to learn dojo to do something I already know is slower than I want to be.

Thanks again for the help
0 Kudos