寫在前面
之前寫了一篇關於在ArcGIS地圖上添加圖片的文章,關注度還可以,在項目中也用文章中提到的技術路線實現了地圖疊加圖片的需求。但是最近客戶又有了新需求,因爲我們在之前的文章中通過擴展圖層來實現圖片添加後,如果圖片中某一處的信息比較豐富,在地圖縮放的一瞬間如果我們拖動地圖的話,那部分的圖片會有卡頓。其實這情況不算嚴重,因爲僅僅卡頓那麼一秒鐘左右而已,但是客戶抓着這個點就要較勁,那沒辦法,來一波優化吧。
之前文章的地址如下:《07 ArcGIS JS API 4.14實現地圖加載圖片》。
最終的效果如下:
具體操作
1、因爲之前的技術路線是通過擴展BaseDynamicLayer這個類來實現的,所以底層還是使用canvas繪製技術,將圖片繪製到了我們的地圖上。那這樣一來,在圖片上信息比較豐富的地方繪製的時候就比較慢,肯定會有一丟丟的卡頓,儘管後期使用雙緩衝技術也沒有得到優化,所以這篇文章我們採用另一種方式來實現地圖疊加圖片。
2、這篇文章直接使用img標籤來做,原理很簡單,我們直接在地圖渲染的canvas標籤處另外添加一個img標籤,然後通過監聽地圖的視圖區域變化來動態改變圖片大小和位置即可。
3、首先,我們實例化一張二維地圖,代碼如下:
<!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標籤,並指定一些屬性,如下:
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標籤指定樣式纔可以看到我們添加後的圖片,所以接下來我們直接監聽地圖的視圖變化,在這裏面爲其指定樣式和相應的位置:
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、完成以上操作後,我們就成功的實現了地圖加載圖片的過程,這樣一來,我們添加上去的圖片在地圖進行縮放的時候,並不會有卡頓的現象了。
附:
全部代碼:
<!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>