基于上一篇文章使用OpenLayers3来展示一段运动轨迹的封装拓展
样式参数什么的都写的乱七八糟的,只是简单的实现一下。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>openlayers绘制</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0"/>
<link href="https://openlayers.org/en/v4.1.0/css/ol.css" rel="stylesheet" type="text/css" />
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.css" type="text/css" media="screen" />
<script type="text/javascript" src="https://openlayers.org/en/v4.1.0/build/ol.js"></script>
<script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=requestAnimationFrame,Element.prototype.classList,URL"></script>
<script src="https://cdn.bootcss.com/jquery/1.12.4/jquery.js"></script>
<style type="text/css">
body,html,div,ul,li,iframe,p,img{
border:none;padding:0;margin:0;
}
html{
height: 100%;
}
body{
height: 100%;
overflow: hidden;
}
li{list-style-type: none;}
#map{
width:100%;
height:100%;
}
/* 隐藏缩放按钮 */
/*#map .ol-zoom-in, #map .ol-zoom-out {
display: none;
}*/
#changeBtn1{
position: absolute;
bottom: 20px;
right: 180px;
width: 150px;
height: 30px;
line-height: 30px;
text-align: center;
background-color: #ff3366;
}
#changeBtn2{
position: absolute;
bottom: 20px;
right: 20px;
width: 150px;
height: 30px;
line-height: 30px;
text-align: center;
background-color: white;
}
.right-btn{
position: absolute;
top: 50px;
right: 0px;
width: 50px;
height: 50px;
line-height: 50px;
background-color: red;
text-align: center;
-webkit-transition:all 500ms linear;
transition:all 500ms linear;
z-index: 999;
}
.right-btn.on{
right: 150px;
-webkit-transition:all 500ms linear;
transition:all 500ms linear;
}
.right-view{
position: absolute;
top: 0px;
right: -150px;
width: 150px;
height: 100%;
line-height: 100%;
background-color: #ccc;
-webkit-transition:all 500ms linear;
transition:all 500ms linear;
z-index: 999;
}
.right-view.on{
right: 0px;
-webkit-transition:all 500ms linear;
transition:all 500ms linear;
}
.time-view{
position: absolute;
left: 3em;
top: 0.5em;
width: 100px;
line-height: 1.5em;
text-align: center;
background-color: white;
}
.player{
position: absolute;
left: 3em;
top: 3em;
width: 200px;
}
.player li{
line-height: 20px;
padding: 0px 5px;
color: white;
background-color: #ccc;
overflow: hidden;
}
.player .player-color{
margin-top: 3px;
width: 14px;
height: 14px;
float: left;
}
.player .green{background-color: green}
.player .blue{background-color: blue}
.player .red{background-color: red}
.player .player-info{margin-left: 5px; float: left;}
.player .player-live{float: right;}
.grade{position: absolute; width: 210px; left: 5%; bottom: 45px;}
.grade li {margin-top: 5px; padding: 0 5px; width: 200px; line-height: 20px; background-color: #eee; overflow: hidden;}
.grade .checkPoint{float: left;}
.grade .number{float: left; margin-left: 20px;}
.grade .distance{float: right;}
.grade .ranking{float: left; width: 15px;}
.grade img{float: left; margin: 0px 5px; width: 20px; height: 20px;}
.grade .name{float: left;}
.grade .time{float: right;}
.newGrade {position: absolute; width: 90% !important; max-width: 400px; line-height: 20px; left: 5%; bottom: 20px; background-color: #eee; padding: 0 5px;}
.newGrade img {float: left; margin: 0px 5px 0px 20px; width: 20px; height: 20px;}
.newGrade .name{float: left;}
.newGrade .time {float: right; margin-right: 30px;}
.newGrade .slow-time{background-color: black; width: 100px; line-height: 20px; text-align: center; color: white; position: absolute; right: 0px; bottom: 25px;}
</style>
</head>
<body>
<div id="map" class="map"></div>
<div id="changeBtn1" class="changeBtn2" onclick="changeMap1()">谷歌卫星图(默认)</div>
<div id="changeBtn2" class="changeBtn2" onclick="changeMap2()">谷歌地形图</div>
<div class="right-btn" onclick="showHideRightView()">点击</div>
<div class="right-view">这是一个侧边栏</div>
<div class="time-view">00:09:35</div>
<div class="player">
<li><div class="player-color green"></div><div class="player-info">XXXXXX 张三</div><div class="player-live">LIVE</div></li>
<li><div class="player-color blue"></div><div class="player-info">XXXXXX 张三</div><div class="player-live">LIVE</div></li>
<li><div class="player-color red"></div><div class="player-info">XXXXXX 张三</div><div class="player-live">LIVE</div></li>
</div>
<div class="grade">
<li><div class="checkPoint">检查点</div><div class="number">49</div><div class="distance">3.7KM</div></li>
<li><div class="ranking">1.</div><img src="" /><div class="name">张三</div><div class="time">10:45</div></li>
<li><div class="ranking">2.</div><img src="" /><div class="name">李四</div><div class="time">10:45</div></li>
<li><div class="ranking">3.</div><img src="" /><div class="name">王五</div><div class="time">10:45</div></li>
</div>
<div class="newGrade">
<img src="" />
<div class="name">王五</div>
<div class="time">10:45</div>
<div class="slow-time">-2:09</div>
</div>
<script type="text/javascript">
//使用瓦片
// 初始给的中心点坐标。
var centerX = 10711315.612909358;
var centerY = 1900873.5099405567;
var extent = [centerX, centerY, centerX, centerY];
var layer1 = new ol.layer.Tile({
source: new ol.source.XYZ({
url:'http://mt2.google.cn/vt/lyrs=y&hl=zh-CN&gl=CN&src=app&x={x}&y={y}&z={z}&s=G' //谷歌瓦片
}),
}); // 谷歌卫星地图(混合)
var layer2 = new ol.layer.Tile({
source: new ol.source.XYZ({
url:'http://mt3.google.cn/vt/lyrs=t@131,r@216000000&hl=zh-CN&gl=CN&src=app&x={x}&y={y}&z={z}&s=Gal'//谷歌地形地图
}),
}); // 谷歌地形地图
var layerImage = new ol.layer.Image({
source: new ol.source.ImageStatic({
url: 'images/mapTest.jpg',//这里添加静态图片的地址
// url: 'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1512636538327&di=1198aa77a3df42bd8046d0353502904c&imgtype=0&src=http%3A%2F%2Foss.p.t262.com%2Fcpic%2Fbc%2F2e%2Fdec7377951965a2d1dca25d006522ebc.jpg',
imageExtent: [centerX-500, centerY-500, centerX+500, centerY+500],// 地图坐标中的图像的范围。这是图像的[左,右,右,上]地图坐标
}),
}); // 自定义的地图图片
//实例一个map
var map = new ol.Map({
layers: [
// 请注意,图层按照提供的顺序进行渲染,因此,如果要使矢量图层显示在拼贴图层的顶部,则必须放在拼贴图层之后。
layer2,
layer1,
// layerImage,
],
target: 'map',
view: new ol.View({
center: [centerX, centerY], //3857坐标系
zoom: 17,//当前的放大度数
minZoom:5,//最小放大度数
maxZoom:19,//最大放大度数
// extent: extent, // Jon: 限制中心的程度,换句话说,中心不能超出这个范围, 前后值一样(minx=maxx, miny=maxy)的话就无法移动。
// Jon: 设置minZoom 和 maxZoom 一样大,就无法缩放。
}),
logo: false, // 禁用地图标志
});
//实例一个数据源获取feature
//实例化一个矢量图层Vector作为绘制层
var source = new ol.source.Vector();
// 需要传入的轨迹数据
var arr = [
[10711293.51783087, 1900921.581665377],
[10711332.930673579, 1900920.9845010934],
[10711337.707987847, 1900825.4382157368],
[10711293.51783087, 1900826.0353800203],
];
var arr1 = [
[10711293.51783087, 1900721.581665377],
[10711332.930673579, 1900720.9845010934],
[10711337.707987847, 1900625.4382157368],
[10711293.51783087, 1900626.0353800203],
];
// 管理线的数据
var lineDic = {};
// 管理点的数据
var pointDic = {};
// 管理线的源
var featureLineDic = {};
// 管理点的源
var featurePointDic = {};
// 封装一个方法,来创建全局变量的内容
// arr: 传入的数组数据, key: 管理所用的key
function createNewGeom(arr, key) {
//实例一个线(标记点), Point 点, LineString 线, Polygon 多边形
var geomLine = new ol.geom.LineString();
var geomPoint = new ol.geom.Point([arr[3][0], arr[3][1]]);
//添加标记点
for (var i = 0; i < arr.length; i++) {
geomLine.appendCoordinate(arr[i]);
}
// 加入管理数组中,方便外部调用
lineDic[key] = geomLine;
pointDic[key] = geomPoint;
var LineStringFeature = new ol.Feature(geomLine); //绘制线的数据
var pointFeature = new ol.Feature(geomPoint); //绘制点的数据
featureLineDic[key] = LineStringFeature;
featurePointDic[key] = pointFeature;
//将线添加到Vector绘制层上
source.addFeature(LineStringFeature);
source.addFeature(pointFeature);
}
//将线添加到Vector绘制层上
var vectorLayer = new ol.layer.Vector({
source: source,
style: new ol.style.Style({
stroke: new ol.style.Stroke({
color: '#f00',
width: 4
}),
image: new ol.style.Icon({
src: 'images/map.png',
anchor: [0.5, 35], //相对位置
anchorYUnits: 'pixels',
}),
})
});
map.addLayer(vectorLayer); //将绘制层添加到地图容器中
// 开启某条线的运动轨迹
// arr: 运动的轨迹数据, key: 需要开启运行的线
function startMove(arr, key) {
// 点和线都要开始运动
var geomLine = lineDic[key];
var geomPoint = pointDic[key];
// 频率
var key = setInterval(function(){
// 暂时,可删除。
var length = arr.length-1;
var lngX = arr[length][0];
var lngY = arr[length][1];
lngX = lngX - Math.random() * 30;
lngY = lngY + Math.random() * 30;
var newPoint = [lngX, lngY];
arr.shift();
arr.push(newPoint);
// 更新点和线的位置
geomLine.setCoordinates(arr);
geomPoint.setCoordinates(newPoint);
}, 300);
setTimeout(function(){
clearInterval(key);
}, 3000);
}
// 移除某条轨迹
// key: 需要关闭的线
function removeGeom(key){
// setTimeout(function(){
console.log("移除某一条轨迹");
if(featureLineDic[key]){
var LineStringFeature = featureLineDic[key];
source.removeFeature(LineStringFeature);
}
if(featurePointDic[key]){
var pointFeature = featurePointDic[key];
source.removeFeature(pointFeature);
}
delete featureLineDic[key];
delete featurePointDic[key];
// }, 5000);
}
// webSocket部分
var websocket;
var host = "ws://echo.websocket.org/";//声明host注意:是ws协议
//判断当前浏览器是否支持WebSocket
if('WebSocket' in window){
websocket = new WebSocket(host);
}
else{
alert('当前浏览器不支持WebSocket');
}
websocket.onopen = function (evt) { onOpen(evt) };
websocket.onclose = function (evt) { onClose(evt) };
websocket.onmessage = function (evt) { onMessage(evt) };
websocket.onerror = function (evt) { onError(evt) };
function onOpen(evt) {
console.log("Connected to WebSocket server.");
}
function onClose(evt) {
console.log("Disconnected");
}
function onMessage(evt) {
console.log('Retrieved data from server: ' + evt.data);
}
function onError(evt) {
console.log('Error occured: ' + evt.data);
}
//监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
window.onbeforeunload = function(){
onClose(evt);
}
// 底层地图层的切换
function changeMap1() {
layer1.setVisible(true);
layer2.setVisible(false);
}
function changeMap2() {
layer1.setVisible(false);
layer2.setVisible(true);
}
// 侧边栏的隐藏/显示
function showHideRightView() {
$(".right-btn").toggleClass('on');
$(".right-view").toggleClass('on');
removeGeom("one");
}
// 创建运动轨迹
createNewGeom(arr, "one");
createNewGeom(arr1, "two");
// 开启运动轨迹
startMove(arr, "one");
startMove(arr1, "two");
// 停止运动轨迹
// removeGeom("one");
</script>
</body>
</html>
现在需要对地图进行封装修改了一遍代码, 以下是修改的地方。
var mapDic = {};// 管理地图
var lineDic = {};// 管理线的数据
var pointDic = {};// 管理点的数据
var featureLineDic = {};// 管理线的源: Feature
var featurePointDic = {};// 管理点的源: Feature
// 创建地图控件
// 此处的id, 就是对应div的id
// obj: id, layer, centerX, centerY, zoom, layer, minZoom, maxZoom, extent
function creatMap(obj) {
var map = new ol.Map({
layers: [
obj.layer,
],
target: obj.id,
view: new ol.View({
center: [obj.centerX, obj.centerY], //3857坐标系
zoom: obj.zoom,//当前的放大度数
minZoom: obj.minZoom,//最小放大度数
maxZoom: obj.maxZoom,//最大放大度数
// extent: obj.extent, // Jon: 限制中心的程度,换句话说,中心不能超出这个范围, 前后值一样(minx=maxx, miny=maxy)的话就无法移动。
}),
logo: false, // 禁用地图标志
});
mapDic[obj.id] = map;
}
// 封装一个方法,来创建全局变量的内容
// arr: 传入的数组数据, key: 管理所用的key
function createNewGeom(arr, key, id) {
//实例一个数据源获取feature
//实例化一个矢量图层Vector作为绘制层
var source = new ol.source.Vector();// 这个东西本来是在外边放的,现在放在里边,不知道会有什么需要优化的地方
//实例一个线(标记点), Point 点, LineString 线, Polygon 多边形
var geomLine = new ol.geom.LineString();
var geomPoint = new ol.geom.Point([arr[3][0], arr[3][1]]);
//添加标记点
for (var i = 0; i < arr.length; i++) {
geomLine.appendCoordinate(arr[i]);
}
// 加入管理数组中,方便外部调用
lineDic[key] = geomLine;
pointDic[key] = geomPoint;
var LineStringFeature = new ol.Feature(geomLine); //绘制线的数据
var pointFeature = new ol.Feature(geomPoint); //绘制点的数据
featureLineDic[key] = LineStringFeature;
featurePointDic[key] = pointFeature;
//将线添加到Vector绘制层上
source.addFeature(LineStringFeature);
source.addFeature(pointFeature);
//将线添加到Vector绘制层上
var vectorLayer = new ol.layer.Vector({
source: source,
style: new ol.style.Style({
stroke: new ol.style.Stroke({
color: '#f00',
width: 4
}),
image: new ol.style.Icon({
src: 'images/map.png',
anchor: [0.5, 35], //相对位置
anchorYUnits: 'pixels',
}),
})
});
console.log("mapDic = ", mapDic);
mapDic[id].addLayer(vectorLayer); //将绘制层添加到地图容器中
}
var obj = {
id: "map",
layer: layer1,
centerX: 10711315.612909358,
centerY: 1900873.5099405567,
zoom: 17,
minZoom: 5,
maxZoom: 19,
extent: null,
}
// 创建地图
creatMap(obj);
// 创建运动轨迹
createNewGeom(arr, "one", "map");