custom symbology for measurement widgets

1701
6
07-04-2020 12:17 PM
NadirHussain
Occasional Contributor II

Dear all

 I want to change the default symbology of area and line tools that comes with measurement widgets in arcgis java script api 4.15.

i want my own custom symbology for both tools area and distance tools.

Thanks.

6 Replies
RobertScheitlin__GISP
MVP Emeritus

Nadir,

   Here is a snippet:

        // Create new instance of the Measurement widget
        const measurement = new Measurement();
        
        measurement.watch("activeWidget", function(evt){
         if(evt.label === "Distance Measurement"){
           console.info(evt.viewModel.palette);
           evt.viewModel.palette.handleColor = [255,0,0,0.8]
           evt.viewModel.palette.pathPrimaryColor = [255,0,0,1];
           evt.viewModel.palette.pathSecondaryColor = [128,128,128,1];
         }else{
           console.info(evt.viewModel.palette);
           evt.viewModel.palette.pathColor = [255,0,0,1];
           evt.viewModel.palette.handleColor = [255,0,0,0.8];
           evt.viewModel.palette.fillColor = [255,0,0,0.3];
         }
        });‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
NadirHussain
Occasional Contributor II

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta
name="viewport"
content="initial-scale=1,maximum-scale=1,user-scalable=no"
/>
<title>Measurement in 2D - 4.15</title>

<style>
html,
body,
#viewDiv {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
}

#topbar {
background: #fff;
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>

<link
rel="stylesheet"
href="https://js.arcgis.com/4.15/esri/themes/light/main.css"
/>
<script src="https://js.arcgis.com/4.15/"></script>

<script>
require([
"esri/views/MapView",
"esri/WebMap",
"esri/widgets/DistanceMeasurement2D",
"esri/widgets/AreaMeasurement2D"
], function(MapView, WebMap, DistanceMeasurement2D, AreaMeasurement2D) {
var activeWidget = null;

// load a webmap
const webmap = new WebMap({
portalItem: {
id: "990d0191f2574db495c4304a01c3e65b"
}
});

// create the map view
const view = new MapView({
container: "viewDiv",
map: webmap
});

// add the toolbar for the measurement widgets
view.ui.add("topbar", "top-right");

document
.getElementById("distanceButton")
.addEventListener("click", function() {
setActiveWidget(null);
if (!this.classList.contains("active")) {
setActiveWidget("distance");
} else {
setActiveButton(null);
}
});

document
.getElementById("areaButton")
.addEventListener("click", function() {
setActiveWidget(null);
if (!this.classList.contains("active")) {
setActiveWidget("area");
} else {
setActiveButton(null);
}
});

function setActiveWidget(type) {
switch (type) {
case "distance":
activeWidget = new DistanceMeasurement2D({
view: view
});

// skip the initial 'new measurement' button
activeWidget.viewModel.newMeasurement();

view.ui.add(activeWidget, "top-right");
setActiveButton(document.getElementById("distanceButton"));
break;
case "area":
activeWidget = new AreaMeasurement2D({
view: view
});

// skip the initial 'new measurement' button
activeWidget.viewModel.newMeasurement();

view.ui.add(activeWidget, "top-right");
setActiveButton(document.getElementById("areaButton"));
break;
case null:
if (activeWidget) {
view.ui.remove(activeWidget);
activeWidget.destroy();
activeWidget = null;
}
break;
}
}

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.classList.remove("active");
}
if (selectedButton) {
selectedButton.classList.add("active");
}
}
const measurement = new Measurement();

measurement.watch("activeWidget", function(evt){
if(evt.label === "distanceButton"){
alert("if");
console.info(evt.viewModel.palette);
evt.viewModel.palette.handleColor = [255,0,0,0.8]
evt.viewModel.palette.pathPrimaryColor = [255,0,0,1];
evt.viewModel.palette.pathSecondaryColor = [128,128,128,1];
}else{
alert("else");
console.info(evt.viewModel.palette);
evt.viewModel.palette.pathColor = [255,0,0,1];
evt.viewModel.palette.handleColor = [255,0,0,0.8];
evt.viewModel.palette.fillColor = [255,0,0,0.3];
}
});


});
</script>
</head>

<body>
<div id="viewDiv"></div>
<div id="topbar">
<button
class="action-button esri-icon-measure-line"
id="distanceButton"
type="button"
title="Measure distance between two or more points"
></button>
<button
class="action-button esri-icon-measure-area"
id="areaButton"
type="button"
title="Measure area"
></button>
</div>
</body>
</html>

the above is me testing code.i applied the which you give it to me.But it not making any effect.

Thanks

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Nadir,

   That's because you are using the DistanceMeasurement2D and AreaMeasurement2D and Not the Measurement widget. Didn't you see the errors in the console about the Menasurement? In your code it would look like this:

      function setActiveWidget(type) {
        switch (type) {
          case "distance":
            activeWidget = new DistanceMeasurement2D({
              view: view
            });

            // skip the initial 'new measurement' button
            activeWidget.viewModel.newMeasurement();
            activeWidget.viewModel.palette.handleColor = [255, 0, 0, 0.8]
            activeWidget.viewModel.palette.pathPrimaryColor = [255, 0, 0, 1];
            activeWidget.viewModel.palette.pathSecondaryColor = [128, 128, 128, 1];

            view.ui.add(activeWidget, "top-right");
            setActiveButton(document.getElementById("distanceButton"));
            break;
          case "area":
            activeWidget = new AreaMeasurement2D({
              view: view
            });

            // skip the initial 'new measurement' button
            activeWidget.viewModel.newMeasurement();
            activeWidget.viewModel.palette.pathColor = [255, 0, 0, 1];
            activeWidget.viewModel.palette.handleColor = [255, 0, 0, 0.8];
            activeWidget.viewModel.palette.fillColor = [255, 0, 0, 0.3];

            view.ui.add(activeWidget, "top-right");
            setActiveButton(document.getElementById("areaButton"));
            break;
          case null:
            if (activeWidget) {
              view.ui.remove(activeWidget);
              activeWidget.destroy();
              activeWidget = null;
            }
            break;
        }
      }
0 Kudos
Lerman
by
Occasional Contributor

Hello Robert,

Thank you! This is a good idea, but it seems that the palette property is only present in 2d's measurement widget viewModel, I use DirectLineMeasurement3D widget, which doesn't have palette property in its corresponding viewModel. I output viewModel from the console and don't see any properties related to symbols. Do you have any suggestions? Thank you so much!

 

0 Kudos
craragon77
New Contributor III

Hello! 

So I had some trouble changing the default colors for two different measurement tool (a distance line tool and an area measurement tool from the measurement widget) in React.js. This post was SUPER helpful but I want to add a few things. I am using React.js version 17.0.1 running with Node.js v 16.0.0 and the arcgis/core package version 4.24

  • The click logic for the measurement tool runs best in a useEffect hook after the initialization of the Measurement widget (i don't know why but it runs a lot smoother)
  • The code for the area widget in the 'else' statement of the first comment works like a charm. you can plug that directly into whatever you're doing. Just be sure to change the colors you want using standard rbga css (e.g. [255, 255, 255, 1] or [255, 102, 255,0.5] )
  • The direct measurement tool color change DOES NOT work as written. the handleColor key works fine as written, but the pathPrimaryColor and pathSecondaryColor don't work because in the of the 'a' in the rgba css. When you change the colors they won't show up on the map. You have the change the 'a' to '255' to make any color appear. It took me forever to figure out why.
  • Finally, I'd recommend breaking up the 'watch' method into two separate functions honestly since the event is undefined at the moment of initialization in React.js because of how the life cycle of components work. If you look at Chrome dev tools in the console for the 'event' you'll see everything you're looking for but because info in the console is displayed RETROACTIVELY (you'll see a little 'i' icon in the console explaining why in the Chrome dev console). That's why if you have 'console.log(evt)' you'll see everything but 'console.log(evt.label)' is undefined. Because the evt.label at the moment when it prints is not defined YET. I had a tough time making the if/else work, so its easier to break up the distance and area measurement css logic into two different code blocks if possible.

Hope this helps someone out there! Good luck! You can do it!

0 Kudos
mh19
by
New Contributor II

Hello,

have anyone tried to change the colour using the ESM? I created a simple Ex WAB widget for the purposes of being able to control the colour of the measurement graphics but I can't see the palette property on the viewModel.

Also, is it possible to turn off the map measurement labels?

I found that someone submitted an idea:

https://community.esri.com/t5/arcgis-javascript-maps-sdk-ideas/measurement-2d-areameasurement2dviewm...

So hopefully available OOTB soon. 

Thank you

0 Kudos