rt-sim-training-client/src/jmap/map.js
2019-07-19 13:54:23 +08:00

314 lines
8.0 KiB
JavaScript

import * as zrUtil from 'zrender/src/core/util';
import zrender from 'zrender';
import Painter from './painter';
import Options from './options';
import MouseController from './mouseController';
import deviceState from './constant/deviceState';
import { selectSkinStyle } from './config/deviceStyle';
import deviceType from './constant/deviceType';
import { parser, deviceFactory } from './utils/parser';
const renderer = 'canvas';
const devicePixelRatio = 2;
class Jmap {
constructor(opts) {
// 回调事件
this.methods = opts.methods;
// 鼠标事件
this.events = { Pan: 'pan', Zoom: 'zoom', Selected: 'selected', Contextmenu: 'contextmenu' };
// 原始数据
this.data = {};
// 皮肤参数
this.skinStyle = '';
// 皮肤风格
this.styleDict = {};
// 设备数据
this.mapDevice = {};
// 默认状态
this.defaultStateDict = this.loadDefaultState();
this.initMapInstance(opts);
}
// 初始化属性有鼠标事件 缩放等
initMapInstance(opts) {
const width = opts.dom.clientWidth;
const height = opts.dom.clientHeight;
this.$zr = zrender.init(opts.dom, Object.assign({ renderer, devicePixelRatio, width, height }, opts.config));
this.$options = new Options(Object.assign({ scaleRate: 1, offsetX: 0, offsetY: 0 }, opts.options || {})); // 缩放
this.$painter = new Painter(this);
this.$painter.updateTransform(this.$options);
this.optionsHandler = this.setOptions.bind(this);
this.$mouseController = new MouseController(this);
this.$mouseController.enable();
this.$mouseController.on(this.events.Pan, this.optionsHandler);
this.$mouseController.on(this.events.Zoom, this.optionsHandler);
}
load(data) {
// 保存皮肤类型
this.skinStyle = data.skinVO.code;
// 保存原始数据
this.data = data;
// 加载对应皮肤
this.styleDict = this.loadStyle(this.skinStyle);
// 解析地图数据
this.mapDevice = parser(data, this);
// 数据加载完成 回调
if (this.methods.dataLoaded instanceof Function) { this.methods.dataLoaded(); }
// 初次渲染视图
this.$painter.repaint(this.mapDevice);
// 视图加载完成 回调
if (this.methods.viewLoaded instanceof Function) { this.methods.viewLoaded(); }
}
loadStyle(skinStyle) {
return selectSkinStyle(skinStyle);
}
loadDefaultState() {
const defaultStateDict = {};
zrUtil.each(Object.keys(deviceState), (type) => {
defaultStateDict[type] = {};
zrUtil.each(Object.keys(deviceState[type] || {}), (state) => {
defaultStateDict[type][state] = deviceState[type][state].Default;
});
});
return defaultStateDict;
}
setDefaultState() {
const list = [];
Object.values(this.mapDevice).forEach(elem => {
const code = elem._code;
const type = elem._type;
list.push(Object.assign({ code, type }, this.defaultStateDict[type]));
});
this.update(list);
if (this.methods.stateLoaded instanceof Function) { this.methods.stateLoaded(); }
}
pullBack(payload) {
if (payload.type === 'zoom') {
const zrWidth = this.$zr.getWidth();
const zrHeight = this.$zr.getHeight();
const originX = payload.originX || zrWidth / 2;
const originY = payload.originY || zrHeight / 2;
const x = (this.$options.offsetX + originX) / this.$options.scaleRate;
const y = (this.$options.offsetY + originY) / this.$options.scaleRate;
const newScaleRate = this.$options.getScaleRate(payload.scale);
const dx = originX - (x * newScaleRate - this.$options.offsetX);
const dy = originY - (y * newScaleRate - this.$options.offsetY);
payload.dx = dx;
payload.dy = dy;
}
return payload || {};
}
setOptions(opts) {
this.$options.update(this.pullBack(opts));
this.$painter.updateTransform(this.$options);
if (this.methods.optionsUpdate instanceof Function) { this.methods.optionsUpdate(); }
if (this.$options.disabled == true) {
this.$mouseController.disable();
} else {
this.$mouseController.enable(opts);
}
}
setLevelVisible(list, show) {
this.$painter.setLevelVisible(list, show);
}
render(list) {
(list || []).forEach(elem => {
const type = elem.type;
const code = elem.code;
const oDevice = this.mapDevice[code] || deviceFactory(type, this.styleDict[type], elem);
const model = Object.assign(oDevice.model || {}, elem);
this.dataSync(model, model._dispose, !this.mapDevice[code]);
this.$painter.delete(oDevice);
if (!elem._dispose) {
const nDevice = Object.assign(oDevice, { model });
this.mapDevice[code] = nDevice;
this.$painter.add(nDevice);
}
});
if (this.methods.viewUpdate instanceof Function) { this.methods.viewUpdate(); }
}
update(list) {
(list || []).forEach(elem => {
const code = elem.code;
const oDevice = this.mapDevice[code] || {};
if (elem._dispose) {
this.$painter.delete(oDevice);
} else {
const state = Object.assign(oDevice.state || {}, elem);
const nDevice = Object.assign(oDevice, { state });
this.mapDevice[code] = nDevice;
this.$painter.update(nDevice);
}
});
if (this.methods.stateUpdate instanceof Function) { this.methods.stateUpdate(); }
}
dataSync(model, isDel, isAdd) {
const code = model.code;
const type = model.type;
let prop = null;
switch (type) {
case deviceType.Link: prop = 'linkList'; break;
case deviceType.Sction: prop = 'sectionList'; break;
case deviceType.Switch: prop = 'switchList'; break;
case deviceType.Signal: prop = 'signalList'; break;
case deviceType.Station: prop = 'stationList'; break;
case deviceType.StationStand: prop = 'stationStandList'; break;
case deviceType.StationControl: prop = 'stationControlList'; break;
case deviceType.StationCounter: prop = 'stationCounterList'; break;
case deviceType.ZcControl: prop = 'zcControlList'; break;
case deviceType.StationDelayUnlock: prop = 'stationDelayUnlockList'; break;
case deviceType.LcControl: prop = 'lcControlList'; break;
case deviceType.LimitControl: prop = 'tempSpeedLimitList'; break;
case deviceType.ImageControl: prop = 'imageControl'; break;
case deviceType.Train: prop = 'trainList'; break;
case deviceType.TrainWindow: prop = 'trainWindowList'; break;
case deviceType.Line: prop = 'lineList'; break;
case deviceType.Text: prop = 'textList'; break;
}
const list = this.data[prop];
if (list) {
if (isAdd) {
list.push(model);
}
if (isDel) {
const idex = list.findIndex(elem => { return elem.code == code; });
if (idex >= 0) {
list.splice(idex, 1);
}
}
}
}
getZr() {
return this.$zr;
}
getPainter() {
return this.$painter;
}
getEvents() {
return this.events;
}
getSkinStyle() {
return this.skinStyle;
}
getStyleDict() {
return this.styleDict;
}
getDefaultStateDict() {
return this.defaultStateDict;
}
getMapDevice() {
return this.mapDevice;
}
getDeviceByCode(code) {
return this.mapDevice[code];
}
resize(opt) {
this.$zr.resize(opt);
this.$painter.updateZrSize({width: this.$zr.getWidth(), height: this.$zr.getHeight()});
}
refresh() {
this.$painter.refresh();
}
clear() {
this.$painter.clear();
}
dispose() {
this.off(this.events.Pan, this.optionsHandler);
this.off(this.events.Zoom, this.optionsHandler);
this.skinStyle = '';
this.styleDict = {};
this.mapDevice = {};
this.$mouseController.dispose();
this.$zr && zrender.dispose(this.$zr);
this.$painter.dispose();
}
on(eventname, cb, context) {
const idx = Object.values(this.events).indexOf(eventname);
if (idx >= 0) {
switch (eventname) {
case this.events.Selected: {
this.$mouseController.on(this.events.Selected, cb, context);
break;
}
case this.events.Contextmenu: {
this.$mouseController.on(this.events.Contextmenu, cb, context);
break;
}
}
}
}
off(eventname, cb) {
const idx = Object.values(this.events).indexOf(eventname);
if (idx >= 0) {
switch (eventname) {
case this.events.Selected: {
this.$mouseController.off(this.events.Selected, cb);
break;
}
case this.events.Contextmenu: {
this.$mouseController.off(this.events.Contextmenu, cb);
break;
}
}
}
}
}
export default Jmap;