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.optionsHandler = this.setOptions.bind(this); 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.updateZoomTransform(this.$options); 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 = this.$options.zoomOnMouseWheel ? payload.originX : zrWidth / 2; const originY = this.$options.zoomOnMouseWheel ? 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(zoom) { this.$options.update(this.pullBack(zoom)); this.$painter.updateZoomTransform(this.$options); if (this.methods.optionsUpdate instanceof Function) { this.methods.optionsUpdate(); } } 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]; } 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;