作者:LX
一、 背景
上一篇文章《流数据存储之Elasticsearch》介绍了如何将流数据存储到Elasticsearch中,本文将进一步介绍一下如何将存储在Elasticsearch中的数据通过iClient展示出来。
二、 开发准备
1、将数据存储到ES数据库中
查看ES数据库中的数据:
2、iClient开发包:9D及以上版本
三、 开发代码
以iClient for Leaflet为例:
1、 引入iClient的js库
<script type="text/javascript" include="moment" src="../js/include-web.js"></script>
<script type="text/javascript" include="mapv,elasticsearch" src="../../dist/leaflet/include-leaflet.js"></script>
2、 定义一幅地图作为底图
initMap();
function initMap() {
if (!map) {
map = L.map('map', {
crs: L.CRS.EPSG3857,
center: [31.3677, 108.116],
maxZoom: 20,
minZoom: 3,
zoom: 7
});
var url ="http://support.supermap.com.cn:8090/iserver/services/map-china400/rest/maps/ChinaDark";
L.supermap.tiledMapLayer(url).addTo(map);
}
}
3、 初始化ElasticSearch服务
//ElasticSearch数据库的地址
var dataUrl = "http://localhost:9200";
//初始化ElasticSearch服务
liveESService = new SuperMap.ElasticSearch(dataUrl);
4、 设定初始化参数
//startTime开始时间;endTime 结束时间;speed 刷新步长;frequency 刷新频率
var options ={startTime: 1498781767000, endTime: 1498935332000, speed: 1000, frequency: 100};
5、 定义时间管理控件
timeControl = new SuperMap.TimeFlowControl(loadLiveData, options);
6、 时间控制器回调参数,即每次刷新时执行的操作,此处为ElasticSearch请求数据并绘制。实时刷新执行
function loadLiveData(currentTime) {
//时间戳转换成时间
var datetime = moment(currentTime).format("YYYY-MM-DDTHH:mm:ss") + "Z";
//航班ID
var flightIds=["CCA4189", "CCA4187", "CBJ5531", "CSC8747", "TBA9879", "CCA4113", "CES2251", "CCA4521", "CSC8927", "CSC8811", "CSC8857", "UEA2711", "UEA2205", "CCA4439", "CCA415", "CSC8719", "CSC8555", "CCA4211", "HDA825"];
var liveParameters = [];
for (var i = 0; i < flightIds.length; i++) {
var code =flightIds[i];
if (code === 'ZUUU') {
continue;
}
//设定搜索条件
liveParameters.push({index: "flights", type: "flight_utc"});
liveParameters.push({
"query": {
"bool": {
"must": {"match": {"ident": code}},
"filter": {"match": {"datetime": datetime}},
}
},
"sort": {"time-ms": {"order": "ASC"}},
"from": 0,
"size": 20
});
}
//同时执行flightIds中所有航班信息的搜索
liveESService.msearch({body: liveParameters}, function (error, result) {
if (error) {
widgets.alert.showAlert(JSON.stringify(error), false);
timeControl.stop();
return;
}
result.responses && renderData.call(window, result.responses);
});
//更新当前时间界面
$("#progress").html(datetime);
}
7、 解析点查询结果数据为mapv数据
function createLiveRendererData(results) {
var data = [];
results && results.map(function (result) {
result.hits.hits.map(function (source) {
var content = source._source;
var img = new Image();
img.src = './planeRed.png';
data.push({
geometry: {
type: 'Point',
coordinates: [content.x, content.y],
},
deg: content.direction, //飞机方向
icon: img, //飞机样式图片
ident: content.ident,
content: content
});
});
});
return data
}
8、 更新数据
function updateDataSet(data) {
if (!liveDataSet) {
liveDataSet = new mapv.DataSet(data);
return;
}
var dat = data.slice();
var innerData = liveDataSet.get();
for (var i = 0; i < dat.length; i++) {
for (var j = 0; j < innerData.length; j++) {
if (dat[i].ident === innerData[j].ident) {
innerData[j] = dat[i];
break;
}
}
//如果是新的飞机Id则追加到飞机数组里
if (j === innerData.length) {
innerData.push(dat[i]);
}
}
liveDataSet.set(innerData);
}
9、 渲染实时点数据到mapv图层
function renderData(result) {
if (timeControl && !timeControl.getRunning()) {
return;
}
var data = createLiveRendererData(result);
if (data.length < 1) {
return;
}
updateDataSet(data);
if (!liveRenderer) {
//定义mapv图层并渲染到地图上
liveRenderer = L.supermap.mapVLayer(liveDataSet, {
zIndex: 800,
draw: 'icon'
}).addTo(map);
} else {
liveRenderer.update({data: liveDataSet});
}
}
10、控制时间管理器的执行
通过页面上的按钮控制时间管理器的开始、暂停、停止
//开始播放
function start() {
timeControl.start();
stopRender = false;
}
//暂停播放
function pause() {
timeControl && timeControl.pause();
}
//停止播放
function stop() {
stopRender = true;
timeControl && timeControl.stop();
clearAll();
}
11、结果展示
附上完整代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title data-i18n="resources.title_ESHeatMap"></title>
<script type="text/javascript" include="moment" src="../js/include-web.js"></script>
</head>
<body style=" margin: 0;overflow: hidden;background: #fff;width: 100%;height:100%;position: absolute;top: 0;">
<div id="map" style="margin:0 auto;width: 100%;height: 100%;border: 1px solid #dddddd">
<div style="width: 250px;;height: 100px;right: 20px;top: 20px;background-color: #dddddd;z-index: 99999;position: absolute;text-align:center; border-radius: 5px;">
<div id="time" style="font-size:14px;width: 250px;padding-right: 5px;margin-top: 12px;">
<div>
<label for='progress'>当前时间:</label><span id='progress'>未开始</span>
</div>
<br>
<input id='start' type='button'value=开始 onclick="start()">
<input id='pause' type='button' value=暂停 onclick="pause()">
<input id='stop' type='button' value=停止 onclick="stop()">
</div>
</div>
</div>
<script type="text/javascript" include="mapv,elasticsearch" src="../../dist/leaflet/include-leaflet.js"></script>
<script type="text/javascript">
var map;
var timeControl,
liveESService,//实时点查询的ESService
liveRenderer,//实时点层
liveDataSet,//渲染用实时点数据集
dataUrl = "http://localhost:9200";//ElasticSearch数据库的地址
initMap();
function initMap() {
if (!map) {
map = L.map('map', {
crs: L.CRS.EPSG3857,
center: [31.3677, 108.116],
maxZoom: 20,
minZoom: 3,
zoom: 7
});
var url ="http://support.supermap.com.cn:8090/iserver/services/map-china400/rest/maps/ChinaDark";
L.supermap.tiledMapLayer(url).addTo(map);
}
}
//定义ElasticSearch服务
liveESService = new SuperMap.ElasticSearch(dataUrl);
//定义初始化参数
var options ={startTime: 1498781767000, endTime: 1498935332000, speed: 1000, frequency: 100};
//定义时间管理控件
if (!timeControl) {
timeControl = new SuperMap.TimeFlowControl(loadLiveData, options);
} else {
timeControl.updateOptions(options);
}
//开始播放
function start() {
timeControl.start();
stopRender = false;
}
//暂停播放
function pause() {
timeControl && timeControl.pause();
}
//停止播放
function stop() {
stopRender = true;
timeControl && timeControl.stop();
clearAll();
}
//时间控制器回调参数,即每次刷新时执行的操作,此处为向服务器请求数据并绘制。实时刷新执行。
function loadLiveData(currentTime) {
//时间戳转换成时间
var datetime = moment(currentTime).format("YYYY-MM-DDTHH:mm:ss") + "Z";
//航班ID
var flightIds=["CCA4189", "CCA4187", "CBJ5531", "CSC8747", "TBA9879", "CCA4113", "CES2251", "CCA4521", "CSC8927", "CSC8811", "CSC8857", "UEA2711", "UEA2205", "CCA4439", "CCA415", "CSC8719", "CSC8555", "CCA4211", "HDA825"];
var liveParameters = [];
for (var i = 0; i < flightIds.length; i++) {
var code =flightIds[i];
if (code === 'ZUUU') {
continue;
}
//设定搜索条件
liveParameters.push({index: "flights", type: "flight_utc"});
liveParameters.push({
"query": {
"bool": {
"must": {"match": {"ident": code}},
"filter": {"match": {"datetime": datetime}},
}
},
"sort": {"time-ms": {"order": "ASC"}},
"from": 0,
"size": 20
});
}
//同时执行flightIds中所有航班信息的搜索
liveESService.msearch({body: liveParameters}, function (error, result) {
if (error) {
widgets.alert.showAlert(JSON.stringify(error), false);
timeControl.stop();
return;
}
result.responses && renderData.call(window, result.responses);
});
//更新当前时间界面
$("#progress").html(datetime);
}
//解析点查询结果数据为mapv数据
function createLiveRendererData(results) {
var data = [];
results && results.map(function (result) {
result.hits.hits.map(function (source) {
var content = source._source;
var img = new Image();
img.src = './planeRed.png';
data.push({
geometry: {
type: 'Point',
coordinates: [content.x, content.y],
},
deg: content.direction,//飞机方向
icon: img,//飞机样式图片
ident: content.ident,
content: content
});
});
});
return data
}
//更新数据
function updateDataSet(data) {
if (!liveDataSet) {
liveDataSet = new mapv.DataSet(data);
return;
}
var dat = data.slice();
var innerData = liveDataSet.get();
for (var i = 0; i < dat.length; i++) {
for (var j = 0; j < innerData.length; j++) {
if (dat[i].ident === innerData[j].ident) {
innerData[j] = dat[i];
break;
}
}
//如果是新的飞机Id则追加到飞机数组里
if (j === innerData.length) {
innerData.push(dat[i]);
}
}
liveDataSet.set(innerData);
}
//渲染实时点数据
function renderData(result) {
if (timeControl && !timeControl.getRunning()) {
return;
}
var data = createLiveRendererData(result);
if (data.length < 1) {
return;
}
updateDataSet(data);
if (!liveRenderer) {
//定义mapv图层并渲染到地图上
liveRenderer = L.supermap.mapVLayer(liveDataSet, {
zIndex: 800,
draw: 'icon',
width: 25, // 图像的宽度
height: 25, // 图像的高度
}).addTo(map);
} else {
liveRenderer.update({data: liveDataSet});
}
}
function clearAll() {
if (timeControl) {
timeControl.destroy();
timeControl = null;
}
if (liveRenderer) {
map.removeLayer(liveRenderer);
liveRenderer = null;
}
if (liveDataSet) {
liveDataSet = null;
}
}
</script>
</body>
</html>