387 lines
10 KiB
Markdown
387 lines
10 KiB
Markdown
|
---
|
||
|
title: 自定义导航
|
||
|
date: 2020-10-29
|
||
|
author: ac
|
||
|
tags:
|
||
|
- OpenLayers
|
||
|
categories:
|
||
|
- GIS
|
||
|
---
|
||
|
|
||
|
## 自定义导航
|
||
|
|
||
|
来实现一个很久以前比较流行的自定义导航控件。
|
||
|
|
||
|
这需要了解`CSS`的定位`position`和`background`属性的知识,来学习构建这个组件,后续的事件交互就是通过`View`对象控制地图视图的操作。
|
||
|
|
||
|
<img src="./images/image-20201110173336191.png" alt="image-20201110173336191" />
|
||
|
|
||
|
材料:
|
||
|
|
||
|
[map_view.png](./images/map_view.png)
|
||
|
|
||
|
[toolbar_rbg.png](./images/toolbar_rbg.png)
|
||
|
|
||
|
|
||
|
|
||
|
完整代码:
|
||
|
|
||
|
```html
|
||
|
<!doctype html>
|
||
|
<html lang="en">
|
||
|
<head>
|
||
|
<meta charset="utf-8">
|
||
|
<link rel="stylesheet" href="css/ol.css" type="text/css">
|
||
|
<style>
|
||
|
.map {
|
||
|
position: relative;
|
||
|
height: 400px;
|
||
|
width: 100%;
|
||
|
}
|
||
|
|
||
|
/*自定义导航start*/
|
||
|
.map-toolbar {
|
||
|
position: absolute;
|
||
|
left: 20px;
|
||
|
top: 20px;
|
||
|
visibility: visible;
|
||
|
width: 52px;
|
||
|
overflow: visible;
|
||
|
z-index: 150;
|
||
|
}
|
||
|
|
||
|
.map-pancontrol {
|
||
|
position: relative;
|
||
|
display: block;
|
||
|
width: 52px;
|
||
|
height: 52px;
|
||
|
background: url("./img/map_view.png") 0 175px;
|
||
|
}
|
||
|
|
||
|
.map-pan-left, .map-pan-top, .map-pan-right, .map-pan-bottom {
|
||
|
position: absolute;
|
||
|
cursor: pointer
|
||
|
}
|
||
|
|
||
|
.map-pan-left, .map-pan-right {
|
||
|
width: 12px;
|
||
|
height: 18px;
|
||
|
top: 17px
|
||
|
}
|
||
|
|
||
|
.map-pan-top, .map-pan-bottom {
|
||
|
width: 18px;
|
||
|
height: 12px;
|
||
|
left: 17px
|
||
|
}
|
||
|
|
||
|
.map-pan-left {
|
||
|
left: 8px
|
||
|
}
|
||
|
|
||
|
.map-pan-right {
|
||
|
left: 32px
|
||
|
}
|
||
|
|
||
|
.map-pan-top {
|
||
|
top: 8px
|
||
|
}
|
||
|
|
||
|
.map-pan-bottom {
|
||
|
top: 31px
|
||
|
}
|
||
|
|
||
|
.map-pan-left:hover,
|
||
|
.map-pan-top:hover,
|
||
|
.map-pan-right:hover,
|
||
|
.map-pan-bottom:hover {
|
||
|
background: url(./img/map_view.png);
|
||
|
}
|
||
|
|
||
|
.map-pan-left:hover {
|
||
|
background-position: -52px -110px
|
||
|
}
|
||
|
|
||
|
.map-pan-top:hover {
|
||
|
background-position: -70px -112px
|
||
|
}
|
||
|
|
||
|
.map-pan-right:hover {
|
||
|
background-position: -61px -110px
|
||
|
}
|
||
|
|
||
|
.map-pan-bottom:hover {
|
||
|
background-position: -84px -110px
|
||
|
}
|
||
|
|
||
|
.map-zoomcontrol {
|
||
|
position: relative;
|
||
|
left: 14px;
|
||
|
width: 24px;
|
||
|
-webkit-user-select: none;
|
||
|
-moz-user-select: none;
|
||
|
-ms-user-select: none;
|
||
|
-o-user-select: none;
|
||
|
user-select: none
|
||
|
}
|
||
|
|
||
|
.map-zoom-plus,
|
||
|
.map-zoom-minus,
|
||
|
.map-zoom-cursor {
|
||
|
background: url(./img/map_view.png);
|
||
|
cursor: pointer
|
||
|
}
|
||
|
|
||
|
.map-zoom-ruler,
|
||
|
.map-zoom-mask {
|
||
|
background: url(./img/toolbar_rbg.png);
|
||
|
cursor: pointer
|
||
|
}
|
||
|
|
||
|
.map-zoom-ruler {
|
||
|
overflow: visible
|
||
|
}
|
||
|
|
||
|
.map-zoom-plus,
|
||
|
.map-zoom-minus {
|
||
|
width: 24px;
|
||
|
height: 21px
|
||
|
}
|
||
|
|
||
|
.map-zoom-plus {
|
||
|
background-position: 0 -217px
|
||
|
}
|
||
|
|
||
|
.map-zoom-plus:hover {
|
||
|
background-position: 0 -194px
|
||
|
}
|
||
|
|
||
|
.map-zoom-minus {
|
||
|
background-position: -26px -224px
|
||
|
}
|
||
|
|
||
|
.map-zoom-minus:hover {
|
||
|
background-position: -26px -195px
|
||
|
}
|
||
|
|
||
|
.map-zoom-ruler {
|
||
|
display: block;
|
||
|
width: 12px;
|
||
|
height: 147px;
|
||
|
position: relative;
|
||
|
left: 6px;
|
||
|
background-position: 0 0
|
||
|
}
|
||
|
|
||
|
.map-zoom-mask,
|
||
|
.map-zoom-cursor {
|
||
|
position: absolute
|
||
|
}
|
||
|
|
||
|
.map-zoom-mask {
|
||
|
height: 45px;
|
||
|
width: 12px;
|
||
|
background-position: -14px 0
|
||
|
}
|
||
|
|
||
|
.map-zoom-cursor {
|
||
|
top: 45px;
|
||
|
width: 24px;
|
||
|
height: 20px;
|
||
|
left: -6px;
|
||
|
background-position: -127px -164px
|
||
|
}
|
||
|
|
||
|
.map-zoom-cursor:hover {
|
||
|
background-position: -127px -141px
|
||
|
}
|
||
|
|
||
|
.map-locate {
|
||
|
position: relative;
|
||
|
left: 17px;
|
||
|
display: block;
|
||
|
width: 18px;
|
||
|
height: 18px;
|
||
|
background: url(./img/map_view.png) -130px -185px;
|
||
|
cursor: pointer
|
||
|
}
|
||
|
|
||
|
.map-touch-toolbar .map-zoomcontrol {
|
||
|
position: absolute;
|
||
|
right: 4px;
|
||
|
bottom: -80px;
|
||
|
z-index: 500;
|
||
|
width: 35px;
|
||
|
background-color: white;
|
||
|
background-color: rgba(255, 255, 255, 0.9);
|
||
|
border-radius: 3px;
|
||
|
border: 1px solid #ccc;
|
||
|
box-shadow: 1px 1px 10px 0 #ccc
|
||
|
}
|
||
|
|
||
|
.map-touch-toolbar .map-zoomcontrol:after {
|
||
|
position: absolute;
|
||
|
content: "";
|
||
|
height: 1px;
|
||
|
background: #ddd;
|
||
|
top: 48px;
|
||
|
width: 60%;
|
||
|
margin: auto;
|
||
|
left: 0;
|
||
|
right: 0
|
||
|
}
|
||
|
|
||
|
/*自定义导航end*/
|
||
|
</style>
|
||
|
<script src="lib/ol.js"></script>
|
||
|
<title>简单控件</title>
|
||
|
</head>
|
||
|
<body>
|
||
|
<h2>自定义导航</h2>
|
||
|
<div id="mouse_position"></div>
|
||
|
<div id="map" class="map">
|
||
|
<!--自定义导航start -->
|
||
|
<div class="map-toolbar">
|
||
|
<div class="map-pancontrol">
|
||
|
<div class="map-pan-left" onclick="handleClickPan('left')"></div>
|
||
|
<div class="map-pan-top" onclick="handleClickPan('top')"></div>
|
||
|
<div class="map-pan-right" onclick="handleClickPan('right')"></div>
|
||
|
<div class="map-pan-bottom" onclick="handleClickPan('bottom')"></div>
|
||
|
</div>
|
||
|
<div class="map-locate" onclick="reposition()"></div>
|
||
|
<div class="map-zoomcontrol">
|
||
|
<div class="map-zoom-plus" onclick="handleClickZoom('plus')"></div>
|
||
|
<div class="map-zoom-ruler">
|
||
|
<div class="map-zoom-mask"></div>
|
||
|
<div class="map-zoom-cursor"></div>
|
||
|
</div>
|
||
|
<div class="map-zoom-minus" onclick="handleClickZoom('minus')"></div>
|
||
|
</div>
|
||
|
</div>
|
||
|
<!--自定义导航end -->
|
||
|
</div>
|
||
|
<script type="text/javascript">
|
||
|
|
||
|
var shenzhen = ol.proj.fromLonLat([113.958334, 22.535640]);
|
||
|
var initZoom = 12;
|
||
|
var map = new ol.Map({
|
||
|
view: new ol.View({
|
||
|
center: shenzhen,
|
||
|
zoom: initZoom,
|
||
|
maxZoom: 20,
|
||
|
minZoom: 1
|
||
|
// rotation: Math.PI/6
|
||
|
}),
|
||
|
layers: [
|
||
|
new ol.layer.Tile({
|
||
|
source: new ol.source.OSM()
|
||
|
})
|
||
|
],
|
||
|
target: "map",
|
||
|
controls: []//去除默认控件
|
||
|
});
|
||
|
var view = map.getView();
|
||
|
|
||
|
function handleClickPan(type) {
|
||
|
var oldExtent = view.calculateExtent();
|
||
|
var height = oldExtent[3] - oldExtent[1];
|
||
|
var width = oldExtent[2] - oldExtent[0];
|
||
|
var center = view.getCenter(), newCenter = null;
|
||
|
switch (type) {
|
||
|
case "left":
|
||
|
newCenter = [center[0] - width / 2, center[1]];
|
||
|
break;
|
||
|
case "top":
|
||
|
newCenter = [center[0], center[1] + height / 2];
|
||
|
break;
|
||
|
case "right":
|
||
|
newCenter = [center[0] + width / 2, center[1]];
|
||
|
break;
|
||
|
case "bottom":
|
||
|
newCenter = [center[0], center[1] - height / 2];
|
||
|
}
|
||
|
if (center) {
|
||
|
view.animate({center: newCenter});
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function reposition() {
|
||
|
view.setCenter(shenzhen);
|
||
|
view.setZoom(initZoom);
|
||
|
}
|
||
|
|
||
|
function handleClickZoom(type) {
|
||
|
var initZoom = view.getZoom();
|
||
|
if (type == "plus") {
|
||
|
view.setZoom(initZoom + 1);
|
||
|
} else if (type == "minus") {
|
||
|
view.setZoom(initZoom - 1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// ------------缩放条部分-------------
|
||
|
// 初始化缩放条
|
||
|
function getCalcMaskHeight() {
|
||
|
var zoomBarHeight = document.getElementsByClassName("map-zoom-ruler")[0].clientHeight;
|
||
|
var maskHeight = document.getElementsByClassName("map-zoom-cursor")[0].clientHeight;
|
||
|
var zoomSilderHeight = zoomBarHeight - maskHeight / 2;
|
||
|
|
||
|
var maxZoom = view.getMaxZoom();
|
||
|
var minZoom = view.getMinZoom();
|
||
|
var currZoom = view.getZoom();
|
||
|
return (currZoom - minZoom) / (maxZoom - minZoom) * zoomSilderHeight;
|
||
|
}
|
||
|
|
||
|
var initMaskHeight = getCalcMaskHeight()
|
||
|
document.getElementsByClassName("map-zoom-mask")[0].style.height = initMaskHeight + "px";
|
||
|
document.getElementsByClassName("map-zoom-cursor")[0].style.top = initMaskHeight + "px";
|
||
|
|
||
|
//缩放条的拖动
|
||
|
document.getElementsByClassName("map-zoom-cursor")[0].onmousedown = function (evt) {
|
||
|
var that = this;
|
||
|
var oEvent = evt || event;
|
||
|
var disY = oEvent.clientY - parseInt(that.style.top);
|
||
|
|
||
|
that.onmousemove = function (evt) { //实时改变目标元素obox的位置
|
||
|
var oEvent = evt || event;
|
||
|
var curY = oEvent.clientY - disY;
|
||
|
//修改移动cursor的位置
|
||
|
if (curY < 0) {
|
||
|
that.style.top = 1 + 'px';
|
||
|
} else if (curY > 135) {
|
||
|
that.style.top = 135 + 'px';
|
||
|
} else {
|
||
|
that.style.top = oEvent.clientY - disY + 'px';
|
||
|
}
|
||
|
//修改mask的位置
|
||
|
document.getElementsByClassName("map-zoom-mask")[0].style.height = that.style.top;
|
||
|
//设置地图
|
||
|
var zoomBarHeight = document.getElementsByClassName("map-zoom-ruler")[0].clientHeight;
|
||
|
var maxZoom = view.getMaxZoom();
|
||
|
var minZoom = view.getMinZoom();
|
||
|
var newZoom = minZoom + (maxZoom - minZoom) * (parseInt(that.style.top) / zoomBarHeight);
|
||
|
view.setZoom(newZoom);
|
||
|
};
|
||
|
//停止拖动
|
||
|
that.onmouseup = function () {
|
||
|
that.onmousemove = null;
|
||
|
that.onmouseup = null;
|
||
|
};
|
||
|
that.onmouseout = function () {
|
||
|
that.onmousemove = null;
|
||
|
that.onmouseout = null;
|
||
|
};
|
||
|
}
|
||
|
//绑定视图的缩放事件
|
||
|
view.on("change:resolution", function changeResolution(e) {
|
||
|
var maskHeight = getCalcMaskHeight();
|
||
|
document.getElementsByClassName("map-zoom-mask")[0].style.height = maskHeight + "px";
|
||
|
document.getElementsByClassName("map-zoom-cursor")[0].style.top = maskHeight + "px";
|
||
|
})
|
||
|
|
||
|
</script>
|
||
|
</body>
|
||
|
</html>
|
||
|
```
|
||
|
|