Vue.component('map-replay-canvas', {
|
template: `
|
<div class="dl-replay-map-shell" style="display: flex; flex-direction: column; width: 100%; height: 100%; min-height: 0;">
|
<div class="dl-replay-floor-bar" v-if="floorList.length > 1 && floorBarVisible">
|
<button
|
v-for="floor in floorList"
|
:key="'replay-floor-' + floor"
|
type="button"
|
class="dl-floor-btn"
|
:class="{ 'is-active': activeFloor === floor }"
|
@click="handleFloorClick(floor)"
|
>{{ floor }}F</button>
|
</div>
|
<div class="dl-replay-map-stage" style="flex: 1; min-height: 0; position: relative;">
|
<map-canvas
|
ref="mapCanvas"
|
:lev="activeFloor"
|
:lev-list="floorList"
|
:viewport-padding="viewportPadding"
|
:hud-padding="hudPadding"
|
:realtime-enabled="false"
|
:tool-panel-enabled="true"
|
:cycle-capacity-visible="false"
|
:highlight-on-param-change="false"
|
:station-task-range="stationTaskRange"
|
@switch-lev="handleToolFloorSwitch"
|
@crn-click="emitDeviceClick('Crn', $event, null)"
|
@dual-crn-click="emitDeviceClick('DualCrn', $event, null)"
|
@rgv-click="emitDeviceClick('Rgv', $event, null)"
|
@station-click="emitDeviceClick('Devp', null, $event)"
|
></map-canvas>
|
</div>
|
</div>
|
`,
|
props: ['frame', 'lev', 'stationTaskRange', 'viewportPadding', 'hudPadding'],
|
data: function () {
|
return {
|
floorList: [],
|
activeFloor: null,
|
lastAppliedFrameKey: '',
|
pendingFrameValue: null,
|
applyFrameRaf: null,
|
floorSyncTimers: [],
|
floorBarVisible: false,
|
lastLoadedFloorForLayout: null
|
};
|
},
|
watch: {
|
frame: function (value) {
|
this.scheduleApplyFrame(value);
|
},
|
lev: function (value) {
|
if (value == null || value === '') {
|
return;
|
}
|
this.activeFloor = Number(value);
|
this.scheduleFloorFrameSync();
|
}
|
},
|
mounted: function () {
|
this.loadFloorList();
|
this.$nextTick(() => {
|
this.scheduleMapCanvasLayoutSync();
|
});
|
},
|
beforeDestroy: function () {
|
if (this.applyFrameRaf) {
|
cancelAnimationFrame(this.applyFrameRaf);
|
this.applyFrameRaf = null;
|
}
|
this.clearFloorSyncTimers();
|
},
|
methods: {
|
loadFloorList: function () {
|
var self = this;
|
$.ajax({
|
url: baseUrl + '/basMap/getLevList',
|
headers: { token: localStorage.getItem('token') },
|
method: 'GET',
|
success: function (res) {
|
var floors = res && res.code === 200 ? (res.data || []) : [];
|
self.floorList = floors.map(function (item) { return Number(item); }).filter(function (item) { return !isNaN(item); });
|
self.activeFloor = self.lev != null && self.lev !== '' ? Number(self.lev) : (self.floorList[0] || 1);
|
self.$emit('lev-list-change', self.floorList.slice());
|
self.scheduleMapCanvasLayoutSync();
|
self.scheduleFloorFrameSync();
|
}
|
});
|
},
|
scheduleMapCanvasLayoutSync: function () {
|
var syncSteps = [0, 80, 220, 420];
|
for (var i = 0; i < syncSteps.length; i++) {
|
var delay = syncSteps[i];
|
var timer = setTimeout(() => {
|
this.syncMapCanvasLayout();
|
}, delay);
|
this.floorSyncTimers.push(timer);
|
}
|
},
|
syncMapCanvasLayout: function () {
|
if (!this.$refs.mapCanvas) {
|
return;
|
}
|
if (typeof this.$refs.mapCanvas.resizeToContainer === 'function') {
|
this.$refs.mapCanvas.resizeToContainer();
|
}
|
var currentFloor = Number(this.activeFloor || this.$refs.mapCanvas.currentLev || 0);
|
if (currentFloor > 0
|
&& this.lastLoadedFloorForLayout !== currentFloor
|
&& typeof this.$refs.mapCanvas.getMap === 'function') {
|
this.lastLoadedFloorForLayout = currentFloor;
|
this.$refs.mapCanvas.getMap();
|
}
|
},
|
scheduleApplyFrame: function (value) {
|
this.pendingFrameValue = value;
|
if (this.applyFrameRaf) {
|
return;
|
}
|
this.applyFrameRaf = requestAnimationFrame(() => {
|
this.flushPendingFrame();
|
});
|
},
|
flushPendingFrame: function () {
|
this.applyFrameRaf = null;
|
this.applyFrame(this.pendingFrameValue);
|
},
|
applyFrame: function (value) {
|
if (!this.$refs.mapCanvas || !value) {
|
return;
|
}
|
var frameKey = [value.sampleSeq || '', value.timestamp || ''].join('|');
|
if (frameKey && frameKey === this.lastAppliedFrameKey) {
|
return;
|
}
|
this.lastAppliedFrameKey = frameKey;
|
this.$refs.mapCanvas.applyReplayFrame(value);
|
},
|
handleFloorClick: function (floor) {
|
this.activeFloor = Number(floor);
|
this.lastLoadedFloorForLayout = null;
|
this.$emit('floor-change', this.activeFloor);
|
this.scheduleFloorFrameSync();
|
},
|
handleToolFloorSwitch: function (floor) {
|
this.handleFloorClick(floor);
|
},
|
clearFloorSyncTimers: function () {
|
while (this.floorSyncTimers.length) {
|
clearTimeout(this.floorSyncTimers.pop());
|
}
|
},
|
scheduleFloorFrameSync: function () {
|
this.clearFloorSyncTimers();
|
var syncSteps = [80, 220, 420];
|
for (var i = 0; i < syncSteps.length; i++) {
|
var timer = setTimeout(() => {
|
this.syncMapCanvasLayout();
|
this.applyFrame(this.frame);
|
}, syncSteps[i]);
|
this.floorSyncTimers.push(timer);
|
}
|
},
|
emitDeviceClick: function (type, deviceNo, stationId) {
|
var target = window.MapCanvasShared && typeof window.MapCanvasShared.buildReplayTarget === 'function'
|
? window.MapCanvasShared.buildReplayTarget(type, deviceNo, stationId)
|
: { type: type, deviceNo: deviceNo, stationId: stationId };
|
this.$emit('target-click', target);
|
}
|
}
|
});
|