import Group from 'zrender/src/container/Group'; import Text from 'zrender/src/graphic/Text'; import Rect from 'zrender/src/graphic/shape/Rect'; import JTriangle from '../../utils/JTriangle'; import ESwName from './ESwName.js'; import ESwLocal from './ESwLocal.js'; import ESwLnversion from './ESwLnversion'; import ELockRect from './ELockRect'; import ELockArc from './ELockArc'; import EMouse from './EMouse'; import EHighlight from '../element/EHighlight'; import ETriangle from './ETriangle'; import store from '@/store/index'; import Vue from 'vue'; export default class Switch extends Group { constructor(model, style) { super(); this._code = model.code; this._type = model._type; this.model = model; this.style = style; this.zlevel = model.zlevel; this.z = 6; this.isShowShape = true; this.triangle = new JTriangle(model.intersection, model.skew); this.create(); this.createLockRect(); // 创建单锁矩形框显示 this.createMouseEvent(); this.setState(model); this.checkIsDrawMap(); } createMouseEvent() { // 鼠标事件 if (this.style.Switch.mouseOverStyle) { this.mouseEvent = new EMouse(this); this.add(this.mouseEvent); this.on('mouseout', (e) => { this.mouseEvent.mouseout(e); }); this.on('mouseover', (e) => { this.mouseEvent.mouseover(e); }); } } create() { const model = this.model; const style = this.style; const swPadding = style.Switch.core.length + style.Section.line.width / 2; const directx = this.triangle.drictx; const directy = this.triangle.dricty; const switchWidth1 = style.Section.line.width / 2; let directxA = 1; const sectionAModel = Vue.prototype.$jlmap.mapDevice[model.sectionACode]; const sectionBModel = Vue.prototype.$jlmap.mapDevice[model.sectionBCode]; let sectionATriangle = new JTriangle(sectionAModel.points[0], sectionAModel.points[1]); let sectionBTriangle = new JTriangle(sectionBModel.points[0], sectionBModel.points[1]); const sectionAPoint = { x: model.intersection.x, y: model.intersection.y }; if (sectionAModel.points[0].x == model.intersection.x && sectionAModel.points[0].y == model.intersection.y) { sectionATriangle = new JTriangle(sectionAModel.points[0], sectionAModel.points[1]); directxA = 1; } if (sectionAModel.points[sectionAModel.points.length - 1].x == model.intersection.x && sectionAModel.points[sectionAModel.points.length - 1].y == model.intersection.y) { sectionATriangle = new JTriangle(sectionAModel.points[sectionAModel.points.length - 2], sectionAModel.points[sectionAModel.points.length - 1]); directxA = -1; } if (sectionBModel.points[0].x == model.intersection.x && sectionBModel.points[0].y == model.intersection.y) { sectionBTriangle = new JTriangle(sectionBModel.points[0], sectionBModel.points[1]); } if (sectionBModel.points[sectionBModel.points.length - 1].x == model.intersection.x && sectionBModel.points[sectionBModel.points.length - 1].y == model.intersection.y) { sectionBTriangle = new JTriangle(sectionBModel.points[sectionBModel.points.length - 2], sectionBModel.points[sectionBModel.points.length - 1]); } const drictyyA = sectionATriangle.dricty; const point1 = [model.intersection.x + directx * this.triangle.getCotRate() * swPadding, model.intersection.y + directy * swPadding]; const point2 = [model.intersection.x, model.intersection.y]; const point3 = [sectionAPoint.x + directxA * (switchWidth1 * sectionATriangle.getCosRate()), sectionAPoint.y + drictyyA * switchWidth1 * sectionATriangle.getSinRate()]; this.shapeModelA = new ESwLocal({ // 形状 A 层级最高 反位折线覆盖 zlevel: this.zlevel, z: this.z, style: style, shelterPoints: [point1, point2, point3], cursor: 'pointer', triangle: this.triangle, onmouseover: () => { this.name.getArrowText().show(); }, onmouseout: () => { this.name.getArrowText().hide(); } }); const relocShelterLength = 15; const rpoint1 = [sectionAPoint.x - directxA * (relocShelterLength * sectionBTriangle.getCosRate()), sectionAPoint.y - drictyyA * relocShelterLength * sectionBTriangle.getSinRate()]; const rpoint2 = [sectionAPoint.x, sectionAPoint.y]; const rpoint3 = [sectionAPoint.x + directxA * (switchWidth1 * sectionATriangle.getCosRate()), sectionAPoint.y + drictyyA * switchWidth1 * sectionATriangle.getSinRate()]; this.shapeModelB = new ESwLnversion({ // 形状 B 层级居中 定位折线覆盖 zlevel: this.zlevel, z: this.z, style: style, shelterPoints: [rpoint1, rpoint2, rpoint3], cursor: 'pointer', onmouseover: () => { this.name.getArrowText().show(); }, onmouseout: () => { this.name.getArrowText().hide(); } }); if (this.style.Switch.text.lossRect) { // 道岔失表显示红色矩形框 const lossRect = this.shapeModelA.getLocal().getBoundingRect(); this.lossShow = new Rect({ zlevel: this.zlevel, z: this.z + 1, shape: { x: lossRect.x - 5, y: lossRect.y - 5, width: lossRect.width + 10, height: lossRect.height + 10 }, style: { fill: 'rgba(0, 0, 0, 1)', lineDash: [3, 3], stroke: '#F00', lineWidth: 2 } }); this.add(this.lossShow); this.lossShow.hide(); } const Tspoint1 = [model.intersection.x + directx * this.triangle.getCotRate() * swPadding, model.intersection.y + directy * swPadding]; const Tspoint2 = [model.intersection.x, model.intersection.y]; this.shapeModelC = new ETriangle({ // 形状 C 层级最低 应用佛山反位覆盖 zlevel: this.zlevel, z: this.z, style: style, sectionPoints: [Tspoint1, Tspoint2], cursor: 'pointer', onmouseover: () => { this.name.getArrowText().show(); }, onmouseout: () => { this.name.getArrowText().hide(); } }); const arrowTextX = model.intersection.x + 10; const arrowTextY = model.intersection.y + 15; const nameTextX = model.namePosition.x + model.intersection.x + directx * (style.Section.line.width * 3 + style.Switch.text.offset.x) * this.triangle.getCotRate(); const nameTextY = model.namePosition.y + model.intersection.y + style.Switch.text.offset.y * (style.Switch.text.position || directy); this.name = new ESwName({ // 道岔名称 zlevel: this.zlevel, z: this.z, style: style, arrowTextX: arrowTextX, arrowTextY: arrowTextY, nameTextX: nameTextX, nameTextY: nameTextY, sectionName: model.sectionName, name: model.name, nameShow: style.Switch.text.show, triangle: this.triangle }); this.enabledName = new Text({ // 道岔使能 E 西安二号线独有 zlevel: this.zlevel, z: this.z + 6, _subType: 'enabled', // 标识 style: { x: nameTextX, // y: nameTextY + directy * 20, y: nameTextY + 20, fontSize: 12, text: 'E', textAlign: 'center', textVerticalAlign: 'middle', textFill: 'yellow' } }); this.add(this.shapeModelA); this.add(this.shapeModelB); this.add(this.shapeModelC); this.add(this.name); this.add(this.enabledName); style.Switch.text.show && model.nameShow ? this.name.show() : this.name.hide(); } createLockRect() { let offsetX = this.model.locateType == '01' ? 3 : 0; let offsetY = 0; if (this.style.Switch.rectLock.offset) { const directx = this.triangle.drictx; const directy = this.triangle.dricty; offsetX = directx * this.style.Switch.rectLock.offset.x; offsetY = directy * this.style.Switch.rectLock.offset.y; } this.lockRect = new ELockRect({ // 单锁矩形框 zlevel: this.zlevel, z: this.z + 6, x: this.model.intersection.x - this.style.Switch.rectLock.rectWidth / 2 + offsetX, y: this.model.intersection.y - this.style.Switch.rectLock.rectWidth / 2 + offsetY, width: this.style.Switch.rectLock.rectWidth, lineWidth: 1.8, stroke: this.style.Switch.rectLock.rectBorderColor, fill: this.style.transparentColor }); this.add(this.lockRect); this.lockRect.hide(); if (this.style.Switch.arcBlcok || this.style.Switch.interlocking) { this.lockArc = new ELockArc({ // 单锁圆形 只有宁波线路使用 国赛线 zlevel: this.zlevel, z: this.z + 6, x: this.model.intersection.x, y: this.model.intersection.y, shapeR: this.style.Switch.arcBlcok.shapeR, lineWidth: 1.2, stroke: this.style.Switch.arcBlcok.arcBorderColor, fill: this.style.transparentColor }); this.add(this.lockArc); this.lockArc.hide(); } } setCiConfirm() { this.enabledName && this.enabledName.show(); this.enabledName.animateStyle(true) .when(0, { textFill: this.style.backgroundColor }) .when(1000, { textFill: 'yellow' }) .when(2000, { textFill: this.style.backgroundColor }) .start(); } /** 名称动画*/ nameTextAnimation() { this.name.getNameText().animateStyle(true) .when(0, { textFill: this.style.backgroundColor }) .when(1000, { textFill: this.style.Switch.text.lossColor }) .when(2000, { textFill: this.style.backgroundColor }) .start(); this.name.getTextRect().animateStyle(true) .when(0, { textFill: this.style.backgroundColor }) .when(1000, { textFill: this.style.Switch.text.borderColor }) .when(2000, { textFill: this.style.backgroundColor }) .start(); } /** 设置道岔文字颜色*/ setTextColor(color) { this.name.getNameText().setStyle({ textFill: color }); } /** 设置道岔背景颜色*/ setTextStyle(style) { this.name.getNameText().setStyle(style); } /** 设置道岔文字边框颜色 (道岔封锁) */ setHasTextBorder(width) { this.name.getTextRect().setStyle({ lineWidth: width }); } /** 恢复状态*/ recover() { this.lockRect.hide(); // 矩形包围框 this.lockArc.hide(); // 圆形单锁框 this.name.getNameText().stopAnimation(false); this.shapeModelC.hide(); // 形状 C this.shapeModelA.hide(); // 形状 A this.shapeModelB.hide(); // 形状 B this.setHasTextBorder(0); this.shapeModelC.attr({ z: this.z + 3 }); this.enabledName && this.enabledName.hide(); // 使能隐藏 this.lossShow && this.lossShow.hide(); // 道岔失去矩形 this.lossShow && this.lossShow.stopAnimation(false); } /** 定位*/ setLocationAction() { if (this.style.Switch.core.splice) { // 哈尔滨线路 this.shapeModelB.hide(); this.shapeModelC.hide(); } else { this.shapeModelB.show(); this.shapeModelB.setColor(this.style.Section.line.spareColor); this.shapeModelC.show(); this.shapeModelC.setColor(this.style.backgroundColor); } if (this.style.Switch.core.graphShow) { // 佛山线路显示 this.shapeModelB.show(); this.shapeModelB.setColor('#00FF00'); this.shapeModelC.show(); this.shapeModelC.setColor(this.style.backgroundColor); } this.setTextColor(this.style.Switch.text.locateColor); } /** 反位*/ setInversionAction() { this.setTextColor(this.style.Switch.text.inversionColor); if (this.style.Switch.core.splice) { // this.shapeModelA.show(); // this.shapeModelA.setColor(this.style.Section.line.spareColor); } else { this.shapeModelB.show(); } this.shapeModelA.show(); this.shapeModelA.setColor(this.style.Section.line.spareColor); if (this.style.Switch.core.graphShow) { // 佛山线路显示 this.shapeModelC.show(); this.shapeModelC.setColor('#FFFF00'); this.shapeModelC.attr({ z: this.z + 6 }); } } /** 失去*/ setLossAction() { this.shapeModelA.show(); this.shapeModelB.show(); this.shapeModelC.show(); this.shapeModelC.setColor(this.style.backgroundColor); this.setTextColor(this.style.Switch.text.lossColor); this.style.Switch.text.faultFlashing && this.nameTextAnimation(); this.lossShow && this.lossShow.show(); // 西安线路专有 this.lossShow && this.lossShow.animateStyle(true) .when(0, { stroke: this.style.backgroundColor }) .when(500, { stroke: '#F00' }) .when(1000, { stroke: this.style.backgroundColor }) .start(); } setSwitchFault(split, normalPosition, reversePosition) { if (this.style.Switch.jointImg.faultStatus && split && !reversePosition && !normalPosition ) { // 宁波线失表状态 this.setForkAction(); // 道岔挤岔 } else { if (this.model.switchFaultCode && split) { const switchFault = store.getters['map/getDeviceByCode'](this.model.switchFaultCode); switchFault.instance.setControlColor('#F00', true); } else if (this.model.switchFaultCode && !split) { const switchFault = store.getters['map/getDeviceByCode'](this.model.switchFaultCode); switchFault.instance.setControlColor(this.style.backgroundColor, false); } // stopAnimation this.shapeModelB.stopAnimation(false); this.shapeModelC.stopAnimation(false); this.shapeModelA.stopAnimation(false); } } /** 挤叉*/ setForkAction() { if (this.style.Switch.jointImg.fork) { this.recover(); this.shapeModelB.show(); this.shapeModelB.animateStyle(item => { item.animateStyle(true) .when(0, { stroke: this.style.backgroundColor }) .when(1000, { stroke: 'red' }) .when(2000, { stroke: this.style.backgroundColor }) .start(); }); this.shapeModelC.show(); // 宁波线路挤叉特殊显示 this.shapeModelC.animateStyle(item => { item.animateStyle(true) .when(0, { stroke: this.style.backgroundColor }) .when(1000, { stroke: 'red' }) .when(2000, { stroke: this.style.backgroundColor }) .start(); }); this.shapeModelA.show(); this.shapeModelA.animateStyle(item => { item.animateStyle(true) .when(0, { stroke: this.style.backgroundColor }) .when(1000, { stroke: 'red' }) .when(2000, { stroke: this.style.backgroundColor }) .start(); }); this.setTextColor('red'); } } /** 单锁*/ setMonolock(normalPosition, reversePosition) { if (this.style.Switch.rectLock.monolock) { // 判断单锁矩形是否显示 this.lockRect.show(); if (this.style.Switch.rectLock.rectBorderFillColor) { // 西安二号线 专用显示 this.lockRect.setStyle({ stroke: this.style.Switch.rectLock.rectBorderColor, fill: this.style.Switch.rectLock.rectBorderFillColor }); } } if (this.style.Switch.text.monolock) { // 单锁显示名称包围框 this.setHasTextBorder(1); } if (this.style.Switch.arcBlcok.show) { // 圆形单锁是否显示 this.lockArc.show(); if (normalPosition) { this.lockArc.setStyle({ stroke: this.style.Switch.arcBlcok.locationColor }); } else if (reversePosition) { this.lockArc.setStyle({ stroke: this.style.Switch.arcBlcok.inversionColor }); } } this.model.normalPosition && this.setTextColor(this.style.Switch.text.monolockLocationColor); // 定位 设置道岔名称颜色 this.model.reversePosition && this.setTextColor(this.style.Switch.text.monolockInversionColor); // 反位 设置道岔名称颜色 } /** 封锁 */ block() { if (this.style.Switch.jointImg.block) { // 宁波专用封锁显示 this.shapeModelB.show(); this.shapeModelB.animateStyle(item => { item.animateStyle(true) .when(0, { stroke: this.style.backgroundColor }) .when(1000, { stroke: this.style.Switch.jointImg.flashingColors }) .when(2000, { stroke: this.style.backgroundColor }) .start(); }); this.shapeModelC.show(); this.shapeModelC.animateStyle(item => { item.animateStyle(true) .when(0, { stroke: this.style.backgroundColor }) .when(1000, { stroke: this.style.Switch.jointImg.flashingColors }) .when(2000, { stroke: this.style.backgroundColor }) .start(); }); this.shapeModelA.show(); this.shapeModelA.animateStyle(item => { item.animateStyle(true) .when(0, { stroke: this.style.backgroundColor }) .when(1000, { stroke: this.style.Switch.jointImg.flashingColors }) .when(2000, { stroke: this.style.backgroundColor }) .start(); }); } if (this.style.Switch.text.block) { this.setHasTextBorder(1); } if (this.style.Switch.text.blockText) { this.setTextColor(this.style.Switch.text.blockText); } if (this.style.Switch.jointImg.trapezoidBlock && this.model.reversePosition) { // 范围且封锁时显示 this.shapeModelC.show(); this.shapeModelC.getSection().setStyle('fill', '#000080'); } if (this.style.Switch.rectLock.block) { this.lockRect.show(); this.lockRect.setStyle({ stroke: this.style.Switch.rectLock.blockColor }); if (this.style.Switch.rectLock.blockFillColor) { // 西安二号线 专用显示 this.lockRect.setStyle({ stroke: this.style.Switch.rectLock.blockColor, fill: this.style.Switch.rectLock.blockFillColor }); } } } blockMonolock() { if (this.style.Switch.rectLock.block && this.style.Switch.rectLock.monolock) { if (this.style.Switch.rectLock.blockFillColor && this.style.Switch.rectLock.rectBorderFillColor) { this.lockRect.show(); this.lockRect.setStyle({ stroke: 'rgba(0,0,0,0)', fill: this.style.Switch.rectLock.blockMonolockFillColor }); } } } // 联锁预留道岔 interlockingReserved() { if (this.style.Switch.interlocking) { this.lockArc.show(); this.lockArc.attr({ style: { lineWidth: 0.5, stroke: this.style.Switch.interlocking.strokeColor, fill: this.style.Switch.interlocking.fillColor }, shape: { r: this.style.Section.line.width / 2 + 0.3 } }); this.lockArc.setStyle({ }); } } // 处理岔芯颜色 setSectionState(state) { const sectionC = store.getters['map/getDeviceByCode'](state.sectionCCode); if (sectionC && state.reversePosition) { this.setSwitchModelStatus(this.shapeModelA, sectionC); } const sectionA = store.getters['map/getDeviceByCode'](state.sectionACode); if (sectionA && state.normalPosition && !this.style.Switch.core.graphShow) { this.setSwitchModelStatus(this.shapeModelB, sectionA); } } // 处理道岔元素状态 setSwitchModelStatus(section, sectionModel) { // 空闲 section.setStyle({'stroke': this.style.Section.line.spareColor}); section.show(); // 道岔保护区段锁闭 if (sectionModel.overlapLock) { section.setStyle({'stroke': this.style.Section.line.protectiveLockColor}); section.show(); } // 空闲锁闭或者叫进路锁闭 if (sectionModel.routeLock) { section.setStyle({'stroke': this.style.Section.line.routeLockColor}); section.show(); } // 非CBTC车占用 if (sectionModel.nctOccupied) { section.setStyle({'stroke': this.style.Section.line.unCommunicationOccupiedColor}); section.show(); } // CBTC车占用 if (sectionModel.ctOccupied) { section.setStyle({'stroke': this.style.Section.line.communicationOccupiedColor}); section.show(); } if (sectionModel.cutOff) { section.hide(); } } setAshShow() { this.shapeModelA.setColor('#7F7F7F'); this.shapeModelB.setColor('#7F7F7F'); this.shapeModelC.setColor('#7F7F7F'); this.name.getNameText().setStyle({textFill: '#7F7F7F'}); } setState(model) { if (!this.isShowShape) return; this.recover(); this.setSwitchFault(model.split, model.normalPosition, model.reversePosition); if (model.normalPosition) { this.setLocationAction(model); /** 定位*/ } else if (model.reversePosition) { this.setInversionAction(model); /** 反位*/ } else { this.setLossAction(); // 失去 } model.isCiConfirm && this.setCiConfirm(); // 道岔使能显示 model.singleLock && this.setMonolock(model.normalPosition, model.reversePosition); // 道岔单锁 model.blockade && this.block(); // 道岔封锁 model.singleLock && model.blockade && this.blockMonolock(); // 单锁&锁闭状态 const path = window.location.href; if (!path.includes('/map/draw')) { this.setSectionState(this.model); // 处理元素颜色 } // this.interlockingReserved(); // 联锁预留道岔 if (this.style.Switch.sectionAction.flag) { // 哈尔滨线路处理道岔相关区段颜色 const switchModel = Vue.prototype.$jlmap.mapDevice[model.code]; if (switchModel.normalPosition != 0) { // 定位情况 const sectionC = Vue.prototype.$jlmap.mapDevice[switchModel.sectionCCode]; sectionC && sectionC.instance && sectionC.instance.setState(sectionC); } else if (switchModel.normalPosition == 0) { // 反位情况 const sectionB = Vue.prototype.$jlmap.mapDevice[switchModel.sectionBCode]; sectionB && sectionB.instance && sectionB.instance.setState(sectionB); } } model.noStatus && this.setAshShow(); } getBoundingRect() { return this.name.getBoundingRect(); } getShapeTipPoint(opts) { let rect; let text; switch (opts.subDeviceType) { case 'enabled': rect = this.enabledName.getBoundingRect(); break; default: text = this.name.getNameText(); if (text) { rect = text.getBoundingRect(); } break; } if (rect) { return { x: rect.x + rect.width / 2, y: rect.y }; } return null; } drawSelected(selected) { this.highlight && this.highlight.drawSelected(selected); } checkIsDrawMap() { const path = window.location.href; if (path.includes('/map/draw')) { this.highlight = new EHighlight(this); this.add(this.highlight); this.on('mouseout', () => { this.highlight.mouseout(); }); this.on('mouseover', () => { this.highlight.mouseover(); }); } } setShowMode() {} setShowStation(stationCode) { if (!stationCode || this.model.stationCode === stationCode) { this.eachChild(item => { item.show(); }); if (this.name) { this.style.Switch.text.show && this.model.nameShow ? this.name.show() : this.name.hide(); } this.isShowShape = true; this.setState(this.model); } else { this.eachChild(item => { item.hide(); }); this.isShowShape = false; } } }