0%

ArcGIS JS API 4.15实现地图加载图片(优化版)

主要介绍如何用ArcGIS JS API 4.15实现在二维地图中添加图片的操作。上一篇文章已经介绍了如何添加图片的四种方法,但是添加到地图上的图片在拖动时有些卡顿,所以本文又提出了另一种优化的方法。

写在前面

之前写了一篇关于在ArcGIS地图上添加图片的文章,关注度还可以,在项目中也用文章中提到的技术路线实现了地图叠加图片的需求。但是最近客户又有了新需求,因为我们在之前的文章中通过扩展图层来实现图片添加后,如果图片中某一处的信息比较丰富,在地图缩放的一瞬间如果我们拖动地图的话,那部分的图片会有卡顿。其实这情况不算严重,因为仅仅卡顿那么一秒钟左右而已,但是客户抓着这个点就要较劲,那没办法,来一波优化吧。

之前文章的地址如下:《ArcGIS JS API 4.14实现地图加载图片》。

最终的效果如下:

img

具体操作

1、因为之前的技术路线是通过扩展BaseDynamicLayer这个类来实现的,所以底层还是使用canvas绘制技术,将图片绘制到了我们的地图上。那这样一来,在图片上信息比较丰富的地方绘制的时候就比较慢,肯定会有一丢丢的卡顿,尽管后期使用双缓冲技术也没有得到优化,所以这篇文章我们采用另一种方式来实现地图叠加图片。

2、这篇文章直接使用img标签来做,原理很简单,我们直接在地图渲染的canvas标签处另外添加一个img标签,然后通过监听地图的视图区域变化来动态改变图片大小和位置即可。

3、首先,我们实例化一张二维地图,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
<title>Intro to MapView - Create a 2D map - 4.15</title>
<style>
html,
body,
#viewDiv {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
}
</style>
<link rel="stylesheet" href="http://localhost/4.15/esri/themes/light/main.css" />
<script src="http://localhost/4.15/init.js"></script>
<script>
require(['esri/Map', 'esri/views/MapView', 'esri/core/watchUtils'], function (Map, MapView, watchUtils) {
var map = new Map({
basemap: 'osm',
});
var view = new MapView({
container: 'viewDiv',
map: map,
zoom: 7,
center: [104.071883, 30.664022], // longitude, latitude
});
});
</script>
</head>
<body>
<div id="viewDiv"></div>
</body>
</html>

4、然后我们在地图初始化完成之后获取地图渲染的标签,在它同级的地方添加一个img标签,并指定一些属性,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
var resultDom;
view.when(function () {
//添加图片
var selectDom = document.getElementsByClassName(
'esri-view-surface esri-view-surface--inset-outline esri-view-surface--touch-none',
);
console.log(extent);
resultDom = document.createElement('img');
resultDom.src = './testquickviewphoto.png';
resultDom.className = 'mystyle';
resultDom.id = 'mystyle';
selectDom[0].appendChild(resultDom);
});

5、这样一来,我们的图片就已经添加到了地图上,需要我们为这个img标签指定样式才可以看到我们添加后的图片,所以接下来我们直接监听地图的视图变化,在这里面为其指定样式和相应的位置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
let extent = {    //图片的范围
xmin: 10138549.59667821,
ymin: 3449716.2722409572,
xmax: 10249869.087471481,
ymax: 3578363.913808475,
};
var absd = view.zoom;
watchUtils.when(view, 'extent', function () {
if (view.extent && document.getElementById('mystyle')) {
var lefttop = {
x: extent.xmin,
y: extent.ymax,
spatialReference: {
wkid: 102100,
},
};
var screen_lefttop = view.toScreen(lefttop);
document.getElementById('mystyle').style.top = screen_lefttop.y + 'px';
document.getElementById('mystyle').style.left = screen_lefttop.x + 'px';
//zoom未改变的情况下不重新计算image长和宽
if (absd != view.zoom) {
var rightbottom = {
x: extent.xmax,
y: extent.ymin,
spatialReference: {
wkid: 102100,
},
};
var screen_rightbottom = view.toScreen(rightbottom);
document.getElementById('mystyle').style.width =
screen_rightbottom.x - screen_lefttop.x + 'px';
document.getElementById('mystyle').style.height =
screen_rightbottom.y - screen_lefttop.y + 'px';
}
}
});

6、完成以上操作后,我们就成功的实现了地图加载图片的过程,这样一来,我们添加上去的图片在地图进行缩放的时候,并不会有卡顿的现象了。

附:

全部代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
<title>Intro to MapView - Create a 2D map - 4.15</title>
<style>
html,
body,
#viewDiv {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
}
.mystyle {
position: absolute;
top: 937px;
left: 0px;
width: 1920px;
height: 937px;
}
</style>
<link rel="stylesheet" href="http://localhost/4.15/esri/themes/light/main.css" />
<script src="http://localhost/4.15/init.js"></script>
<script>
require(['esri/Map', 'esri/views/MapView', 'esri/core/watchUtils'], function (Map, MapView, watchUtils) {
var map = new Map({
basemap: 'osm',
});
var view = new MapView({
container: 'viewDiv',
map: map,
zoom: 7,
center: [104.071883, 30.664022], // longitude, latitude
});
let extent = {
xmin: 10138549.59667821,
ymin: 3449716.2722409572,
xmax: 10249869.087471481,
ymax: 3578363.913808475,
};
var resultDom;
view.when(function () {
//添加图片
var selectDom = document.getElementsByClassName(
'esri-view-surface esri-view-surface--inset-outline esri-view-surface--touch-none',
);
console.log(extent);
resultDom = document.createElement('img');
resultDom.src = './testquickviewphoto.png';
resultDom.className = 'mystyle';
resultDom.id = 'mystyle';
selectDom[0].appendChild(resultDom);
});
var absd = view.zoom;
watchUtils.when(view, 'extent', function () {
if (view.extent && document.getElementById('mystyle')) {
var lefttop = {
x: extent.xmin,
y: extent.ymax,
spatialReference: {
wkid: 102100,
},
};
var screen_lefttop = view.toScreen(lefttop);
document.getElementById('mystyle').style.top = screen_lefttop.y + 'px';
document.getElementById('mystyle').style.left = screen_lefttop.x + 'px';
//zoom未改变的情况下不重新计算image长和宽
if (absd != view.zoom) {
var rightbottom = {
x: extent.xmax,
y: extent.ymin,
spatialReference: {
wkid: 102100,
},
};
var screen_rightbottom = view.toScreen(rightbottom);
document.getElementById('mystyle').style.width =
screen_rightbottom.x - screen_lefttop.x + 'px';
document.getElementById('mystyle').style.height =
screen_rightbottom.y - screen_lefttop.y + 'px';
}
}
});
setTimeout(reloadPhoto, 500);
function reloadPhoto() {
//console.log(extent.xmax)
//左下角
var leftbottom = {
x: extent.xmin,
y: extent.ymin,
spatialReference: {
wkid: 102100,
},
};
var screen_leftbottom = view.toScreen(leftbottom);
//右上角
var righttop = {
x: extent.xmax,
y: extent.ymax,
spatialReference: {
wkid: 102100,
},
};
var screen_righttop = view.toScreen(righttop);
document.getElementById('mystyle').style.top = screen_righttop.y + 'px';
document.getElementById('mystyle').style.left = screen_leftbottom.x + 'px';
document.getElementById('mystyle').style.width =
Math.abs(screen_righttop.x - screen_leftbottom.x) + 'px';
document.getElementById('mystyle').style.height =
Math.abs(screen_righttop.y - screen_leftbottom.y) + 'px';
}
});
</script>
</head>
<body>
<div id="viewDiv"></div>
</body>
</html>