如今的商場管理者在管理商場的同時面臨着一些沒法避免的問題好比:人員監管不到位、效率低下、商場同質化嚴重,人流量少等。發現了這些問題做爲開發人員的咱們怎能視而不見,咱們的責任就是發現問題解決問題,提供更好更智能的服務。所以就此問題咱們想出了相應的解決辦法,使用JS+Three.js+Echart開發了一個功能界面,爲商場管理者提供更加高效的管理方法。javascript
經過商場管理系統的相應界面,商場管理者可實時獲取商場的人流數據、人流密度的熱力分佈、可實時查看商場各處的視頻監控信息、安保人員的實時位置信息及運動軌跡。針對突發情況能夠即時調度、快速處理。還能夠依據大數據分析周邊業態狀況,爲制定運營策略提供數據支持等。html
就以上的市場實際狀況需求,開始了個人功能開發之旅。java
我使用ESMap的地圖編輯器編輯好商場地圖後,開始佈局規劃解決問題node
開發流程以下:web
首先,實現一個商場客流量信息的餅狀統計表,還有各個時間點的流量趨勢和人羣密度的線性圖表。再實現一個控制面板,能夠經過控制面板根據地圖的熱力圖查看商場各個位置客流量以及各個位置的實時視頻等,狀況一目瞭然;最後作一個能夠搜索店鋪客流量及營業額狀況的搜索框。json
1.方便開發,先使用模擬數據建立圖表,投入使用後自行接入後臺數據便可。canvas
(1)使用Echart建立統計客流量的餅狀圖:數組
function circleSet() { myChart1 = echarts.init(document.getElementById('ec1')); myChart2 = echarts.init(document.getElementById('ec2')); var color= ['#b679fe', '#6271fd','#94d96c', '#0fbdd9','#f0f0f0']; var dataStyle = { normal: { label: { show: false }, labelLine: { show: false }, shadowBlur: 40, borderWidth: 10, shadowColor: 'rgba(0, 0, 0, 0)' //邊框陰影 } }; //第一個餅狀圖
var optionCircleA = { backgroundColor: '#fff', title: { text: '52452', x: 'center', y: 'center', textStyle: { fontWeight: 'normal', fontSize: 14, color: "#b679fe", } }, series: [{ name: 'Line 1', type: 'pie', clockWise: false, radius: [37, 45], center:['50%','50%'], itemStyle: dataStyle, hoverAnimation: false, startAngle: 90, label:{ borderRadius:'10', }, data: [{ value: 54.6, name: '外', itemStyle: { normal: { color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{ offset: 0, color:color[0] }, { offset: 1, color: color[1] }]) } } }, { value: 0, name: '', tooltip: { show: false }, }, ] }, { name: 'Line 2', type: 'pie', clockWise: false, radius: [30, 32], center:['50%','50%'], itemStyle: dataStyle, hoverAnimation: false, startAngle: 90, data: [{ value: 56.7, name: '內', itemStyle: { normal: { color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{ offset: 0, color: color[4] }, { offset: 1, color: color[4] }]) } } }, { value: 0, name: '', tooltip: { show: false }, }, ] }, ] }; //第二個餅狀圖
var optionCircleB = { backgroundColor: '#fff', title: { text: '15386', x: 'center', y: 'center', textStyle: { fontWeight: 'normal', fontSize: 14, color: "#94d96c", } }, series: [{ name: 'Line 1', type: 'pie', clockWise: false, radius: [37, 45], center:['50%','50%'], itemStyle: dataStyle, hoverAnimation: false, startAngle: 90, label:{ borderRadius:'10', }, data: [{ value: 54.6, name: '外', itemStyle: { normal: { color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{ offset: 0, color:color[2] }, { offset: 1, color: color[3] }]) } } }, { value: 0, name: '', tooltip: { show: false }, }, ] }, { name: 'Line 2', type: 'pie', clockWise: false, radius: [30, 32], center:['50%','50%'], itemStyle: dataStyle, hoverAnimation: false, startAngle: 90, data: [{ value: 56.7, name: '內', itemStyle: { normal: { color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{ offset: 0, color: color[4] }, { offset: 1, color: color[4] }]) } } }, { value: 0, name: '', tooltip: { show: false }, }, ] }, ] }; myChart1.setOption(optionCircleA); myChart2.setOption(optionCircleB); }
效果以下圖:app
(2)使用echart建立人羣密度線性圖表,封裝在函數lineSetA()內:echarts
//人羣密度線性圖表
function lineSetA() { myChart3 = echarts.init(document.getElementById('ec3')); var colors = ['#12c3f8', '#4384d7']; optionLineA = { color: colors, visualMap: [{ show: false, type: 'continuous', seriesIndex: 0, min: 0, max: 600, borderWidth: 3, color: colors, }], xAxis: { type: 'category', data: ['0', '2', '4', '6', '8', '10', '12', '14', '16', '18', '20', '22'], show: true, position: { bottom: 10, show: false, }, onZero: false, axisLine: { lineStyle: { width: 0, } } }, yAxis: { type: 'value', axisLabel: { formatter: '{value} 人', fontSize: 10, }, axisLine: { lineStyle: { width: 0, } }, minInterval: 300, }, grid: [{ top: '40', bottom: '25', left: '50', right: '10' }], series: [{ data: [ 0, 10, 20, 30, 40, 100, 600, 900, 880, 900, 1100, 1000], type: 'line', smooth: true, markPoint: { data: [ { name: '880', coord: ['16','880'], value: '880', ], label: { show: true, }, } }] }; myChart3.setOption(optionLineA); }
建立流量趨勢線性圖表,封裝在函數lineSetB()內:
//流量趨勢線性圖表
function lineSetB() { myChart4 = echarts.init(document.getElementById('ec3')); var colors = ['#12c3f8', '#4384d7']; var optionLineB = { color: colors, visualMap: [{ show: false, type: 'continuous', seriesIndex: 0, min: 0, max: 600, borderWidth: 3, color: colors, }], xAxis: { type: 'category', data: ['0', '2', '4', '6', '8', '10', '12', '14', '16', '18', '20', '22'], show: true, position: { bottom: 10, show: false, }, onZero: false, axisLine: { lineStyle: { width: 0, } } }, yAxis: { type: 'value', axisLabel: { formatter: '{value} 人/平方米', fontSize: 10, }, axisLine: { lineStyle: { width: 0, } }, minInterval: 0.5, }, grid: [{ top: '40', bottom: '25', left: '70', right: '10' }], series: [{ data: [ 0, 1, 2, 3, 4, 3, 2, 3, 3.5, 2, 1, 3], type: 'line', smooth: true, markPoint: { data: [ { name: '4', coord: ['14','3'], value: '4', } ], label: { show: true, }, } }] }; myChart4.setOption(optionLineB); }
切換線性圖表數據顯示實現:
//切換線性圖表數據顯示
$(".list-b .title-box .t-a").click(function() {//點擊流量趨勢
$(".list-b .title-box .t-b").removeClass('active');//移除當前樣式
$(this).addClass('active');//給點擊添加新樣式
resizeLineA(); }) $(".list-b .title-box .t-b").click(function() {//點擊人羣密度
$(".list-b .title-box .t-a").removeClass('active'); $(this).addClass('active'); resizeLineA(1); })
更換裝圖表的盒子(div)和線性圖表信息:
function resizeLineA(n) { $(".line-cen").remove();//先移除原有的盒子
var aa = document.createElement('div');//在建立一個新盒子裝圖表
aa.id = 'ec3' aa.className = 'line-cen' $(".line-box").append(aa) if (n == 1) { lineSetA();//顯示人羣密度圖表
} else { lineSetB();//顯示流量趨勢圖表
} }
效果以下圖:
除此以外,還能夠根據實際狀況再添加相應的圖表。
2.check控制面板
開發一個控制面板,對管理者來講能夠更好的全局掌握控制商場狀況我在控制面板上加了實時視頻,全景漫遊和客流分佈,下面就這三個功能的實現過程作下介紹。
(1)客流分佈熱力圖功能,如下載入的是模擬數據,投入使用後可直接載入實際數據,根據數據體現熱力圖的狀況。
//添加熱力圖,根據json文件
function addHeatMap() { // 建立熱力圖對象
if (!heatmapInstance) heatmapInstance = esmap.ESHeatMap.create(map, { radius: 24, //熱點半徑
opacity: .5, //熱力圖透明度
max: 35, //熱力點value的最大值
maxSize: 2048, gradient: {//漸變色值,可配
0.35: "green", 0.5: "yellow", 0.7: "orange", 0.85: "red" } $.getJSON("data/003.json", function(data) { //數據載入
var datas = data.datas; var len = datas.length; exec(datas[0]["data"][0]["fnum"], datas[0]["data"][0]["points"]);//繪製熱力圖
var index = 1; timer1 = setInterval(function () { if (index > 1) index = 0; for (var el of datas[0]["data"][0]["points"]) { switch (index) { case 0: el.value = el.value - 1; break; case 1: el.value = el.value + 1; break; } } exec(datas[0]["data"][0]["fnum"], datas[0]["data"][0]["points"]); index++; }, 2000) return; }); function exec(fnum, points) {//繪製熱力圖函數
var floorLayer = map.getFloor(fnum);//獲取應用樓層
heatmapInstance.clearPoints();//清除熱力點
heatmapInstance.addPoints(points);//熱力點添加到熱力圖
//熱力圖應用到哪一樓層
floorLayer.applyHeatMap(heatmapInstance); } }
熱力圖以下:
(2)實時視頻及全景漫遊的實現:
首先建立實時視頻的攝像頭圖片標註和全景漫遊的360°圖片標註,標註實現後可在地圖上點擊相應的圖片標註從而顯示實時視頻畫面或360°全景畫面,畫面可拖拽可放大縮小。
各樓層實時視頻的攝像頭圖片標註:
//建立各樓層攝像頭標註
function showCameras() { var url = 'data/test666/model/camera1.js'; //json數據,定義攝像頭所在樓層和位置
var infos = [{ fnum: 1, cameras: [{ x: 12683472.409512023, y: 2557870.1781415385, }, { x: 12683450.258123305, y: 2557858.104209115 }, { x: 12683430.863774385, y: 2557865.8999765064 } ] }, { fnum: 2, cameras: [{ x: 12683472.409512023, y: 2557870.1781415385, }, { x: 12683450.258123305, y: 2557858.104209115 }, { x: 12683430.863774385, y: 2557865.8999765064 } ] }, { fnum: 3, cameras: [{ x: 12683472.409512023, y: 2557870.1781415385, }, { x: 12683450.258123305, y: 2557858.104209115 }, { x: 12683430.863774385, y: 2557865.8999765064 } ] }]; //建立三維模型標註 實時視頻攝像頭
var ang = 0; infos.forEach(function (info) { var floorLayer = map.getFloor(info.fnum); var layer = floorLayer.getOrCreateLayerByName("cameras", esmap.ESLayerType.MODEL3D); var _id = 1; info.cameras.forEach(function (camera) { var im = new esmap.ES3DMarker({ x: camera.x, y: camera.y, id: _id++, name: "camera", url: url, size: 44, angle: ang, height: 3, showLevel: 16, spritify: true }); ang += 30; layer.addMarker(im);//一個樓層共用一個圖層
}); layer && layer.show3D(); }); }
點擊地圖展現實時視頻或全景漫遊彈框(div)函數active():
//地圖點擊標註後 臨時建立div盒子 放全景圖或實時視頻
function active(e, type) { // type: 1.pano; 0.video
var cc = $($(".drag")[0]).clone(); var wid = $(".drag").width(); $("body").append(cc); cc[0].style.display = "block"; if (__xx < wid) { __xx = wid; } cc[0].style.left = (__xx - wid - 20).toString() + "px"; cc[0].style.top = (__yy - 25 / 2).toString() + "px"; if (!type) { cc.find('.content')[0].innerHTML = '<video class="video_" src="videos/' + e.id_ + '.mp4" autoplay loop></video>'; cc.find('.title h2')[0].innerHTML = '實時視頻'; createPopBox(); } else { cc.find('.title h2')[0].innerHTML = '全景展現';
var box = document.createElement('div');
cc.find('.content').append(box); box.className = 'psv-box'; oPano = new CreatePanorama({ container: box, panorama: 'image/pano/' + e.id + '/', six: 1 }) createPopBox(oPano); } }
展現的彈框可拖拽、大小可調整,功能實現以下函數:
/*可拖拽可放大縮小彈框*/
function createPopBox(pano) { // pano: 0.視頻,1.全景
/*-------------------------- + 獲取id, class, tagName 函數 +-------------------------- */
var get = { byId: function (id) { return typeof id === "string" ? document.getElementById(id) : id; }, byClass: function (sClass, oParent) { var aClass = []; var reClass = new RegExp("(^| )" + sClass + "( |$)"); var aElem = this.byTagName("*", oParent); for (var i = 0; i < aElem.length; i++) reClass.test(aElem[i].className) && aClass.push(aElem[i]); return aClass }, byTagName: function (elem, obj) { return (obj || document).getElementsByTagName(elem); } }; var dragMinWidth = 250; var dragMinHeight = 173; /*-------------------------- + 拖拽函數 +-------------------------- */
function drag(oDrag, handle) { var disX = dixY = 0; var oMax = get.byClass("max", oDrag)[0];//獲取最大化div的 class
var oRevert = get.byClass("revert", oDrag)[0];//獲取恢復div的 class
var oClose = get.byClass("close", oDrag)[0];//獲取關閉div的 class
handle = handle || oDrag; handle.style.cursor = "move"; handle.onmousedown = function (event) { var event = event || window.event; disX = event.clientX - oDrag.offsetLeft; disY = event.clientY - oDrag.offsetTop; document.onmousemove = function (event) { var event = event || window.event; var iL = event.clientX - disX; var iT = event.clientY - disY; var maxL = document.documentElement.clientWidth - oDrag.offsetWidth; var maxT = document.documentElement.clientHeight - oDrag.offsetHeight; iL <= 0 && (iL = 0); iT <= 0 && (iT = 0); iL >= maxL && (iL = maxL); iT >= maxT && (iT = maxT); oDrag.style.left = iL + "px"; oDrag.style.top = iT + "px"; return false }; document.onmouseup = function () { document.onmousemove = null; document.onmouseup = null; this.releaseCapture && this.releaseCapture() }; this.setCapture && this.setCapture(); return false }; //最大化按鈕
oMax.onclick = function () { if (!pano) { $(this).parents('.drag').find('.video_')[0].webkitEnterFullscreen(true); } else { fullPano = 1; oDrag.classList.add('over-auto'); var _box = $(oDrag).find('.psv-box')[0]; _box.classList.add('psv-full', 'over-auto'); var _div = document.createElement('div'); document.body.append(_div); _div.className = 'psv-full-btns'; _div.innerHTML = '<a class="full-revert" href="javascript:;" title="還原"></a>' document.onkeydown = function (e) { if (e.keyCode == 27 && fullPano == 1) { fullPano = 0; oDrag.classList.remove('over-auto'); _box.classList.remove('psv-full', 'over-auto'); _div.remove(); pano.onWindowResize(); } } $(_div).find('.full-revert').click(function () { fullPano = 0; oDrag.classList.remove('over-auto'); _box.classList.remove('psv-full', 'over-auto'); _div.remove(); pano.onWindowResize(); }) pano.onWindowResize(); } }; //還原按鈕
oRevert.onclick = function () { oDrag.style.width = dragMinWidth + "px"; oDrag.style.height = dragMinHeight + "px"; oDrag.style.left = (document.documentElement.clientWidth - oDrag.offsetWidth) / 2 + "px"; oDrag.style.top = (document.documentElement.clientHeight - oDrag.offsetHeight) / 2 + "px"; this.style.display = "none"; oMax.style.display = "block"; pano && pano.onWindowResize(); }; //關閉按鈕
oClose.onclick = function () { if (!pano) { $(this).parents('.drag').remove(); } else { oPano = null; $(this).parents('.drag').remove(); } }; //阻止冒泡
oMax.onmousedown = oClose.onmousedown = function (event) { this.onfocus = function () { this.blur(); }; (event || window.event).cancelBubble = true }; } /*-------------------------- + 改變大小函數 +-------------------------- */
function resize(oParent, handle, isLeft, isTop, lockX, lockY) { handle.onmousedown = function (event) { var event = event || window.event; var disX = event.clientX - handle.offsetLeft; var disY = event.clientY - handle.offsetTop; var iParentTop = oParent.offsetTop; var iParentLeft = oParent.offsetLeft; var iParentWidth = oParent.offsetWidth; var iParentHeight = oParent.offsetHeight; document.onmousemove = function (event) { var event = event || window.event; var iL = event.clientX - disX; var iT = event.clientY - disY; var maxW = document.documentElement.clientWidth - oParent.offsetLeft - 2; var maxH = document.documentElement.clientHeight - oParent.offsetTop - 2; var iW = isLeft ? iParentWidth - iL : handle.offsetWidth + iL; var iH = isTop ? iParentHeight - iT : handle.offsetHeight + iT; isLeft && (oParent.style.left = iParentLeft + iL + "px"); isTop && (oParent.style.top = iParentTop + iT + "px"); iW < dragMinWidth && (iW = dragMinWidth); iW > maxW && (iW = maxW); lockX || (oParent.style.width = iW + "px"); iH < dragMinHeight && (iH = dragMinHeight); iH > maxH && (iH = maxH); lockY || (oParent.style.height = iH + "px"); if ((isLeft && iW == dragMinWidth) || (isTop && iH == dragMinHeight)) document.onmousemove = null; pano && pano.onWindowResize(); return false; }; document.onmouseup = function () { document.onmousemove = null; document.onmouseup = null; }; return false; } }; function aaa() { var dom = document.getElementsByClassName("drag"); var oDrag = dom[dom.length - 1]; var oTitle = get.byClass("title", oDrag)[0]; var oL = get.byClass("resizeL", oDrag)[0]; var oT = get.byClass("resizeT", oDrag)[0]; var oR = get.byClass("resizeR", oDrag)[0]; var oB = get.byClass("resizeB", oDrag)[0]; var oLT = get.byClass("resizeLT", oDrag)[0]; var oTR = get.byClass("resizeTR", oDrag)[0]; var oBR = get.byClass("resizeBR", oDrag)[0]; var oLB = get.byClass("resizeLB", oDrag)[0]; drag(oDrag, oTitle); //拉四角
resize(oDrag, oLT, true, true, false, false); resize(oDrag, oTR, false, true, false, false); resize(oDrag, oBR, false, false, false, false); resize(oDrag, oLB, true, false, false, false); //拉四邊
resize(oDrag, oL, true, false, false, true); resize(oDrag, oT, false, true, true, false); resize(oDrag, oR, false, false, false, true); resize(oDrag, oB, false, false, true, false); oDrag.style.left = (document.documentElement.clientWidth - oDrag.offsetWidth) / 2 + "px"; oDrag.style.top = (document.documentElement.clientHeight - oDrag.offsetHeight) / 2 + "px"; } aaa(); }
功能都實現後投入使用,點擊地圖上的標註顯示相應的實時視頻,這裏我使用了ESMap的地圖點擊事件map.on(「mapClickNode」,function(){});
map.on("mapClickNode", function (e) { removeAll(); if (e.nodeType && e.nodeType == 31 && e.name && e.name == 'myMarker') {//全景
active(e, 1); } if (e.nodeType && e.nodeType == 6 && e.name && e.name == 'camera') {//視頻
active(e) } if (e.nodeType && e.nodeType == 5) {//點擊地圖商鋪顯示相應運營狀況
if (e.name) { var obj = { id: e.ID, fnum: e.FloorNum, x: e.x, y: e.y, name: e.name } searchClick(obj);// 函數以下
} } })
封裝氣泡標註函數searchClick(),顯示商鋪信息:
function searchClick(data, isAddImageMarker) { if (!data.name) return; // 添加pop
removeAll(); var floorLayer = map.getFloor(data.fnum); if (isAddImageMarker) { floorControl.changeFocusFloor(data.fnum); } if (data.name == '房間') { var dom = '<div class="pop-content"><strong>房間 ' + data.id + '</strong><p>經度:' + data.x.toFixed(3) + '</p><p>緯度:' + data.y.toFixed(3) + '</p></div>'; } else { var shopDatas = getShopMsg(data.id);//數字number
var dom = '<div class="pop-content"><strong>' + data.name + '</strong><p>人流量:' + shopDatas.msgA + '</p><p>營業額:' + shopDatas.msgB + '</p></div>' } //添加信息窗
popMarker = new esmap.ESPopMarker({ mapCoord: { //設置彈框的x軸
x: data.x, //設置彈框的y軸
y: data.y, height: 1, //控制信息窗的高度
//設置彈框位於的樓層
fnum: data.fnum }, //設置彈框的寬度
width: 200, //設置彈框的高度
height: 120, marginTop: 10, //設置彈框的內容
content: dom, // content: '<input id="pop-input" type="text"/>',
closeCallBack: function () { //信息窗點擊關閉操做
// alert('信息窗關閉了!');
}, }); $(".es-control-popmarker input").val('✖'); // 手動添加close按鈕value
}
效果圖以下:
各樓層全景漫遊的360°圖片標註:
//建立360°圖片標註到各層
function showImageMarker() { var _arr = [{ fnum: 1, node: [{ x: 12683473.823037906, y: 2557891.805802924, }, { x: 12683424.1333389, y: 2557880.7494297, } ] }, { fnum: 2, node: [{ x: 12683473.823037906, y: 2557891.805802924, }, { x: 12683424.1333389, y: 2557880.7494297, } ] }, { fnum: 3, node: [{ x: 12683473.823037906, y: 2557891.805802924, }, { x: 12683424.1333389, y: 2557880.7494297, } ] }] for (var el of _arr) { var floorLayer = map.getFloor(el.fnum); var im_layer = new esmap.ESLayer('imageMarker');//建立圖層
im_layer.name = 'mylayer';//給圖層命名
var index = 1; for (var el2 of el.node) { var im = new esmap.ESImageMarker({ x: el2.x, y: el2.y, url: 'image/360.png', id: index++, size: 50, name: 'myMarker', zoom: 2, }) im_layer.addMarker(im); floorLayer.addLayer(im_layer); } } }
圖片標註建立後,使用three.JS建立全景圖,而後綁定鼠標事件
function CreatePanorama(prop) { var camera, scene, renderer, container, mesh; var texture_placeholder, target = new THREE.Vector3();//建立3維向量
this.container = container; this.panorama = prop.panorama; this.camera = camera; this.scene = scene; this.renderer = renderer; this.mesh = mesh; function init() { container = prop.container; camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 1, 1100); scene = new THREE.Scene(); texture_placeholder = document.createElement('canvas'); texture_placeholder.width = 128; texture_placeholder.height = 128; var context = texture_placeholder.getContext('2d'); context.fillStyle = 'rgb( 200, 200, 200 )'; context.fillRect(0, 0, texture_placeholder.width, texture_placeholder.height); if (prop.six) { var materials = [ loadTexture(prop.panorama + 'r.jpg'), // right
loadTexture(prop.panorama + 'l.jpg'), // left
loadTexture(prop.panorama + 'u.jpg'), // top
loadTexture(prop.panorama + 'd.jpg'), // bottom
loadTexture(prop.panorama + 'b.jpg'), // back
loadTexture(prop.panorama + 'f.jpg') // front
]; var matss = new THREE.MultiMaterial(materials) mesh = new THREE.Mesh(new THREE.BoxGeometry(300, 300, 300, 7, 7, 7), matss); } else { var geometry = new THREE.SphereGeometry(100, 64, 64, -1.5707963267948966); var material = new THREE.MeshBasicMaterial({ map: new THREE.TextureLoader().load(prop.panorama), }) mesh = new THREE.Mesh(geometry, material); } mesh.scale.x = -1; scene.add(mesh); renderer = new THREE.WebGLRenderer({//建立一個webGL渲染器,renderer
antialias: true }) renderer.setPixelRatio(window.devicePixelRatio);//設備設置像素比
renderer.setSize(container.clientWidth, container.clientHeight);//調整輸出canvas尺寸
container.appendChild(renderer.domElement); //監聽鼠標各類事件
container.addEventListener('mousedown', onDocumentMouseDown, false); container.addEventListener('mousemove', onDocumentMouseMove, false); container.addEventListener('mouseup', onDocumentMouseUp, false); container.addEventListener('wheel', onDocumentMouseWheel, false); container.addEventListener('touchstart', onDocumentTouchStart, false); container.addEventListener('touchmove', onDocumentTouchMove, false); window.addEventListener('resize', onWindowResize, false); } }
全景漫遊完成,在地圖上點擊、拖拽、縮放功能如實時視頻同樣,效果以下圖:
3.建立一個搜索框,能夠直接鎖定目標,查看店鋪運營狀況
// 經過店名搜索地圖中店鋪 搜索框函數
function searchByName(name) { Listmodel.item = []; if (!name) return; var data = map.mapService.sourceData.floors;//獲取地圖信息
for (var ele of data) {//遍歷獲取到的信息
for (var i in ele.Rooms) { //遍歷獲取到數組裏的Rooms
var el = ele.Rooms[i]; if (el.name) { var a = el.name.indexOf(name);//查找輸入的店名是否在地圖內存在
if (a != -1) {//若是存在
var obj = { x: el.CenX, y: el.CenY, id: el._id, fnum: ele.floornum, name: el.name } Listmodel.item.push(obj);//把輸入的店名信息存入數組
} } } } }
效果以下圖:
以上就是我就商場管理者在管理過程當中所面臨的一些問題,開發的商場管理系統的一個界面,固然我只是簡單實現了一些功能,在實際開發過程可根據實際狀況定製一些功能方案,從而達到管理者高效管理的目的。ESMap-SDK提供的免費地圖開發和熱力圖、圖片標註等功能實現的支持。
Thank you for reading!