当我们使用ArcGIS JS API开发项目时,经常会用到地图测量控件,用于测量地图上两点之间的距离、一片区域的面积或周长等,但是ArcGIS JS API测量控件自带的默认样式是黄白相间的大粗线,这在用户看来是很不美观的,所以就需要我们对其进行一些样式优化。
在使用ArcGIS API for JavaScript 4.17开发项目时,有一个需求是需要在地图上添加距离测量和面积测量的控件,这其实很简单,直接调用ArcGIS JS API自带的测量控件就可以实现,但是客户对控件自带的黄白相间、并且略粗的默认样式不满意,所以需要修改ArcGIS JS API自带的测量控件默认样式。
我们先来看看ArcGIS JS API自带的默认样式:
然后再来看看客户想要的样式:
其实说白了就是要更改默认样式的宽度和颜色。
遇到这种需求的话,下意识就去看看ArcGIS JS API的官网有没有提供可以直接使用的API,但是经过一番查找后发现是没有的,那接下来就只能找找其他的地图JS库里面有没有了,如果有的话就试试能不能用于ArcGIS的底图,其实除了这种做法之外还有另一种做法,就是找到ArcGIS JS API的源码文件,直接改里面的css样式代码就可以,最后在”AriaGIS“大佬的帮助下发现确实是行得通的,但是考虑到目前项目中使用的ArcGIS JS API地址是在线的官网地址,所以没法用这种方法,那就只能再想想其他办法了。 最后找了好久没找到最优的方法,就先自己写了一个方法,但是最近在逛ArcGIS知乎的时候发现我当初的帖子有大佬回复了,并且还附加demo,所以我就拿来试试,结果测试发现是可行的。知乎帖子链接如下:
http://zhihu.geoscene.cn/question/38481
解决方法的话其实很简单,就是监听测量控件的激活事件,然后修改它的绘制句柄里面自带的样式属性即可。但是虽然说简单,自己找了好久也没找到,所以大佬还是牛批啊。下面分别介绍在二维和三维下的修改方法,demo代码就是对大佬的代码做了一下简单修改过后的。
const measurement = new Measurement();
// 监听测量控件的激活事件
measurement.watch('activeWidget', function (evt) {
if (evt !== null) {
// 分别修改距离测量和面积测量句柄的默认样式
if (measurement.activeTool === 'distance') {
evt.viewModel.palette.handleColor = [
255,
64,
64,
0.5,
];
evt.viewModel.palette.pathPrimaryColor = [
255,
48,
48,
1,
];
evt.viewModel.palette.pathSecondaryColor = [
255,
48,
48,
1,
];
evt.viewModel.palette.handleWidth = 8;
evt.viewModel.palette.pathWidth = 2;
} else {
evt.viewModel.palette.fillColor = [
255,
48,
48,
0.3,
];
evt.viewModel.palette.handleColor = [
255,
64,
64,
0.5,
];
evt.viewModel.palette.pathColor = [
255,
48,
48,
0.8,
];
}
}
});
measurement.activeTool = 'distance'; // 距离测量
measurement.activeTool = 'area'; // 面积测量
三维下如果按照二维的方式修改的话会报错,具体原因是三维下绘制句柄中并没有palette属性导致的,所以三维下测量控件的样式更改暂未找到方法,最后跟用户沟通,取消了三维中的测量功能,但是回到公司后验证发现,三维下的测量确实比较复杂,而且我感觉ArcGIS JS API三维下的测量已经做的很厉害了,哈哈,没必要修改啊,比如下面的效果图这样:
如果实在想更改的话,就等我后期再找找资源吧,此处代码待更新
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta
name="viewport"
content="initial-scale=1,maximum-scale=1,user-scalable=no"
/>
<title>
Measurement widget | Sample | ArcGIS API for JavaScript 4.17
</title>
<style>
html,
body,
#viewDiv {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
}
#toolbarDiv {
position: absolute;
top: 15px;
right: 15px;
cursor: default;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
}
#infoDiv {
position: absolute;
top: 15px;
left: 60px;
}
#infoDiv input {
border: none;
box-shadow: rgba(0, 0, 0, 0.3) 0px 1px 2px;
}
.esri-widget--button.active,
.esri-widget--button.active:hover,
.esri-widget--button.active:focus {
cursor: default;
background-color: #999696;
}
.esri-widget--button.active path,
.esri-widget--button.active:hover path,
.esri-widget--button.active:focus path {
fill: #e4e4e4;
}
</style>
<link
rel="stylesheet"
href="https://js.arcgis.com/4.17/esri/themes/light/main.css"
/>
<script src="https://js.arcgis.com/4.17/"></script>
<script>
require([
'esri/Map',
'esri/views/MapView',
'esri/widgets/Measurement',
], function (Map, MapView, Measurement) {
const map = new Map({
basemap: 'osm',
});
const mapView = new MapView({
container: 'viewDiv',
zoom: 6,
center: [26.1025, 44.4268],
map: map,
});
const measurement = new Measurement();
// 监听测量控件的激活事件
measurement.watch('activeWidget', function (evt) {
if (evt !== null) {
// 分别修改距离测量和面积测量句柄的默认样式
if (measurement.activeTool === 'distance') {
evt.viewModel.palette.handleColor = [
255,
64,
64,
0.5,
];
evt.viewModel.palette.pathPrimaryColor = [
255,
48,
48,
1,
];
evt.viewModel.palette.pathSecondaryColor = [
255,
48,
48,
1,
];
evt.viewModel.palette.handleWidth = 8;
evt.viewModel.palette.pathWidth = 2;
} else {
evt.viewModel.palette.fillColor = [
255,
48,
48,
0.3,
];
evt.viewModel.palette.handleColor = [
255,
64,
64,
0.5,
];
evt.viewModel.palette.pathColor = [
255,
48,
48,
0.8,
];
}
}
});
const distanceButton = document.getElementById('distance');
const areaButton = document.getElementById('area');
const clearButton = document.getElementById('clear');
distanceButton.addEventListener('click', function () {
distanceMeasurement();
});
areaButton.addEventListener('click', function () {
areaMeasurement();
});
clearButton.addEventListener('click', function () {
clearMeasurements();
});
loadView();
function loadView() {
mapView.ui.add(measurement, 'bottom-right');
measurement.view = mapView;
}
// 距离测量
function distanceMeasurement() {
measurement.activeTool = 'distance';
distanceButton.classList.add('active');
areaButton.classList.remove('active');
}
// 面积测量
function areaMeasurement() {
measurement.activeTool = 'area';
distanceButton.classList.remove('active');
areaButton.classList.add('active');
}
// 清屏
function clearMeasurements() {
distanceButton.classList.remove('active');
areaButton.classList.remove('active');
measurement.clear();
}
});
</script>
</head>
<body>
<div id="viewDiv"></div>
<div id="toolbarDiv" class="esri-component esri-widget">
<button
id="distance"
class="esri-widget--button esri-interactive esri-icon-measure-line"
title="Distance Measurement Tool"
></button>
<button
id="area"
class="esri-widget--button esri-interactive esri-icon-measure-area"
title="Area Measurement Tool"
></button>
<button
id="clear"
class="esri-widget--button esri-interactive esri-icon-trash"
title="Clear Measurements"
></button>
</div>
</body>
</html>
代码待更新