I am trying to add drawing tool on map. so user can draw different geometries (polygon, polyline, arrow, square, circle, traingle. etc)... I have already implement simple toolbar using below sample
but I have also want to add text input ...for labeling on map area or geometries.. along with different color and font size..
In short I am trying to implement smart draw tool using ArcGIS JavaScript.
Any help appreciated.
Thank You
Solved! Go to Solution.
Here's a quick update I did to the Esri sketch geometry sandbox to include a text graphic button. The Esri icon font graphic example also has a simplified way of displaying a point graphic with textSymbol.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">
<title>Sketch temporary geometries - 4.9</title>
<link rel="stylesheet" href="https://js.arcgis.com/4.9/esri/css/main.css">
<script src="https://js.arcgis.com/4.9/"></script>
<style>
html,
body,
#viewDiv {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
font-family: verdana;
}
#topbar {
background: #fff;
position: absolute;
top: 15px;
right: 15px;
padding: 10px;
}
.action-button {
font-size: 16px;
background-color: transparent;
border: 1px solid #D3D3D3;
color: #6e6e6e;
height: 32px;
width: 32px;
text-align: center;
box-shadow: 0 0 1px rgba(0, 0, 0, 0.3);
}
.action-button:hover,
.action-button:focus {
background: #0079c1;
color: #e4e4e4;
}
.active {
background: #0079c1;
color: #e4e4e4;
}
</style>
<script>
require([
"esri/views/MapView",
"esri/Map",
"esri/widgets/Sketch/SketchViewModel",
"esri/Graphic",
"esri/layers/GraphicsLayer"
], function (
MapView, Map,
SketchViewModel, Graphic, GraphicsLayer
) {
let editGraphic;
// GraphicsLayer to hold graphics created via sketch view model
const graphicsLayer = new GraphicsLayer({
id: "tempGraphics"
});
const map = new Map({
basemap: "gray",
layers: [graphicsLayer]
});
const view = new MapView({
container: "viewDiv",
map: map,
zoom: 3
});
const pointSymbol = {
type: "simple-marker", // autocasts as new SimpleMarkerSymbol()
style: "square",
color: "#8A2BE2",
size: "16px",
outline: { // autocasts as new SimpleLineSymbol()
color: [255, 255, 255],
width: 3
}
};
const polylineSymbol = {
type: "simple-line", // autocasts as new SimpleLineSymbol()
color: "#8A2BE2",
width: "4",
style: "dash"
};
const polygonSymbol = {
type: "simple-fill", // autocasts as new SimpleFillSymbol()
color: "rgba(138,43,226, 0.8)",
style: "solid",
outline: {
color: "white",
width: 1
}
};
const textSymbol = {
type: "text", // autocasts as new TextSymbol()
color: "white",
haloColor: "black",
haloSize: "1px",
text: "",
xoffset: 3,
yoffset: 3,
font: { // autocast as new Font()
size: 12,
family: "sans-serif",
weight: "bold"
}
};
view.when(function () {
// create a new sketch view model
const sketchViewModel = new SketchViewModel({
view,
layer: graphicsLayer,
pointSymbol,
polylineSymbol,
polygonSymbol
});
setUpClickHandler();
// Listen to create-complete event to add a newly created graphic to view
sketchViewModel.on("create-complete", addGraphic);
// Listen the sketchViewModel's update-complete and update-cancel events
sketchViewModel.on("update-complete", updateGraphic);
sketchViewModel.on("update-cancel", updateGraphic);
// called when sketchViewModel's create-complete event is fired.
function addGraphic(event) {
// Create a new graphic and set its geometry to
// `create-complete` event geometry.
let graphicSymbol;
if (document.querySelector("button.active").id === "textButton") {
graphicSymbol = textSymbol;
graphicSymbol.text = prompt("Please enter some text", "Default Text");
} else {
graphicSymbol = sketchViewModel.graphic.symbol;
}
const graphic = new Graphic({
geometry: event.geometry,
symbol: graphicSymbol
});
graphicsLayer.add(graphic);
}
// Runs when sketchViewModel's update-complete or update-cancel
// events are fired.
function updateGraphic(event) {
// Create a new graphic and set its geometry event.geometry
var graphic = new Graphic({
geometry: event.geometry,
symbol: editGraphic.symbol
});
graphicsLayer.add(graphic);
// set the editGraphic to null update is complete or cancelled.
editGraphic = null;
}
// set up logic to handle geometry update and reflect the update on "graphicsLayer"
function setUpClickHandler() {
view.on("click", function (event) {
view.hitTest(event).then(function (response) {
var results = response.results;
if (results.length > 0) {
for (var i = 0; i < results.length; i++) {
// Check if we're already editing a graphic
if (!editGraphic && results[i].graphic.layer.id === "tempGraphics") {
// Save a reference to the graphic we intend to update
editGraphic = results[i].graphic;
// Remove the graphic from the GraphicsLayer
// Sketch will handle displaying the graphic while being updated
graphicsLayer.remove(editGraphic);
sketchViewModel.update(editGraphic);
break;
}
}
}
});
});
}
// activate the sketch to create a point
var drawPointButton = document.getElementById("pointButton");
drawPointButton.onclick = function () {
// set the sketch to create a point geometry
sketchViewModel.create("point");
setActiveButton(this);
};
// activate the sketch to create a polyline
var drawLineButton = document.getElementById("polylineButton");
drawLineButton.onclick = function () {
// set the sketch to create a polyline geometry
sketchViewModel.create("polyline");
setActiveButton(this);
};
// activate the sketch to create a polygon
var drawPolygonButton = document.getElementById("polygonButton");
drawPolygonButton.onclick = function () {
// set the sketch to create a polygon geometry
sketchViewModel.create("polygon");
setActiveButton(this);
};
// activate the sketch to create text
var drawRectangleButton = document.getElementById(
"textButton");
drawRectangleButton.onclick = function () {
// set the sketch to create a polygon geometry
sketchViewModel.create("point");
setActiveButton(this);
};
// reset button
document.getElementById("resetBtn").onclick = function () {
sketchViewModel.reset();
graphicsLayer.removeAll();
setActiveButton();
};
function setActiveButton(selectedButton) {
// focus the view to activate keyboard shortcuts for sketching
view.focus();
var elements = document.getElementsByClassName("active");
for (var i = 0; i < elements.length; i++) {
elements[i].classList.remove("active");
}
if (selectedButton) {
selectedButton.classList.add("active");
}
}
});
});
</script>
</head>
<body>
<div id="viewDiv">
<div id="topbar">
<button class="action-button esri-icon-blank-map-pin" id="pointButton"
type="button" title="Draw point"></button>
<button class="action-button esri-icon-polyline" id="polylineButton" type="button"
title="Draw polyline"></button>
<button class="action-button esri-icon-polygon" id="polygonButton" type="button"
title="Draw polygon"></button>
<button class="action-button esri-icon-comment" id="textButton"
type="button" title="Add Text"></button>
<button class="action-button esri-icon-trash" id="resetBtn" type="button"
title="Clear graphics"></button>
</div>
</div>
</body>
</html>
You should be able to create a TextSymbol graphic and add it to a GraphicsLayer. As for the interface to do so, you'd have to build that. Probably when they click on the text graphic button, you can get the text from an input element ahead of time or show a prompt(). Then create the graphic with the user's text and add it to the GraphicsLayer with some default styling.
Hello Blake,
Am trying to implement function by which user can add text on map manually for labeling purpose. Can you please help me with that. and if possible can you share any snippet for that..
Thanks
Raj
Here's a quick update I did to the Esri sketch geometry sandbox to include a text graphic button. The Esri icon font graphic example also has a simplified way of displaying a point graphic with textSymbol.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">
<title>Sketch temporary geometries - 4.9</title>
<link rel="stylesheet" href="https://js.arcgis.com/4.9/esri/css/main.css">
<script src="https://js.arcgis.com/4.9/"></script>
<style>
html,
body,
#viewDiv {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
font-family: verdana;
}
#topbar {
background: #fff;
position: absolute;
top: 15px;
right: 15px;
padding: 10px;
}
.action-button {
font-size: 16px;
background-color: transparent;
border: 1px solid #D3D3D3;
color: #6e6e6e;
height: 32px;
width: 32px;
text-align: center;
box-shadow: 0 0 1px rgba(0, 0, 0, 0.3);
}
.action-button:hover,
.action-button:focus {
background: #0079c1;
color: #e4e4e4;
}
.active {
background: #0079c1;
color: #e4e4e4;
}
</style>
<script>
require([
"esri/views/MapView",
"esri/Map",
"esri/widgets/Sketch/SketchViewModel",
"esri/Graphic",
"esri/layers/GraphicsLayer"
], function (
MapView, Map,
SketchViewModel, Graphic, GraphicsLayer
) {
let editGraphic;
// GraphicsLayer to hold graphics created via sketch view model
const graphicsLayer = new GraphicsLayer({
id: "tempGraphics"
});
const map = new Map({
basemap: "gray",
layers: [graphicsLayer]
});
const view = new MapView({
container: "viewDiv",
map: map,
zoom: 3
});
const pointSymbol = {
type: "simple-marker", // autocasts as new SimpleMarkerSymbol()
style: "square",
color: "#8A2BE2",
size: "16px",
outline: { // autocasts as new SimpleLineSymbol()
color: [255, 255, 255],
width: 3
}
};
const polylineSymbol = {
type: "simple-line", // autocasts as new SimpleLineSymbol()
color: "#8A2BE2",
width: "4",
style: "dash"
};
const polygonSymbol = {
type: "simple-fill", // autocasts as new SimpleFillSymbol()
color: "rgba(138,43,226, 0.8)",
style: "solid",
outline: {
color: "white",
width: 1
}
};
const textSymbol = {
type: "text", // autocasts as new TextSymbol()
color: "white",
haloColor: "black",
haloSize: "1px",
text: "",
xoffset: 3,
yoffset: 3,
font: { // autocast as new Font()
size: 12,
family: "sans-serif",
weight: "bold"
}
};
view.when(function () {
// create a new sketch view model
const sketchViewModel = new SketchViewModel({
view,
layer: graphicsLayer,
pointSymbol,
polylineSymbol,
polygonSymbol
});
setUpClickHandler();
// Listen to create-complete event to add a newly created graphic to view
sketchViewModel.on("create-complete", addGraphic);
// Listen the sketchViewModel's update-complete and update-cancel events
sketchViewModel.on("update-complete", updateGraphic);
sketchViewModel.on("update-cancel", updateGraphic);
// called when sketchViewModel's create-complete event is fired.
function addGraphic(event) {
// Create a new graphic and set its geometry to
// `create-complete` event geometry.
let graphicSymbol;
if (document.querySelector("button.active").id === "textButton") {
graphicSymbol = textSymbol;
graphicSymbol.text = prompt("Please enter some text", "Default Text");
} else {
graphicSymbol = sketchViewModel.graphic.symbol;
}
const graphic = new Graphic({
geometry: event.geometry,
symbol: graphicSymbol
});
graphicsLayer.add(graphic);
}
// Runs when sketchViewModel's update-complete or update-cancel
// events are fired.
function updateGraphic(event) {
// Create a new graphic and set its geometry event.geometry
var graphic = new Graphic({
geometry: event.geometry,
symbol: editGraphic.symbol
});
graphicsLayer.add(graphic);
// set the editGraphic to null update is complete or cancelled.
editGraphic = null;
}
// set up logic to handle geometry update and reflect the update on "graphicsLayer"
function setUpClickHandler() {
view.on("click", function (event) {
view.hitTest(event).then(function (response) {
var results = response.results;
if (results.length > 0) {
for (var i = 0; i < results.length; i++) {
// Check if we're already editing a graphic
if (!editGraphic && results[i].graphic.layer.id === "tempGraphics") {
// Save a reference to the graphic we intend to update
editGraphic = results[i].graphic;
// Remove the graphic from the GraphicsLayer
// Sketch will handle displaying the graphic while being updated
graphicsLayer.remove(editGraphic);
sketchViewModel.update(editGraphic);
break;
}
}
}
});
});
}
// activate the sketch to create a point
var drawPointButton = document.getElementById("pointButton");
drawPointButton.onclick = function () {
// set the sketch to create a point geometry
sketchViewModel.create("point");
setActiveButton(this);
};
// activate the sketch to create a polyline
var drawLineButton = document.getElementById("polylineButton");
drawLineButton.onclick = function () {
// set the sketch to create a polyline geometry
sketchViewModel.create("polyline");
setActiveButton(this);
};
// activate the sketch to create a polygon
var drawPolygonButton = document.getElementById("polygonButton");
drawPolygonButton.onclick = function () {
// set the sketch to create a polygon geometry
sketchViewModel.create("polygon");
setActiveButton(this);
};
// activate the sketch to create text
var drawRectangleButton = document.getElementById(
"textButton");
drawRectangleButton.onclick = function () {
// set the sketch to create a polygon geometry
sketchViewModel.create("point");
setActiveButton(this);
};
// reset button
document.getElementById("resetBtn").onclick = function () {
sketchViewModel.reset();
graphicsLayer.removeAll();
setActiveButton();
};
function setActiveButton(selectedButton) {
// focus the view to activate keyboard shortcuts for sketching
view.focus();
var elements = document.getElementsByClassName("active");
for (var i = 0; i < elements.length; i++) {
elements[i].classList.remove("active");
}
if (selectedButton) {
selectedButton.classList.add("active");
}
}
});
});
</script>
</head>
<body>
<div id="viewDiv">
<div id="topbar">
<button class="action-button esri-icon-blank-map-pin" id="pointButton"
type="button" title="Draw point"></button>
<button class="action-button esri-icon-polyline" id="polylineButton" type="button"
title="Draw polyline"></button>
<button class="action-button esri-icon-polygon" id="polygonButton" type="button"
title="Draw polygon"></button>
<button class="action-button esri-icon-comment" id="textButton"
type="button" title="Add Text"></button>
<button class="action-button esri-icon-trash" id="resetBtn" type="button"
title="Clear graphics"></button>
</div>
</div>
</body>
</html>
It works perfectly Blake. thanks for the reply. I am sharing one of widget here.. I am working on that but its in 3.10 js...
Can you check it once for me.. its a advanced tool for drawing geometries and labeling on the map.
Can we implement this draw tool in 4.9 js...
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
- <html>
- <head>
- <title>Create a Map</title>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
- <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no">
- <link rel="stylesheet" href="http://js.arcgis.com/3.10/js/dojo/dijit/themes/claro/claro.css">
- <link rel="stylesheet" href="http://js.arcgis.com/3.10/js/esri/css/esri.css">
- <style>
- html,
- body,
- #mapDiv {
- padding: 0;
- margin: 0;
- height: 100%;
- }
- button {
- display: block;
- }
- </style>
- <script src="http://js.arcgis.com/3.10/"></script>
- <script>
- var map, tb;
- require([
- "esri/map", "esri/toolbars/draw",
- "esri/symbols/SimpleMarkerSymbol", "esri/symbols/SimpleLineSymbol",
- "esri/symbols/PictureFillSymbol", "esri/symbols/CartographicLineSymbol",
- "esri/graphic", "esri/Color", "dojo/dom", "dojo/on", "dojo/parser",
- "dijit/form/Button", "dijit/layout/BorderContainer", "dijit/layout/ContentPane", "dijit/form/ComboBox",
- "dijit/layout/TabContainer", "dijit/form/NumberSpinner", "dijit/form/TextBox", "dijit/ColorPalette",
- "dojo/domReady!"
- ], function (
- Map, Draw,
- SimpleMarkerSymbol, SimpleLineSymbol,
- PictureFillSymbol, CartographicLineSymbol,
- Graphic,
- Color, dom, on, parser
- ) {
- parser.parse();
- map = new Map("mapDiv", {
- basemap: "streets",
- center: [-25.312, 34.307],
- zoom: 3
- });
- map.on("load", initToolbar);
- map.on("resize", resizeMap);
- function initToolbar() {
- tb = new Draw(map);
- tb.on("draw-end", addToMap);
- // event delegation so a click handler is not
- // needed for each individual button
- on(dom.byId("info"), "click", function(evt) {
- if ( evt.target.id === "info" ) {
- return;
- }
- var tool = evt.target.id.toLowerCase();
- if(tool == "clear"){
- map.graphics.clear();
- map.enableMapNavigation();
- }else{
- map.disableMapNavigation();
- tb.activate(tool);
- }
- });
- }
- function addToMap(evt) {
- //deactivate the toolbar and clear existing graphics
- tb.deactivate();
- map.enableMapNavigation();
- switch (evt.geometry.type) {
- case "point":
- var font = new esri.symbol.Font();
- font.setSize(parseInt(dojo.byId("tsSize").value));
- font.setWeight(esri.symbol.Font[dojo.byId("tsWeight").value]);
- var symbol = new esri.symbol.TextSymbol();
- symbol.setText(dojo.byId("tsText").value);
- symbol.setColor(new dojo.Color(dijit.byId("tsColor").value));
- symbol.setFont(font);
- symbol.setAngle(parseInt(dojo.byId("tsAngle").value));
- break;
- case "polyline":
- var symbol = new esri.symbol.SimpleLineSymbol(esri.symbol.SimpleLineSymbol.STYLE_SOLID, new dojo.Color([255, 0, 0]), 1);
- break;
- case "polygon":
- var symbol = new esri.symbol.SimpleFillSymbol(esri.symbol.SimpleFillSymbol.STYLE_NONE, new esri.symbol.SimpleLineSymbol(esri.symbol.SimpleLineSymbol.STYLE_DASHDOT, new dojo.Color([255, 0, 0]), 2), new dojo.Color([255, 255, 0, 0.25]));
- break;
- case "extent":
- var symbol = new esri.symbol.SimpleFillSymbol(esri.symbol.SimpleFillSymbol.STYLE_NONE, new esri.symbol.SimpleLineSymbol(esri.symbol.SimpleLineSymbol.STYLE_DASHDOT, new dojo.Color([255, 0, 0]), 2), new dojo.Color([255, 255, 0, 0.25]));
- break;
- case "multipoint":
- var symbol = new esri.symbol.SimpleMarkerSymbol(esri.symbol.SimpleMarkerSymbol.STYLE_DIAMOND, 20, new esri.symbol.SimpleLineSymbol(esri.symbol.SimpleLineSymbol.STYLE_SOLID, new dojo.Color([0, 0, 0]), 1), new dojo.Color([255, 255, 0, 0.5]));
- break;
- }
- map.graphics.add(new Graphic(evt.geometry, symbol));
- }
- //Handle resize of browser
- function resizeMap() {
- clearTimeout(resizeTimer);
- resizeTimer = setTimeout(function () {
- map.resize();
- map.reposition();
- }, 800);
- }
- });
- </script>
- </head>
- <body class="claro">
- <div id="mainWindow" dojotype="dijit.layout.BorderContainer" design="sidebar" gutters="false" style="width:100%; height:100%;">
- <div id="mapDiv" dojotype="dijit.layout.ContentPane" region="center" style="margin:5px;">
- </div>
- <div dojoType="dijit.layout.TabContainer" region="right" style="width:25%;margin:5px;">
- <div dojoType="dijit.layout.ContentPane" selected="true" title="Symbol Properties">
- <div id="info">
- <div>Select a shape then draw on map to add graphic</div>
- <button id="Point">Text</button>
- <button id="Multipoint">Multipoint</button>
- <button id="Line">Line</button>
- <button id="Polyline">Polyline</button>
- <button id="FreehandPolyline">Freehand Polyline</button>
- <button id="Triangle">Triangle</button>
- <button id="Extent">Rectangle</button>
- <button id="Circle">Circle</button>
- <button id="Ellipse">Ellipse</button>
- <button id="Polygon">Polygon</button>
- <button id="FreehandPolygon">Freehand Polygon</button>
- <button id="Clear">Clear Graphics</button>
- </div>
- <br/>
- Enter Text:
- <input dojotype="dijit.form.TextBox" value="Text" id="tsText" />
- <br />
- <br />Color :
- <br />
- <div dojoType="dijit.ColorPalette" id="tsColor"></div>
- <br />
- <br />
- <br />Angle :
- <br />
- <input dojoType="dijit.form.NumberSpinner" value="0" constraints="{min:-360,max:360}" id="tsAngle" />
- <br>Weight :
- <br />
- <select id="tsWeight" dojoType="dijit.form.ComboBox" autocomplete="false" value="WEIGHT_NORMAL">
- <option selected="selected">WEIGHT_NORMAL</option>
- <option>WEIGHT_BOLD</option>
- <option>WEIGHT_BOLDER</option>
- <option>WEIGHT_LIGHTER</option>
- </select>
- <br />Size :
- <br />
- <select id="tsSize" dojoType="dijit.form.ComboBox" autocomplete="false" value="14pt">
- <option>10pt</option>
- <option>12pt</option>
- <option selected="selected">14pt</option>
- <option>16pt</option>
- <option>18pt</option>
- <option>20pt</option>
- <option>22pt</option>
- <option>24pt</option>
- <option>26pt</option>
- <option>28pt</option>
- <option>30pt</option>
- </select>
- </div>
- </div>
- </body>
- </html>
Sorry, I'm not very familiar with the 3.x API and I can't get your code to run (even with the missing closing </div> tag for mainWindow). The Esri Sketch temporary geometries sample is the best example of making a sketch widget in 4.x.
No worries... i have already implemented function with referring your code. I really appreciate that.
Actually this one is advanced Draw tool so thinking we can use it in 4.x API...
Thanks
Working Perfectly