diff --git a/src/iscs_new/config/defaultStyle.js b/src/iscs_new/config/defaultStyle.js new file mode 100644 index 000000000..c9ecac6f6 --- /dev/null +++ b/src/iscs_new/config/defaultStyle.js @@ -0,0 +1,40 @@ +import mask from '@/assets/map/tpsq/image-mask.jpg'; + +export default class defaultStyle { + constructor() { + /** 透明填充 颜色*/ + this.transparentColor = 'rgba(0,0,0,0)'; + + /** 默认背景 颜色*/ + this.backgroundColor = '#000000'; + + /** 默认字体 族类*/ + this.fontFamily = '黑体,Times New Roman'; + + /** 默认字体 大小*/ + this.fontSize = 12; + + /** 图片高亮遮罩*/ + this.maskHover2Image = mask; + + /** 文字高亮遮罩*/ + this.textHover2Color = '#1477e5'; + + /** 管道高亮遮罩*/ + this.pipeHover2Color = '#ffff00'; // '#ff5f5f' + + this.pipeHover2ColorDef = '#fff'; + + /** 图形高亮遮罩*/ + this.graphHover2Color = '#62ff00'; + + /** 测量高亮遮罩*/ + this.measureHover2Color = '#6000ff'; + + /** 选中透明度*/ + this.maskOpacity = 0.8; + + /** 提亮度*/ + this.liftLevel = 0.5; + } +} diff --git a/src/iscs_new/config/graphStyle.js b/src/iscs_new/config/graphStyle.js new file mode 100644 index 000000000..d0dece440 --- /dev/null +++ b/src/iscs_new/config/graphStyle.js @@ -0,0 +1,117 @@ +import defaultStyle from './defaultStyle'; +import graphType from '../constant/graphType'; + +class SkinCode extends defaultStyle { + constructor() { + super(); + + this[graphType.Text] = { + text: { + fontWeight: 'normal' + } + }; + + this[graphType.Table] = { + header: { + height: 40, + fontWeight: 'bold', + fontSize: 18 + } + }; + + this[graphType.Resource] = { + warning: { + r: 5, + fill: 'red', + offset: { x: 0, y: 0} + }, + hover: { + lineWidth: 1 + } + }; + + this[graphType.LinePipe] = { + line: { + lineWidth: 2 + }, + arrow: { + lineWidth: 1 + } + }; + + this[graphType.Measure] = { + }; + + this[graphType.Warning] = { + circle: { + lineWidth: 0, + stroke: '#eee' + }, + text: { + fontWeight: 'bold', + fontSize: 16, + textFill: 'red' + } + }; + + this[graphType.Switching] = { + text: { + fontWeight: 'normal' + }, + button: { + lineWidth: 0.5, + stroke: '#666', + fill: '#d1d1d1' + } + }; + + this[graphType.Popup] = { + text: { + fontWeight: 'normal' + }, + button: { + lineWidth: 0.5, + stroke: '#666', + fill: '#d1d1d1' + } + }; + + this[graphType.ProgramControl] = { + button: { + lineWidth: 3, + stroke: '#fff', + width: 72, + height: 24 + }, + line: { + lineWidth: 1, + stroke: '#fff' + }, + block: { + lineWidth: 1, + stroke: '#888', + fill: '#d1d1d1', + shadowColor: '#000', + shadowOffsetX: 1, + shadowOffsetY: 1 + }, + indicate: { + fill: '#000' + } + }; + + this[graphType.Pid] = { + text: { + fontWeight: 'normal' + }, + button: { + lineWidth: 0.5, + stroke: '#666', + fill: '#d1d1d1' + } + }; + + } +} + +export default new SkinCode(); diff --git a/src/iscs_new/config/panelStyle.js b/src/iscs_new/config/panelStyle.js new file mode 100644 index 000000000..d61977f57 --- /dev/null +++ b/src/iscs_new/config/panelStyle.js @@ -0,0 +1,117 @@ +import defaultStyle from './defaultStyle'; +import panelType from '../constant/panelType'; + +class SkinCode extends defaultStyle { + constructor() { + super(); + + this[panelType.Text] = { + text: { + fontWeight: 'normal' + } + }; + + this[panelType.Table] = { + header: { + height: 40, + fontWeight: 'bold', + fontSize: 18 + } + }; + + this[panelType.Resource] = { + warning: { + r: 5, + fill: 'red', + offset: { x: 0, y: 0} + }, + hover: { + lineWidth: 1 + } + }; + + this[panelType.LinePipe] = { + line: { + lineWidth: 2 + }, + arrow: { + lineWidth: 1 + } + }; + + this[panelType.Measure] = { + }; + + this[panelType.Warning] = { + circle: { + lineWidth: 0, + stroke: '#eee' + }, + text: { + fontWeight: 'bold', + fontSize: 16, + textFill: 'red' + } + }; + + this[panelType.Switching] = { + text: { + fontWeight: 'normal' + }, + button: { + lineWidth: 0.5, + stroke: '#666', + fill: '#d1d1d1' + } + }; + + this[panelType.Popup] = { + text: { + fontWeight: 'normal' + }, + button: { + lineWidth: 0.5, + stroke: '#666', + fill: '#d1d1d1' + } + }; + + this[panelType.ProgramControl] = { + button: { + lineWidth: 3, + stroke: '#fff', + width: 72, + height: 24 + }, + line: { + lineWidth: 1, + stroke: '#fff' + }, + block: { + lineWidth: 1, + stroke: '#888', + fill: '#d1d1d1', + shadowColor: '#000', + shadowOffsetX: 1, + shadowOffsetY: 1 + }, + indicate: { + fill: '#000' + } + }; + + this[panelType.Pid] = { + text: { + fontWeight: 'normal' + }, + button: { + lineWidth: 0.5, + stroke: '#666', + fill: '#d1d1d1' + } + }; + + } +} + +export default new SkinCode(); diff --git a/src/iscs_new/config/resourceStyle.js b/src/iscs_new/config/resourceStyle.js new file mode 100644 index 000000000..d082ffa2b --- /dev/null +++ b/src/iscs_new/config/resourceStyle.js @@ -0,0 +1,39 @@ +import defaultStyle from './defaultStyle'; +import STLBg from '@/assets/map/stl_bg.png'; +import STLPilotLamp from '@/assets/map/stl_pilot_lamp.png'; +import STLButton from '@/assets/map/stl_button.png'; +import graphType from '../constant/graphType'; +import resourceType from '../constant/resourceType'; + +class SkinCode extends defaultStyle { + constructor() { + super(); + this[graphType.Resource] = { + warning: { + r: 5, + fill: 'red', + offset: { x: 0, y: 0} + }, + hover: { + lineWidth: 2 + }, + Bg: { + image: STLBg + }, + PilotLamp: { + image: STLPilotLamp + }, + Button: { + image: STLButton + } + }; + this[resourceType.Button] = { + text: { + fontSize: 14, + fontWeight: 'bold' + } + }; + } +} + +export default new SkinCode(); diff --git a/src/iscs_new/config/style.js b/src/iscs_new/config/style.js new file mode 100644 index 000000000..a342ac25b --- /dev/null +++ b/src/iscs_new/config/style.js @@ -0,0 +1,10 @@ +import GraphStyle from './graphStyle'; +import PanelStyle from './panelStyle'; +import ResourceStyle from './resourceStyle'; + +export default { + ...GraphStyle, + ...PanelStyle, + ...ResourceStyle +}; + diff --git a/src/iscs_new/constant/graphRender.js b/src/iscs_new/constant/graphRender.js new file mode 100644 index 000000000..859242666 --- /dev/null +++ b/src/iscs_new/constant/graphRender.js @@ -0,0 +1,65 @@ +import graphType from './graphType'; + +const graphRender = {}; + +graphRender[graphType.Text] = { + _type: graphType.Text, + zlevel: 1, + z: 9 +}; + +graphRender[graphType.Table] = { + _type: graphType.Table, + zlevel: 1, + z: 4 +}; + +graphRender[graphType.Resource] = { + _type: graphType.Resource, + zlevel: 1, + z: 8 +}; + +graphRender[graphType.LinePipe] = { + _type: graphType.LinePipe, + zlevel: 1, + z: 4 +}; + +graphRender[graphType.Measure] = { + _type: graphType.Measure, + zlevel: 1, + z: 9 +}; + +graphRender[graphType.Warning] = { + _type: graphType.Warning, + zlevel: 1, + z: 9 +}; + +graphRender[graphType.Switching] = { + _type: graphType.Switching, + zlevel: 1, + z: 9 +}; + +graphRender[graphType.Popup] = { + _type: graphType.Popup, + zlevel: 1, + z: 9 +}; + +graphRender[graphType.ProgramControl] = { + _type: graphType.ProgramControl, + zlevel: 1, + z: 9 +}; + +graphRender[graphType.Pid] = { + _type: graphType.Pid, + zlevel: 1, + z: 9 +}; + +export default graphRender; diff --git a/src/iscs_new/constant/graphType.js b/src/iscs_new/constant/graphType.js new file mode 100644 index 000000000..f74a067d9 --- /dev/null +++ b/src/iscs_new/constant/graphType.js @@ -0,0 +1,15 @@ +const graphType = { + Text: 'text', + Table: 'table', + Table1: 'Table1', + Resource: 'resource', + LinePipe: 'linePipe', + Measure: 'measure', + Warning: 'warning', + Switching: 'switching', // 投切按钮 + Popup: 'popup', // 弹窗按钮 + ProgramControl: 'programControl', // 程制按钮 + Pid: 'pid' // Pid按钮 +}; + +export default graphType; diff --git a/src/iscs_new/constant/panelRender.js b/src/iscs_new/constant/panelRender.js new file mode 100644 index 000000000..40073e157 --- /dev/null +++ b/src/iscs_new/constant/panelRender.js @@ -0,0 +1,65 @@ +import panelType from './panelType'; + +const panelRender = {}; + +panelRender[panelType.Text] = { + _type: panelType.Text, + zlevel: 1, + z: 9 +}; + +panelRender[panelType.Table] = { + _type: panelType.Table, + zlevel: 1, + z: 4 +}; + +panelRender[panelType.Resource] = { + _type: panelType.Resource, + zlevel: 1, + z: 4 +}; + +panelRender[panelType.LinePipe] = { + _type: panelType.LinePipe, + zlevel: 1, + z: 4 +}; + +panelRender[panelType.Measure] = { + _type: panelType.Measure, + zlevel: 1, + z: 9 +}; + +panelRender[panelType.Warning] = { + _type: panelType.Warning, + zlevel: 1, + z: 9 +}; + +panelRender[panelType.Switching] = { + _type: panelType.Switching, + zlevel: 1, + z: 9 +}; + +panelRender[panelType.Popup] = { + _type: panelType.Popup, + zlevel: 1, + z: 9 +}; + +panelRender[panelType.ProgramControl] = { + _type: panelType.ProgramControl, + zlevel: 1, + z: 9 +}; + +panelRender[panelType.Pid] = { + _type: panelType.Pid, + zlevel: 1, + z: 9 +}; + +export default panelRender; diff --git a/src/iscs_new/constant/panelType.js b/src/iscs_new/constant/panelType.js new file mode 100644 index 000000000..9babf0813 --- /dev/null +++ b/src/iscs_new/constant/panelType.js @@ -0,0 +1,14 @@ +const panelType = { + Text: 'panel-text', + Table: 'panel-table', + Resource: 'panel-resource', + LinePipe: 'panel-linePipe', + Measure: 'panel-measure', + Warning: 'panel-warning', + Switching: 'panel-switching', // 投切按钮 + Popup: 'panel-popup', // 弹窗按钮 + ProgramControl: 'panel-programControl', // 程制按钮 + Pid: 'panel-pid' // Pid按钮 +}; + +export default panelType; diff --git a/src/iscs_new/constant/resourceRender.js b/src/iscs_new/constant/resourceRender.js new file mode 100644 index 000000000..3ce6a819a --- /dev/null +++ b/src/iscs_new/constant/resourceRender.js @@ -0,0 +1,32 @@ +import resourceType from './resourceType'; + +const resourceRender = {}; +resourceRender[resourceType.Background] = { + _type: resourceType.Background, + zlevel: 1, + z: 9, + z2: 1 +}; + +resourceRender[resourceType.Button] = { + _type: resourceType.Button, + zlevel: 1, + z: 9, + z2: 1 +}; + +resourceRender[resourceType.PilotLamp] = { + _type: resourceType.PilotLamp, + zlevel: 1, + z: 9, + z2: 1 +}; + +resourceRender[resourceType.Display] = { + _type: resourceType.Display, + zlevel: 1, + z: 9, + z2: 1 +}; + +export default resourceRender; diff --git a/src/iscs_new/constant/resourceType.js b/src/iscs_new/constant/resourceType.js new file mode 100644 index 000000000..0f9be6630 --- /dev/null +++ b/src/iscs_new/constant/resourceType.js @@ -0,0 +1,8 @@ +const resourceType = { + Button: 'res-button', + Display: 'res-display', + PilotLamp: 'res-pilotLamp', + Background: 'res-background' +}; + +export default resourceType; diff --git a/src/iscs_new/controller.js b/src/iscs_new/controller.js new file mode 100644 index 000000000..dbae427ad --- /dev/null +++ b/src/iscs_new/controller.js @@ -0,0 +1,387 @@ +import * as eventTool from 'zrender/src/core/event'; +import * as utils from './utils/utils.js'; +import Storage from './utils/container/Storage'; +import graphType from './constant/graphType'; +import panelType from './constant/panelType'; +import resourceType from './constant/resourceType'; +import Eventful from 'zrender/src/mixin/Eventful'; +import DragHandle from './dragHandle'; +import SelectingHandle from './selectingHandle'; +import SelectHandle from './selectHandle'; +import KeyBoardHandle from './keyboardHandle'; + +class MapEvent { + constructor(e) { + this.clientX = e.event.clientX; + this.clientY = e.event.clientY; + + let view = e.target; + while (view) { + if ([ + ...Object.values(graphType), + ...Object.values(panelType), + ...Object.values(resourceType) + ].includes(view._type)) { + this.shapeCode = view._code; + this.graphType = view._type; + break; + } + + if (view._subType) { + this.subType = view._subType; + } + + if (view._val) { + this.val = view._val; + } + + view = view.parent; + } + } +} + +class Controller extends Eventful { + constructor(map) { + super(); + this.$map = map; + this.events = map.getEvents(); + this.dragHandle = new DragHandle(map, this); + this.selectingHandle = new SelectingHandle(map, this); + this.selectHandle = new SelectHandle(map, this); + this.keyBoardHandle = new KeyBoardHandle(map, this); + this._pan =false; + this._isNotLeftMouse = false; + this._shortcuts = ''; + this._distance = 0; + this._target = null; + this.initData(); + this.initHandler(); + } + + initData() { + this.storage = new Storage(); + } + + initHandler() { + const zr = this.$map.getZr(); + const keyupHandle = this.onKeyup.bind(this); + const keydownHandle = this.onKeydown.bind(this); + + const dragStartHandle = this.dragHandle.onDragStart; + const draggingHandle = this.dragHandle.onDragging; + const dragEndHandle = this.dragHandle.onDragEnd; + + const selectStartHandle = this.selectingHandle.onSelectStart; + const selectingHandle = this.selectingHandle.onSelecting; + const selectEndHandle = this.selectingHandle.onSelectEnd; + const selectedHandle = this.selectHandle.onSelected; + + const boardKeyupHandle = this.keyBoardHandle.onKeyup; + const boardKeydownHandle = this.keyBoardHandle.onKeydown; + + this.on(this.events.__DragStart, dragStartHandle, this.dragHandle); // 单个元素拖拽 + this.on(this.events.__Dragging, draggingHandle, this.dragHandle); + this.on(this.events.__DragEnd, dragEndHandle, this.dragHandle); + + this.on(this.events.__SelectStart, selectStartHandle, this.selectingHandle); + this.on(this.events.__Selecting, selectingHandle, this.selectingHandle); + this.on(this.events.__SelectEnd, selectEndHandle, this.selectingHandle); + + this.on(this.events.__Selected, selectedHandle, this.selectHandle); + + this.enable = function (opts={}) { + const zr = this.$map.getZr(); + + this._panEnable = opts.panEnable || false; + this._zoomEnable = opts.zoomEnable || false; + this._keyEnable = opts.keyEnable || false; + this._dragEnable = opts.draggle || false; + this._areaSelectEnable = opts.selecting || false; + this._selectEnable = opts.selectable || false; + this._reflectEnable = opts.reflectable || false; + this._preventDefaultMouseMove = opts.preventDefaultMouseMove || true; + this.disable(); + + zr.on('mousedown', this.mousedown, this); + zr.on('mousemove', this.mousemove, this); + zr.on('mouseup', this.mouseup, this); + + zr.on('globalout', this.mouseup, this); + zr.on('mousewheel', this.mousewheel, this); + + zr.dom.addEventListener('keyup', keyupHandle, false); + zr.dom.addEventListener('keydown', keydownHandle, false); + zr.dom.focus(); + + this.on(this.events.Keyup, boardKeyupHandle, this.keyBoardHandle); + this.on(this.events.Keydown, boardKeydownHandle, this.keyBoardHandle); + }; + + this.disable = function () { + zr.off('mousedown', this.mousedown); + zr.off('mousemove', this.mousemove); + zr.off('mouseup', this.mouseup); + + zr.off('globalout', this.mouseup); + zr.off('mousewheel', this.mousewheel); + + zr.dom.removeEventListener('keyup', keyupHandle, false); + zr.dom.removeEventListener('keydown', keydownHandle, false); + + this.off(this.events.Keyup, boardKeyupHandle); + this.off(this.events.Keydown, boardKeydownHandle); + }; + + this.dispose = function () { + zr.off('click', this.click); + zr.off('contextmenu', this.contextmenu); + this.off(this.events.__DragStart, dragStartHandle); + this.off(this.events.__Dragging, draggingHandle); + this.off(this.events.__DragEnd, dragEndHandle); + + this.off(this.events.__SelectStart, selectStartHandle); + this.off(this.events.__Selecting, selectingHandle); + this.off(this.events.__SelectEnd, selectEndHandle); + + this.off(this.events.__Selected, selectedHandle); + this.disable(); + }; + + zr.on('click', this.click, this); + zr.on('contextmenu', this.contextmenu, this); + } + + getKeyStr() { + return this._shortcuts; + } + + isSpecialEl(e) { + return ['dragEl', 'selectingEl'].includes(e.subType); + } + + limitDrag(e) { + const dx2 = Math.pow(e.dx, 2); + const dy2 = Math.pow(e.dy, 2); + const scale = this.$map.$options.getScaleRate(); + const diff = Math.ceil(Math.sqrt(dx2+dy2)); + + if (scale > 1) { + return true; + } else if (diff > 2/scale) { + return true; + } + + return false; + } + + mousedown(e) { + const event = new MapEvent(e); + const target = this.$map.getShapeByCode(event.shapeCode); + const zr = this.$map.getZr(); + + this._x = e.offsetX; + this._y = e.offsetY; + this._pan = false; + this._target = target; + + zr.dom.focus(); + if (utils.isMobile()) { + if (e.event.touches.length == 1 && this._dragEnable && target) { + this.trigger(this.events.__DragStart, { x: e.offsetX, y: e.offsetY, target }); + } else if (e.event.touches.length >= 2) { + const touches = e.event.touches; + const powX = Math.pow(touches[1].clientX-touches[0].clientX, 2); + const powY = Math.pow(touches[1].clientY-touches[0].clientY, 2); + this._distance = Math.sqrt(powX + powY); + } + } else { + this._isNotLeftMouse = eventTool.isMiddleOrRightButtonOnMouseUpDown(e); + + if (this._isNotLeftMouse) { // 非左键点击 + this.$map.setCursorStyle('grab'); // 鼠标状态 + } else { + this.selectingHandle.clear(e); + if (this.isSpecialEl(event)) { return; } + if (this._dragEnable && target) { + this.trigger(this.events.__DragStart, { x: e.offsetX, y: e.offsetY, target }); + } else if (this._areaSelectEnable && !event.graphType) { + this.trigger(this.events.__SelectStart, { x: e.offsetX, y: e.offsetY}); + } + } + } + } + + mousemove(e) { + const oldX = this._x; + const oldY = this._y; + const dx = Math.round(e.offsetX - this._x); + const dy = Math.round(e.offsetY - this._y); + const target = this._target; + + this._x = e.offsetX; + this._y = e.offsetY; + this._preventDefaultMouseMove && eventTool.stop(e.event); + + if (utils.isMobile()) { + if (target && e.event.touches.length == 1) { + if (this._dragEnable && this.dragHandle.isDragging()) { + if (this.limitDrag({dx, dy})) { + this.trigger(this.events.__Dragging, { dx, dy }); + if (this._reflectEnable) { + this.trigger(this.events.Reflect, {dx, dy}); + } + } else { + this._x = oldX; + this._y = oldY; + } + } + } else if (e.event.touches.length == 2) { + const touches = e.event.touches; + const powX = Math.pow(touches[1].clientX-touches[0].clientX, 2); + const powY = Math.pow(touches[1].clientY-touches[0].clientY, 2); + const distance = Math.sqrt(powX + powY); + const wheelDelta = distance - this._distance; + const originX = Math.ceil((touches[1].clientX+touches[0].clientX)/2); + const originY = Math.ceil((touches[1].clientY+touches[0].clientY)/2); + + if (Math.abs(wheelDelta) >= 10) { + const scale = wheelDelta > 0? 1: -1; + this.trigger(this.events.__Zoom, {type: this.events.__Zoom, scale, originX, originY }); + } + this._distance = distance; + } else if (e.event.touches.length > 2) { + if (this._panEnable) { + if (dx**2+dy**2 > 8) { + this._pan = true; + } + this.$map.setCursorStyle('grabbing'); + this.trigger(this.events.__Pan, { dx, dy, oldX, oldY, newX: this._x, newY: this._y }); + } + } + } else { + if (this._isNotLeftMouse) { + if (this._panEnable) { + if (dx**2+dy**2 > 8) { + this._pan = true; + } + this.$map.setCursorStyle('grabbing'); + this.trigger(this.events.__Pan, { dx, dy, oldX, oldY, newX: this._x, newY: this._y }); + } + } else { + if (this._target && this._dragEnable && this.dragHandle.isDragging()) { + if (this.limitDrag({dx, dy})) { + this.trigger(this.events.__Dragging, { dx, dy }); + if (this._reflectEnable) { + this.trigger(this.events.Reflect, {dx, dy}); + } + } else { + this._x = oldX; + this._y = oldY; + } + } else if (this._areaSelectEnable && this.selectingHandle.isSelecting()) { + this.trigger(this.events.__Selecting, { x: e.offsetX, y: e.offsetY }); + } + } + } + } + + mouseup(e) { + const target = this._target; + + if (this._isNotLeftMouse) { + this._isNotLeftMouse = false; + this.$map.setCursorStyle('default'); + } else { + if (this._dragEnable && this.dragHandle.isDragging()) { + this.trigger(this.events.__DragEnd, {x: e.offsetX, y: e.offsetY}); + } else if (this._areaSelectEnable && this.selectingHandle.isSelecting()) { + this.trigger(this.events.__SelectEnd, { x: e.offsetX, y: e.offsetY }); + } + + if (this._selectEnable && target) { + this.trigger(this.events.__Selected, {target }); + } + } + this._target = null; + } + + mousewheel(e) { + const zoomEnable = this._zoomEnable; + const wheelDelta = e.wheelDelta; + const originX = Math.ceil(e.offsetX); + const originY = Math.ceil(e.offsetY); + + if (wheelDelta === 0 || !zoomEnable) { + return; + } + + if (zoomEnable) { + eventTool.stop(e.event); + + let scale = 1; + if (wheelDelta > 0) { + scale = 1; + this.$map.setCursorStyle('zoom-in'); + } else if (wheelDelta < 0) { + scale = -1; + this.$map.setCursorStyle('zoom-out'); + } + + this.trigger(this.events.__Zoom, {type: this.events.__Zoom, scale, originX, originY }); + } + } + + click(e) { + const event = new MapEvent(e); + + if (!event.graphType) { + this.selectHandle.clear(); + this.selectingHandle.clear(); + this.clear(); + } + + this.trigger(this.events.Selected, event); + } + + contextmenu(e) { + eventTool.stop(e.event); + + const event = new MapEvent(e); + if (!this._pan) { + this.trigger(this.events.ContextMenu, event); + } + + this._pan = false; + } + + onKeydown(e) { + let shortcuts = e.key; + + if (e.altKey && e.key != 'Alt') { + shortcuts = `Alt_${shortcuts}`; + } + + if (e.shiftKey && e.key != 'Shift') { + shortcuts = `Shift_${shortcuts}`; + } + + if (e.ctrlKey && e.key != 'Control') { + shortcuts = `Control_${shortcuts}`; + } + + this._shortcuts = shortcuts; + this.trigger(this.events.Keydown, {key: shortcuts}); + } + + onKeyup(e) { + this._shortcuts = ''; + } + + clear() { + this.storage.clear(); + this.storage.clearClipboard(); + this._pan =false; + } +} + +export default Controller; diff --git a/src/iscs_new/dragHandle.js b/src/iscs_new/dragHandle.js new file mode 100644 index 000000000..2bef068c5 --- /dev/null +++ b/src/iscs_new/dragHandle.js @@ -0,0 +1,55 @@ +export default class DragHandle { + constructor(map, controller) { + this.$zr = map.getZr(); + this.$controller = controller; + this.$options = map.getOptions(); + this.$painter = map.getPainter(); + this.dragging = false; + } + + isDragging() { + return this.dragging; + } + + onDragStart(e) { + if (e.target && this.$controller.storage.has(e.target.model.code)) { + this.dragging = true; + } + } + + onDragging(e) { + const dx = e.dx; + const dy = e.dy; + const scaleRate = this.$options.getScaleRate(); + + e.dx = dx / scaleRate; + e.dy = dy / scaleRate; + + if (this.dragging) { + this.$controller.storage.values().forEach(dragTarget => { + if (dragTarget) { + if (dragTarget.hover) { + this.$painter.hoverLevel.remove(dragTarget.hover); + dragTarget.hover = null; + } + + if (dragTarget.instance.doInactive) { + dragTarget.instance.doInactive(this.$zr); + } + + if (dragTarget.instance.dragging) { + dragTarget.instance.dragging(e); + } + + if (dragTarget.instance.doActive) { + dragTarget.instance.doActive(this.$zr); + } + } + }); + } + } + + onDragEnd(e) { + this.dragging = false; + } +} diff --git a/src/iscs_new/draggable/Image.js b/src/iscs_new/draggable/Image.js new file mode 100644 index 000000000..8a2412414 --- /dev/null +++ b/src/iscs_new/draggable/Image.js @@ -0,0 +1,127 @@ + +import _ from 'lodash'; +import * as graphic from '../graph/graphic'; +import * as eventTool from 'zrender/src/core/event'; +import panelType from '../constant/panelType'; + +export default class ImageDraggable extends graphic.Group { + constructor(handle, draggle=false) { + super(); + this.draggle = draggle; + this.handle = handle; + this.style = handle.$map.getDefaultStyleDict(); + this.invTransform = [1, 0, 0, 1, 0, 0]; + this.target = null; + this.shapes = []; + this.offset = null; + this.r = 2; + + if (this.draggle && + this.handle.e.target && + this.handle.e.target.instance) { + const bound = this.handle.e.target.instance.getBoundingRect(); + const r = (this.handle.e.target.model.width||this.r)+3; + this.shapes.push(this.newShape({ cx: bound.x, cy: bound.y, r})); + this.shapes.push(this.newShape({ cx: bound.x+bound.width, cy: bound.y, r})); + this.shapes.push(this.newShape({ cx: bound.x+bound.width, cy: bound.y+bound.height, r})); + this.shapes.push(this.newShape({ cx: bound.x, cy: bound.y+bound.height, r})); + this.shapes.forEach(shape => { this.add(shape); }); + } + } + + newShape(shape) { + return new graphic.Circle({ + _subType: 'dragEl', + zlevel: 1, + z: 999999, + draggable: false, + cursor: 'crosshair', + shape, + style: { + opacity: 0.5, + fill: '#0000ff' + }, + onmousedown: this.mousedown.bind(this), + onmousemove: _.throttle(this.mousemove.bind(this), 100), + onmouseup: this.mouseup.bind(this) + }); + } + + updateShapeRect(dx, dy) { + const index = this.shapes.indexOf(this.target); + if (index >= 0) { + this.shapes[(3-index)%4].setShape({cx: this.shapes[(3-index)%4].shape.cx+dx}); + this.shapes[(5-index)%4].setShape({cy: this.shapes[(5-index)%4].shape.cy+dy}); + } + + return this.getBoundingRect().clone(); + } + + updateModel(target, bound) { + target.model.width = bound.width-this.r*2; + target.model.height = bound.height-this.r*2; + } + + setShape(dx, dy) { + const bound = this.updateShapeRect(dx, dy); + + if (this.handle.e.target && + this.handle.e.target.instance) { + this.handle.e.target.model.point = { x: bound.x+this.r, y: bound.y+this.r }; + + this.handle.e.target.instance.doInactive(this.handle.$zr); + this.handle.e.target.instance.setShape(this.handle.e.target.model); + this.handle.e.target.instance.doActive(this.handle.$zr); + } + } + + mousedown(e) { + if (e.target && ['dragEl'].includes(e.target._subType)) { + if (!eventTool.isMiddleOrRightButtonOnMouseUpDown(e)) { + this.target = e.target; + this.offset = {x: e.offsetX, y: e.offsetY}; + this.setDraggable(true); + } + } + } + + mousemove(e) { + eventTool.stop(e.event); + if (this.target && + this.handle.e.target && + this.offset) { + if (!eventTool.isMiddleOrRightButtonOnMouseUpDown(e)) { + const type = this.handle.e.target.model._type; + const dx = Math.round(e.offsetX-this.offset.x); + const dy = Math.round(e.offsetY-this.offset.y); + + this.setShape(...this.handle.normalizedDiff(dx, [panelType.Resource].includes(type)? dx:dy)); + this.handle.$controller.trigger(this.handle.$controller.events.Reflect, {dx, dy}); + + this.offset = {x: e.offsetX, y: e.offsetY}; + } + } + } + + mouseup(e) { + if (this.target && + this.handle.e.target && + this.offset) { + const type = this.handle.e.target.model._type; + const dx = Math.round(e.offsetX-this.offset.x); + const dy = Math.round(e.offsetY-this.offset.y); + this.setShape(...this.handle.normalizedDiff(dx, [panelType.Resource].includes(type)? dx:dy)); + this.handle.$controller.trigger(this.handle.$controller.events.Reflect, {dx, dy}); + + this.setDraggable(false); + this.offset = null; + this.target = null; + } + } + + setDraggable(draggable) { + this.shapes.forEach(shape => { + shape.attr('draggable', draggable); + }); + } +} diff --git a/src/iscs_new/draggable/Line.js b/src/iscs_new/draggable/Line.js new file mode 100644 index 000000000..3c4c2c802 --- /dev/null +++ b/src/iscs_new/draggable/Line.js @@ -0,0 +1,118 @@ +import _ from 'lodash'; +import * as graphic from '../graph/graphic'; +import * as eventTool from 'zrender/src/core/event'; +import panelType from '../constant/panelType'; +export default class LineDraggable extends graphic.Group { + constructor(handle, draggle=true) { + super(); + this.draggle = draggle; + this.handle = handle; + this.style = handle.$map.getDefaultStyleDict(); + this.invTransform = [1, 0, 0, 1, 0, 0]; + this.target = null; + this.shapes = []; + this.line = null; + this.r = 2; + this.offset = null; + + if (this.draggle && this.handle.e.target && this.handle.e.target.model.points) { + this.handle.e.target.model.points.forEach((elem, index) => { + const r = (this.handle.e.target.model.width||this.r)+1; + this.shapes.push(this.newShape({ cx: elem.x, cy: elem.y, r })); + this.add(this.shapes[index]); + }); + + this.line = new graphic.Line({ + _subType: 'dragEl', + zlevel: 1, + z: 999990, + shape: {x1: 0, y1: 0, x2: 0, y2: 0 }, + style: { + opacity: 0.8, + lineWidth: this.style[panelType.LinePipe].line.lineWidth, + stroke: '#ff0000' + } + }); + + this.add(this.line); + } + } + + newShape(shape) { + return new graphic.Circle({ + _subType: 'dragEl', + zlevel: 1, + z: 999999, + draggable: false, + cursor: 'crosshair', + shape, + style: { + opacity: 0.5, + fill: '#0000ff' + }, + onmousedown: this.mousedown.bind(this), + onmousemove: _.throttle(this.mousemove.bind(this), 100), + onmouseup: this.mouseup.bind(this) + }); + } + + setShape(e) { + const dx = Math.round(e.offsetX-this.offset.x); + const dy = Math.round(e.offsetY-this.offset.y); + + if (this.handle.e.target && this.handle.e.target.instance) { + this.offset = {x: e.offsetX, y: e.offsetY}; + this.handle.e.target.instance.doInactive(this.handle.$zr); + this.handle.e.target.instance.setShape(this.handle.e.target.model); + this.handle.e.target.instance.doActive(this.handle.$zr); + this.handle.$controller.trigger(this.handle.$controller.events.Reflect, {dx, dy}); + } + } + + mousedown(e) { + this.offset = {x: e.offsetX, y: e.offsetY}; + if (e.target && ['dragEl'].includes(e.target._subType)) { + this.target = e.target; + if (!eventTool.isMiddleOrRightButtonOnMouseUpDown(e)) { + this.setDraggable(true); + } + } + } + + mousemove(e) { + eventTool.stop(e.event); + if (this.target && this.handle.e.target) { + if (!eventTool.isMiddleOrRightButtonOnMouseUpDown(e) ) { + this.handle.e.target.model.points = this.shapes.map(elem => { + const position = elem.position || [0, 0]; + const x = elem.shape.cx + position[0]; + const y = elem.shape.cy + position[1]; + return {x, y}; + }); + + this.setShape(e); + } + } + } + + mouseup(e) { + if (this.target && this.handle.e.target) { + this.handle.e.target.model.points = this.shapes.map(elem => { + const position = elem.position || [0, 0]; + const x = elem.shape.cx + position[0]; + const y = elem.shape.cy + position[1]; + return {x, y}; + }); + this.setShape(e); + this.setDraggable(false); + this.line.setShape({x1: 0, y1: 0, x2: 0, y2: 0 }); + this.target = null; + } + } + + setDraggable(draggable) { + this.shapes.forEach(shape => { + shape.attr('draggable', draggable); + }); + } +} diff --git a/src/iscs_new/graph/core/parser.js b/src/iscs_new/graph/core/parser.js new file mode 100644 index 000000000..2ee8fc1e7 --- /dev/null +++ b/src/iscs_new/graph/core/parser.js @@ -0,0 +1,73 @@ +import * as graphic from '../graphic'; + +class Parser { + constructor(graph) { + this.__graph = graph; + } + + createShape(model, opts) { + const option = Object.assign(opts, { + zlevel: model.zlevel, + z: model.z, + z2: (model.layer || model.z2) + opts.z2, + silent: opts.silent || false, + cursor: opts.cursor ? opts.cursor : this.__graph._is ? 'default' : 'pointer' + }); + const shape = new graphic[opts.type](option); + + this.__graph.add(shape); + return shape; + } + + isShapeLeaf(obj) { + return obj && obj.name && obj.type && Object.keys(graphic).includes(obj.type); + } + + buildSTL(model, template, out = {}) { + Object.keys(template).forEach(attr => { + if (!['__ctx'].includes(attr)) { + const leaf = template[attr]; + if (leaf instanceof Function) { + out[attr] = leaf(model); + } else if (leaf instanceof Array) { + out[attr] = leaf.map(el => { + return el instanceof Array + ? this.buildSTL(model, el, []) + : el instanceof Object + ? this.buildSTL(model, el, {}) + : el; + }); + } else if (leaf instanceof Object) { + out[attr] = this.buildSTL(model, leaf, {}); + } else { + out[attr] = leaf; + } + } + }); + + return out; + } + + parse2Shape(model, stl, out = {}) { + if (stl instanceof Array) { + stl.forEach(elem => { + const shape = this.parse2Shape(model, elem, out); + out[shape.name] = shape; + }); + } else if (Object instanceof Object) { + if (this.isShapeLeaf(stl)) { + return this.createShape(model, stl); + } else { + Object.keys(stl || {}).forEach(attr => { out[attr] = this.parse2Shape(model, stl[attr]); }); + } + } + + return out; + } + + parse(template, model) { + return this.parse2Shape(model, this.buildSTL(model, template)); + } +} + +export default Parser; diff --git a/src/iscs_new/graph/core/state.js b/src/iscs_new/graph/core/state.js new file mode 100644 index 000000000..e2dcc1549 --- /dev/null +++ b/src/iscs_new/graph/core/state.js @@ -0,0 +1,85 @@ +import * as graphic from '../graphic'; + +class State extends graphic.Group { + constructor(shape, is) { + super(); + + if (is) { + this._subType = shape.model._type; + this._val = shape.model.code; + } else { + this._code = shape.model.code; + this._type = shape.model._type; + } + + this._caches = {}; + this._shape = shape; + this._is = is; + + this._origin = null; + this._rotation = null; + this._scale = [1, 1]; + } + + onFrame(delta) { + } + + setShape(model) { + this.removeAll(); + this.parser.parse(this.$template, model, this.$elMap); + this.transformed(model); + } + + setState(state) { + if (this.$template.__ctx && this.$template.__ctx.$doUpdate) { + this.$template.__ctx.$doUpdate({model: this._shape.model, state}); + } + } + + doActive(zr) { + if (this.$template.__ctx && this.$template.__ctx.$doActive) { + this.$template.__ctx.$doActive(zr); + } + } + + doInactive(zr) { + if (this.$template.__ctx && this.$template.__ctx.$doInactive) { + this.$template.__ctx.$doInactive(zr); + } + } + + dragging(e) { + if (this.$template.__ctx && this.$template.__ctx.$doDragging) { + this.$template.__ctx.$doDragging(this._shape.model); + } + this.setShape(this._shape.model); + } + + transformed({origin, rotation, scale}) { + this._origin = origin; + this._rotation = rotation; + this._scale = scale||[1, 1]; + + this.traverse(el => { + if (!(el instanceof graphic.Group)) { + el.attr('origin', origin); + el.attr('rotation', rotation); + el.attr('scale', scale); + } + }, this); + } + + traversed(elMap, cb) { + Object.values(elMap).forEach(el => { + if (el) { + if (this.parser.isShapeLeaf(el)) { + cb(el); + } else { + this.traversed(el, cb); + } + } + }); + } +} + +export default State; diff --git a/src/iscs_new/graph/graph.js b/src/iscs_new/graph/graph.js new file mode 100644 index 000000000..da20fcf52 --- /dev/null +++ b/src/iscs_new/graph/graph.js @@ -0,0 +1,81 @@ + +// import Animation from 'zrender/src/animation/Animation'; +import Parser from './core/parser'; +import State from './core/state'; + +const lifeCycleHookList = ['onload', 'reload']; +const actionHookList = ['doUpdate', 'doActive', 'doInactive']; + +function noop () {} + +class Graph extends State { + constructor(options, shape, is) { + super(shape, is); + + this.invTransform = [1, 0, 0, 1, 0, 0]; + this.parser = new Parser(this); + + this.reload(options); + // this.$animation = new Animation({onFrame: this.onFrame }); + // this.$animation.start(); + if (this.$template.__ctx.$onload) this.$template.__ctx.$onload(); + } + + reload(options) { + const index = options.cacheId; + const cache = this._caches[index]; // 获取缓存 + const shapes = []; + + this.removeAll(); + + if (cache) { + this.$template = cache.template; + this.$elMap = cache.elMap; + + cache.shapes.forEach(shape => { this.add(shape); }); + } else { + this.$template = this.defineTemplate(options); // 生成模板 + this.$elMap = this.compile(this.$template, this._shape); + + this.traverse(shape=> { shapes.push(shape); }, this); + + this._caches[index] = { template: this.$template, elMap: this.$elMap, shapes }; + } + + this.transformed(this._shape.model); + // this.setState(this._shape._state); + if (this.$template.__ctx.$reload) this.$template.__ctx.$reload(); + } + + defineTemplate (options) { + const template = options.template; + const methods = options.methods||{}; + const incidents = options.incidents||{}; + const actions = options.actions||{}; + const ctx = Object.create(Object.assign(options.data(), {$vm: this})); + + Object.keys(methods).forEach(name => { + ctx[name] = (methods[name] || noop).bind(ctx); + }); + + Object.keys(incidents).forEach(name => { + ctx[`$${name}`] = (incidents[name] || noop).bind(ctx); + }); + + actionHookList.forEach(name => { + ctx[`$${name}`] = (actions[name] || noop).bind(ctx); + }); + + lifeCycleHookList.forEach(name => { + ctx[`$${name}`] = (options[name] || noop).bind(ctx); + }); + + return Object.assign(template.apply(ctx), { __ctx: ctx }); + } + + compile(template, shape) { + return this.parser.parse(template, shape.model, {}); + } +} + +export default Graph; diff --git a/src/iscs_new/graph/graphic.js b/src/iscs_new/graph/graphic.js new file mode 100644 index 000000000..de5f2eb72 --- /dev/null +++ b/src/iscs_new/graph/graphic.js @@ -0,0 +1,32 @@ +export {default as Group} from 'zrender/src/container/Group'; +export {default as Image} from 'zrender/src/graphic/Image'; +export {default as Text} from 'zrender/src/graphic/Text'; + +export {default as Arc} from 'zrender/src/graphic/shape/Arc'; +export {default as BezierCurve} from 'zrender/src/graphic/shape/BezierCurve'; +export {default as Circle} from 'zrender/src/graphic/shape/Circle'; +export {default as Droplet} from 'zrender/src/graphic/shape/Droplet'; +export {default as Ellipse} from 'zrender/src/graphic/shape/Ellipse'; +export {default as Heart} from 'zrender/src/graphic/shape/Heart'; +export {default as Isogon} from 'zrender/src/graphic/shape/Isogon'; +export {default as Line} from 'zrender/src/graphic/shape/Line'; +export {default as Polygon} from 'zrender/src/graphic/shape/Polygon'; +export {default as Polyline} from 'zrender/src/graphic/shape/Polyline'; +export {default as Rect} from 'zrender/src/graphic/shape/Rect'; +export {default as Ring} from 'zrender/src/graphic/shape/Ring'; +export {default as Rose} from 'zrender/src/graphic/shape/Rose'; +export {default as Sector} from 'zrender/src/graphic/shape/Sector'; +export {default as Star} from 'zrender/src/graphic/shape/Star'; +export {default as Trochoid} from 'zrender/src/graphic/shape/Trochoid'; + +export {default as Hover} from './shape/Hover'; +export {default as Digit} from './shape/Digit'; +export {default as Arrow} from './shape/Arrow'; +export {default as ArrowLine} from './shape/ArrowLine'; +export {default as Sausage} from './shape/Sausage'; +export {default as Pointer} from './shape/Pointer'; +export {default as Table} from './shape/Table/table'; +export {default as CurvedScale} from './shape/CurvedScale/curvedScale'; +export {default as LinearScale} from './shape/LinearScale/linearScale'; +export {default as Coordinate} from './shape/Coordinate/Coordinate'; +export {default as Svg} from './shape/Svg'; diff --git a/src/iscs_new/graph/shape/Arrow.js b/src/iscs_new/graph/shape/Arrow.js new file mode 100644 index 000000000..b4197409c --- /dev/null +++ b/src/iscs_new/graph/shape/Arrow.js @@ -0,0 +1,49 @@ +import Path from 'zrender/src/graphic/Path'; + +export default Path.extend({ + + type: 'arrow', + + shape: { + x: 0, + y: 0, + w: 3, + r: 6, + toward: null + }, + + style: { + stroke: '#000', + fill: null + }, + + buildPath: function (ctx, shape) { + var x = shape.x; + var y = shape.y; + var r = shape.r; + var w = shape.w; + + switch (shape.toward) { + case 'up': + ctx.moveTo(x - w, y + r); + ctx.lineTo(x - w, y); + ctx.lineTo(x - w - r, y); + ctx.lineTo(x, y - r); + ctx.lineTo(x + w + r, y); + ctx.lineTo(x + w, y); + ctx.lineTo(x + w, y + r); + ctx.closePath(); + break; + case 'down': + ctx.moveTo(x - w, y - r); + ctx.lineTo(x - w, y); + ctx.lineTo(x - w - r, y); + ctx.lineTo(x, y + r); + ctx.lineTo(x + w + r, y); + ctx.lineTo(x + w, y); + ctx.lineTo(x + w, y - r); + ctx.closePath(); + break; + } + } +}); diff --git a/src/iscs_new/graph/shape/ArrowLine.js b/src/iscs_new/graph/shape/ArrowLine.js new file mode 100644 index 000000000..3253adb6d --- /dev/null +++ b/src/iscs_new/graph/shape/ArrowLine.js @@ -0,0 +1,48 @@ +import Path from 'zrender/src/graphic/Path'; + +export default Path.extend({ + + type: 'arrow-line', + + shape: { + x: 0, + y: 0, + l: 15, + r: 5, + isLeft: true, + toLeft: true + }, + + style: { + stroke: '#000', + fill: null + }, + + buildPath: function (ctx, shape) { + var x = shape.x; + var y = shape.y; + var l = shape.l; + var r = shape.r; + var d = shape.toLeft ? 1: -1; + + if (shape.isLeft && shape.toLeft || !shape.isLeft && !shape.toLeft) { + ctx.moveTo(x, y); + ctx.lineTo(x, y - r); + ctx.lineTo(x - l*d, y - r); + ctx.lineTo(x - l*d - r*d, y); + ctx.lineTo(x - l*d, y + r); + ctx.lineTo(x, y + r); + ctx.closePath(); + } + + if (shape.isLeft && !shape.toLeft || !shape.isLeft && shape.toLeft) { + ctx.moveTo(x, y); + ctx.lineTo(x + r*d, y - r); + ctx.lineTo(x + r*d + l*d, y - r); + ctx.lineTo(x + r*d + l*d, y + r); + ctx.lineTo(x + r*d, y + r); + ctx.closePath(); + } + + } +}); diff --git a/src/iscs_new/graph/shape/Coordinate/Coordinate.js b/src/iscs_new/graph/shape/Coordinate/Coordinate.js new file mode 100644 index 000000000..156bc619c --- /dev/null +++ b/src/iscs_new/graph/shape/Coordinate/Coordinate.js @@ -0,0 +1,395 @@ +import * as graphic from '../../graphic'; +import LineView from './lineView'; + +export default class LineCoordinate extends graphic.Group { + constructor(option) { + super(); + + this._option = { + zlevel: option.zlevel || 0, + z: option.z || 0, + z2: option.z2 || 0, + shape: { + x: 0, + y: 0, + xLength: 100, + yLength: 60, + ...option.shape + }, + style: { + globalStyle: { + lineWidth: 0.2, + color: '#000', + ...option.style.globalStyle + }, + xAxis: { + show: true, + type: 'category', + boundaryGap: 2, + name: option.style.xAxis.name, + nameGap: { + left: 8, + ...option.style.xAxis.nameGap + }, + axisLine: { + symbol: true, + style: { + }, + ...option.style.xAxis.axisLine + }, + axisTick: { + show: true, + splitNumber: 0, + inside: true, + style: { + }, + ...option.style.xAxis.axisTick + }, + axisLabel: { + show: true, + distance: 4, + verticalAlign: 'top', + style: { + }, + ...option.style.xAxis.axisLabel + }, + data: option.style.xAxis.data||[] + }, + yAxis: { + show: true, + type: 'category', + name: option.style.yAxis.name, + boundaryGap: 3, + nameGap: { + left: 2, + ...option.style.yAxis.nameGap + }, + axisLine: { + symbol: true, + style: { + }, + ...option.style.yAxis.axisLine + }, + axisTick: { + show: true, + splitNumber: 5, + inside: true, + style: { + }, + ...option.style.yAxis.axisTick + }, + axisLabel: { + show: true, + distance: 2, + verticalAlign: 'top', + style: { + }, + ...option.style.yAxis.axisLabel + }, + data: option.style.yAxis.data||[] + }, + series: { + type: 'line', + data: [], + style: { + }, + ...option.style.series + } + } + }; + + this.lineView = new LineView(this); + this.render(); + } + + render() { + this.removeAll(); + this._createCoordinate(this._option); + this._createXTicks(this._option); + this._createYTicks(this._option); + this._createData(this._option); + } + + _createCoordinate(option) { + const {shape, style} = option; + + var xAxis = style.xAxis; + var yAxis = style.yAxis; + + var xLength = shape.xLength; + var yLength = shape.yLength; + + var x = shape.x; + var y = shape.y; + + if (xAxis.show) { + const line = new graphic.Line({ + zlevel: this._option.zlevel, + z: this._option.z, + z2: this._option.z2, + ...this._transformation(), + shape: { + x1: x, + y1: y, + x2: x + xLength, + y2: y + } + }); + + line.setStyle({lineCap: 'square', ...style.globalStyle, ...xAxis.axisLine }); + this.add(line); + } + + if (yAxis.show) { + const line = new graphic.Line({ + zlevel: this._option.zlevel, + z: this._option.z, + z2: this._option.z2, + ...this._transformation(), + shape: { + x1: x, + y1: y, + x2: x, + y2: y - yLength + } + }); + + line.setStyle({lineCap: 'square', ...style.globalStyle, ...yAxis.axisLine }); + this.add(line); + } + } + _createXTicks(option) { + const {shape, style} = option; + const xAxis= style.yAxis; + + if (xAxis.axisLine.symbol) { + const x = shape.x + shape.xLength; + const y = shape.y; + const arrows = new graphic.Polygon({ + zlevel: this._option.zlevel, + z: this._option.z, + z2: this._option.z2, + ...this._transformation(), + shape: { + points: [[x + 4, y], [x - 1, y + 1], [x, y], [x - 1, y- 1], [x + 4, y]], + smooth: 0 + } + }); + arrows.setStyle({ ...style.globalStyle, ...xAxis.axisTick.style }); + this.add(arrows); + } + if (xAxis.name) { + const label = new graphic.Text({ + zlevel: this._option.zlevel, + z: this._option.z, + z2: this._option.z2, + ...this._transformation(), + style: { + textVerticalAlign: 'middle', + textAlign: 'left', + text: xAxis.name, + fontSize: 5, + x: shape.x + shape.xLength + xAxis.nameGap.left, + y: shape.y, + textFill: { ...style.globalStyle, ...xAxis.axisTick.style } + } + }); + this.add(label); + } + const scale = (xAxis.data.length - 1) * xAxis.axisTick.splitNumber; + const dataNum = scale + xAxis.boundaryGap; + const num = shape.xLength / dataNum; + const x = shape.x; + const y = shape.y; + let dataIndex = 0; + for (let index = 0; index < dataNum; index++) { + if (xAxis.axisTick.show) { + const spliceLine = new graphic.Line({ + zlevel: this._option.zlevel, + z: this._option.z, + z2: this._option.z2, + ...this._transformation(), + shape: { + x1: x + (num * (index + 1)), + y1: y, + x2: x + (num * (index + 1)), + y2: y - 2 + } + }); + if (index <= scale) { + spliceLine.setStyle({ ...style.globalStyle, ...xAxis.axisTick.style }); + } else { + spliceLine.setStyle({ lineWidth: 0 }); + } + this.add(spliceLine); + } + + if (xAxis.axisLabel.show && + xAxis.axisTick.splitNumber && ( + index % xAxis.axisTick.splitNumber) == 0) { + const label = new graphic.Text({ + zlevel: this._option.zlevel, + z: this._option.z, + z2: this._option.z2, + ...this._transformation(), + style: { + textVerticalAlign: 'middle', + textAlign: 'center', + text: xAxis.data[dataIndex], + fontSize: 5, + x: x + (num * (index + 1)), + y: y + xAxis.axisLabel.distance, + textFill: { ...style.globalStyle, ...xAxis.axisTick.style } + } + }); + this.add(label); + dataIndex++; + } + } + } + _createYTicks(option) { + const {style, shape} = option; + const yAxis= style.yAxis; + + if (yAxis.axisLine.symbol) { + const x = shape.x; + const y = shape.y - shape.yLength; + const arrows = new graphic.Polygon({ + zlevel: this._option.zlevel, + z: this._option.z, + z2: this._option.z2, + ...this._transformation(), + shape: { + points: [[x, y - 4], [x + 1, y + 1], [x, y], [x - 1, y + 1], [x, y - 4]], + smooth: 0 + } + }); + arrows.setStyle({ ...style.globalStyle, ...yAxis.axisTick.style}); + this.add(arrows); + } + if (yAxis.name) { + const label = new graphic.Text({ + zlevel: this._option.zlevel, + z: this._option.z, + z2: this._option.z2, + ...this._transformation(), + style: { + textVerticalAlign: 'middle', + textAlign: 'left', + text: yAxis.name, + fontSize: 5, + x: shape.x + yAxis.nameGap.left, + y: shape.y - shape.yLength, + textFill: { ...style.globalStyle, ...yAxis.axisTick.style} + } + }); + this.add(label); + } + const scale = (yAxis.data.length - 1) * yAxis.axisTick.splitNumber; + const dataNum = scale + yAxis.boundaryGap; + const num = shape.yLength / dataNum; + const x = shape.x; + const y = shape.y; + let dataIndex = 0; + for (let index = 0; index < dataNum; index++) { + if (yAxis.axisTick.show) { + const spliceLine = new graphic.Line({ + zlevel: this._option.zlevel, + z: this._option.z, + z2: this._option.z2, + ...this._transformation(), + shape: { + x1: x, + y1: y - (num * (index + 1)), + x2: x + 2, + y2: y - (num * (index + 1)) + } + }); + if (index <= scale) { + spliceLine.setStyle({ ...style.globalStyle, ...yAxis.axisTick.style }); + } else { + spliceLine.setStyle({ lineWidth: 0 }); + } + this.add(spliceLine); + } + + if (yAxis.axisLabel.show && + yAxis.axisTick.splitNumber && ( + index % yAxis.axisTick.splitNumber) == 0) { + const label = new graphic.Text({ + zlevel: this._option.zlevel, + z: this._option.z, + z2: this._option.z2, + ...this._transformation(), + style: { + textVerticalAlign: 'middle', + textAlign: 'right', + text: yAxis.data[dataIndex], + fontSize: 5, + x: x - yAxis.axisLabel.distance, + y: y - (num * (index + 1)), + fill: { ...style.globalStyle, ...yAxis.axisTick.style } + } + }); + this.add(label); + dataIndex++; + } + } + } + _createData(option) { + const series = option.style.series; + switch (series.type) { + case 'line': return this.lineView.render(option); + } + } + + _transformation() { + var parent = this.parent||{}; + var origin = parent._origin||null; + var rotation = parent._rotation||null; + var scale = parent._scale||[1, 1]; + return { origin, rotation, scale }; + } + + _traverse(target, attr) { + for (var key in attr) { + if (!(attr[key] instanceof Object) || !attr[key]) { + target[key] = attr[key]; + } else { + this._traverse(target[key], attr[key]); + } + } + } + + setShape(objs) { + this._traverse(this._option.shape, objs); + this.render(); + } + + setStyle(objs) { + this._traverse(this._option.style, objs); + this.render(); + } + + dragging(e) { + this.traverse(el => { + if (el instanceof graphic.Text) { + el.setStyle({ + x: el.style.x + e.dx, + y: el.style.y + e.dy + }); + } else if (el instanceof graphic.Line) { + el.setShape({ + x1: el.shape.x1 + e.dx, + y1: el.shape.y1 + e.dy, + x2: el.shape.x2 + e.dx, + y2: el.shape.y2 + e.dy + }); + } else if (el instanceof graphic.Polygon) { + el.setShape({ + points: el.shape.points.map(it => { return [it[0]+e.dx, it[1]+e.dy]; }) + }); + } + }, this); + } +} diff --git a/src/iscs_new/graph/shape/Coordinate/lineView.js b/src/iscs_new/graph/shape/Coordinate/lineView.js new file mode 100644 index 000000000..459a9797c --- /dev/null +++ b/src/iscs_new/graph/shape/Coordinate/lineView.js @@ -0,0 +1,39 @@ +import * as graphic from '../../graphic'; + +export default class LineView { + constructor(coordinate) { + this.coordinate = coordinate; + } + + render(option) { + const {series, xAxis, yAxis, globalStyle} = option.style; + if (series.type == 'line') { + const shape = option.shape; + const dataList = []; + const scalex = (xAxis.data.length - 1) * xAxis.axisTick.splitNumber; + const dataNumx = scalex + xAxis.boundaryGap; + const numx = (shape.xLength / dataNumx); + const scaley = (yAxis.data.length - 1) * yAxis.axisTick.splitNumber; + const dataNumy = scaley + yAxis.boundaryGap; + const numy = shape.yLength / dataNumy; + const seriesStyle = series.style; + series.data.forEach(point => { + const data = [shape.x + (numx * ((point[0] * xAxis.axisTick.splitNumber) + 1)), shape.y - (numy * (point[1] + 1))]; + dataList.push(data); + }); + + const line = new graphic.Polygon({ + zlevel: option.zlevel, + z: option.z, + z2: option.z2, + ...this.coordinate._transformation(), + shape: { + points: dataList, + smooth: 0 + } + }); + line.setStyle({ ...globalStyle, ...seriesStyle }); + this.coordinate.add(line); + } + } +} diff --git a/src/iscs_new/graph/shape/CurvedScale/curvedScale.js b/src/iscs_new/graph/shape/CurvedScale/curvedScale.js new file mode 100644 index 000000000..f756eb848 --- /dev/null +++ b/src/iscs_new/graph/shape/CurvedScale/curvedScale.js @@ -0,0 +1,457 @@ +import * as graphic from '../../graphic'; + +export default class CurvedScale extends graphic.Group { + constructor(option) { + super(); + + this._option = { + zlevel: option.zlevel || 0, + z: option.z || 0, + z2: option.z2 || 0, + cursor: option.cursor||null, + silent: option.silent||false, + shape: { + cx: 0, + cy: 0, + r: 50, + min: 0, + max: 100, + startAngle: 0, + endAngle: Math.PI, + splitNumber: 10, + clockwise: false, + value: 0, + ...option.shape + }, + style: { + axisLine: { + show: true, + lineStyle: { + color: [[0.2, '#91c7ae'], [0.8, '#63869e'], [1, '#c23531']], + width: 2, + shadowColor: '#fff', + shadowBlur: 10 + }, + ...option.style.axisLine + }, + splitLine: { + show: true, + length: 30, + lineStyle: { + width: 2, + stroke: 'auto' + }, + ...option.style.splitLine + }, + axisTick: { + show: true, + splitNumber: 5, + length: 8, + lineStyle: { + width: 1, + stroke: 'auto', + shadowColor: '#fff', + shadowBlur: 10 + }, + ...option.style.axisTick + }, + axisLabel: { + show: true, + distance: 5, + textStyle: { + fontSize: 18, + textFill: 'auto' + }, + ...option.style.axisLabel + }, + pointer: { + show: true, + width: 8, + length: '80%', + fill: 'auto', + ...option.style.pointer + } + } + }; + + this.render(); + } + + render() { + this.removeAll(); + + var axisLine = this._option.style.axisLine; + + var showAxis = axisLine.show; + var axisLineStyle = axisLine.lineStyle; + var axisColorList = axisLineStyle.color; + var axisLineWidth = axisLineStyle.width; + + var shape = this._option.shape; + var clockwise = shape.clockwise; + var startAngle = -shape.startAngle / 180 * Math.PI; + var endAngle = -shape.endAngle / 180 * Math.PI; + + var angleRangeSpan = (endAngle - startAngle) % (Math.PI * 2); + var prevEndAngle = startAngle; + + if (showAxis) { + for (var i = 0; i < axisColorList.length; i++) { + var percent = Math.min(Math.max(axisColorList[i][0], 0), 1); + var angle = startAngle + angleRangeSpan * percent; + var sector = new graphic.Sector({ + zlevel: this._option.zlevel, + z: this._option.z, + z2: this._option.z2, + cursor: this._option.cursor, + silent: this._option.silent, + ...this._transformation(), + shape: { + startAngle: prevEndAngle, + endAngle: angle, + cx: shape.cx, + cy: shape.cy, + clockwise: false, + r0: shape.r - axisLineWidth, + r: shape.r + } + }); + + sector.setStyle({ + fill: axisColorList[i][1], + color: axisLine.color, + borderWidth: axisLine.borderWidth, + borderColor: axisLine.borderColor + }); + + this.add(sector); + prevEndAngle = angle; + } + } + + var getColor = function (percent) { + percent = clockwise? percent : 1 - percent; + if (percent <= 0) { + return axisColorList[0][1]; + } + for (var i = 0; i < axisColorList.length; i++) { + if (axisColorList[i][0] >= percent && + (i === 0 ? 0 : axisColorList[i - 1][0]) < percent + ) { + return axisColorList[i][1]; + } + } + + return axisColorList[i - 1][1]; + }; + + if (!clockwise) { + [startAngle, endAngle] = [endAngle, startAngle]; + } + + this._createTicks({startAngle, endAngle, getColor}); + + this._createPointer({startAngle, endAngle, getColor}); + } + + _createTicks({startAngle, endAngle, getColor}) { + var shape = this._option.shape; + var x = shape.cx; + var y = shape.cy; + var r = shape.r; + var minVal = parseFloat(shape.min); + var maxVal = parseFloat(shape.max); + var splitNumber = shape.splitNumber; + + var axisLabel = this._option.style.axisLabel; + var axisLabelShow = axisLabel.show; + var axisLabelDistance = axisLabel.distance; + var axisLabelStyle = axisLabel.textStyle; + + var axisTick = this._option.style.axisTick; + var axisTickLen = parsePercent(axisTick.length, r); + var axisTickLineStyle = axisTick.lineStyle; + var axisTickShow = axisTick.show; + + var subSplitNumber = axisTick.splitNumber; + + var splitLine = this._option.style.splitLine; + var splitLineLen = parsePercent(splitLine.length, r); + var splitLineStyle = splitLine.lineStyle; + var splitLineShow = splitLine.show; + + var angle = startAngle; + var step = (endAngle - startAngle) / splitNumber; + var subStep = step / subSplitNumber; + + for (var i = 0; i <= splitNumber; i++) { + const unitX = Math.cos(angle); + const unitY = Math.sin(angle); + + if (splitLineShow) { + const line = new graphic.Line({ + zlevel: this._option.zlevel, + z: this._option.z, + z2: this._option.z2, + cursor: this._option.cursor, + silent: this._option.silent, + ...this._transformation(), + shape: { + x1: unitX * r + x, + y1: unitY * r + y, + x2: unitX * (r - splitLineLen) + x, + y2: unitY * (r - splitLineLen) + y + }, + style: splitLineStyle + }); + + if (splitLineStyle.stroke === 'auto') { + line.setStyle({ stroke: getColor(i / splitNumber) }); + } + + this.add(line); + } + + if (axisLabelShow) { + var label = new graphic.Text({ + zlevel: this._option.zlevel, + z: this._option.z, + z2: this._option.z2, + cursor: this._option.cursor, + silent: this._option.silent, + ...this._transformation(), + style: { + ...axisLabelStyle, + text: formatLabel( + round(i / splitNumber * (maxVal - minVal) + minVal), + axisLabel.formatter || null + ), + x: unitX * (r - splitLineLen - axisLabelDistance) + x, + y: unitY * (r - splitLineLen - axisLabelDistance) + y, + textVerticalAlign: unitY < -0.4 ? 'top' : (unitY > 0.4 ? 'bottom' : 'middle'), + textAlign: unitX < -0.4 ? 'left' : (unitX > 0.4 ? 'right' : 'center') + } + }); + + if (axisLabelStyle.textFill == 'auto') { + label.setStyle({ textFill: getColor(i / splitNumber) }); + } + + this.add(label); + } + + if (axisTickShow && i !== splitNumber) { + for (var j = 0; j <= subSplitNumber; j++) { + const unitX = Math.cos(angle); + const unitY = Math.sin(angle); + const tickLine = new graphic.Line({ + zlevel: this._option.zlevel, + z: this._option.z, + z2: this._option.z2, + cursor: this._option.cursor, + silent: this._option.silent, + ...this._transformation(), + shape: { + x1: unitX * r + x, + y1: unitY * r + y, + x2: unitX * (r - axisTickLen) + x, + y2: unitY * (r - axisTickLen) + y + }, + style: axisTickLineStyle + }); + + if (axisTickLineStyle.stroke === 'auto') { + tickLine.setStyle({ stroke: getColor((i + j / subSplitNumber) / splitNumber) }); + } + + this.add(tickLine); + angle += subStep; + } + angle -= subStep; + } else { + angle += step; + } + } + } + + _createPointer({startAngle, endAngle, getColor}) { + var shape = this._option.shape; + var minVal = parseFloat(shape.min); + var maxVal = parseFloat(shape.max); + var value = parseFloat(shape.value); + var pointerStyle = this._option.style.pointer; + var pointerShow = pointerStyle.show; + var pointerLength = pointerStyle.length; + var pointerWidth = pointerStyle.width; + + if (pointerShow) { + var valueExtent = [minVal, maxVal]; + var angleExtent = [startAngle, endAngle]; + + var pointer = new graphic.Pointer({ + zlevel: this._option.zlevel, + z: this._option.z, + z2: this._option.z2, + cursor: this._option.cursor, + silent: this._option.silent, + ...this._transformation(), + shape: { + x: shape.cx, + y: shape.cy, + width: parsePercent(pointerWidth, shape.r), + r: parsePercent(pointerLength, shape.r), + angle: linearMap(value, valueExtent, angleExtent, true) + }, + style: pointerStyle + }); + + if (pointer.style.fill === 'auto') { + pointer.setStyle('fill', getColor(linearMap(value, valueExtent, [0, 1], true))); + } + + this.add(pointer); + } + } + + _traverse(target, attr) { + for (var key in attr) { + if (!(attr[key] instanceof Object) || !attr[key]) { + target[key] = attr[key]; + } else { + this._traverse(target[key], attr[key]); + } + } + } + + _transformation() { + var parent = this.parent||{}; + var origin = parent._origin||null; + var rotation = parent._rotation||null; + var scale = parent._scale||[1, 1]; + return { origin, rotation, scale }; + } + + dragging(e) { + this.traverse(el => { + if (el instanceof graphic.Text) { + el.setStyle({ + x: el.style.x + e.dx, + y: el.style.y + e.dy + }); + } else if (el instanceof graphic.Sector) { + el.setShape({ + cx: el.shape.cx + e.dx, + cy: el.shape.cy + e.dy + }); + + } else if (el instanceof graphic.Line) { + el.setShape({ + x1: el.shape.x1 + e.dx, + y1: el.shape.y1 + e.dy, + x2: el.shape.x2 + e.dx, + y2: el.shape.y2 + e.dy + }); + + } else if (el instanceof graphic.Pointer) { + el.setShape({ + x: el.shape.x + e.dx, + y: el.shape.y + e.dy + }); + } + }, this); + } + + setShape(objs) { + this._traverse(this._option.shape, objs); + this.render(); + } + + setStyle(objs) { + this._traverse(this._option.style, objs); + this.render(); + } +} + +function formatLabel(label, labelFormatter) { + if (labelFormatter) { + if (typeof labelFormatter === 'string') { + label = labelFormatter.replace('{value}', label != null ? label : ''); + } else if (typeof labelFormatter === 'function') { + label = labelFormatter(label); + } + } + + return label; +} + +function round(x, precision, returnStr) { + if (precision == null) { + precision = 10; + } + + precision = Math.min(Math.max(0, precision), 20); + x = (+x).toFixed(precision); + return returnStr ? x : +x; +} + +function parsePercent(percent, all) { + switch (percent) { + case 'center': + case 'middle': + percent = '50%'; + break; + case 'left': + case 'top': + percent = '0%'; + break; + case 'right': + case 'bottom': + percent = '100%'; + break; + } + if (typeof percent === 'string') { + if (percent.trim().match(/%$/)) { + return parseFloat(percent) / 100 * all; + } + + return parseFloat(percent); + } + + return percent == null ? NaN : +percent; +} + +function linearMap(val, domain, range, clamp) { + var subDomain = domain[1] - domain[0]; + var subRange = range[1] - range[0]; + + if (subDomain === 0) { + return subRange === 0 + ? range[0] + : (range[0] + range[1]) / 2; + } + + if (clamp) { + if (subDomain > 0) { + if (val <= domain[0]) { + return range[0]; + } else if (val >= domain[1]) { + return range[1]; + } + } else { + if (val >= domain[0]) { + return range[0]; + } else if (val <= domain[1]) { + return range[1]; + } + } + } else { + if (val === domain[0]) { + return range[0]; + } + if (val === domain[1]) { + return range[1]; + } + } + + return (val - domain[0]) / subDomain * subRange + range[0]; +} diff --git a/src/iscs_new/graph/shape/Digit.js b/src/iscs_new/graph/shape/Digit.js new file mode 100644 index 000000000..c4ff02852 --- /dev/null +++ b/src/iscs_new/graph/shape/Digit.js @@ -0,0 +1,115 @@ +import Path from 'zrender/src/graphic/Path'; +import * as polyHelper from 'zrender/src/graphic/helper/poly'; +/** + * - 1 + * | | 4 5 + * - 2 + * | | 6 7 + * - 3 + */ +export default Path.extend({ + + type: 'Digit', + + dightMap: { + '0': [1, 3, 4, 5, 6, 7], + '1': [5, 7], + '2': [1, 2, 3, 5, 6], + '3': [1, 2, 3, 5, 7], + '4': [2, 4, 5, 7], + '5': [1, 2, 3, 4, 7], + '6': [1, 2, 3, 4, 6, 7], + '7': [1, 5, 7], + '8': [1, 2, 3, 4, 5, 6, 7], + '9': [1, 2, 3, 4, 5, 7], + '.': [10], + '°': [1, 2, 4, 5], + '*': [1, 2, 4, 5], + 'C': [1, 3, 4, 6], + 'L': [3, 4, 6] + }, + shape: { + x: 0, + y: 0, + l: 4, + r: 2, + v: '8', + dx: 0.5, + dy: 0 + }, + + getVPoints(shape, dx, dy) { + return [ + [shape.x+dx, shape.y+shape.r*1.5+dy], + [shape.x+shape.r+dx, shape.y+shape.r*2.5+dy], + [shape.x+shape.r+dx, shape.y+shape.r*2.5+shape.l+dy], + [shape.x+dx, shape.y+shape.r*3.5+shape.l+dy], + [shape.x-shape.r+dx, shape.y+shape.r*2.5+shape.l+dy], + [shape.x-shape.r+dx, shape.y+shape.r*2.5+dy] + ]; + }, + + getLPoints(shape, dx, dy) { + return [ + [shape.x+dx, shape.y+shape.r+dy], + [shape.x+shape.r+dx, shape.y+dy], + [shape.x+shape.r+shape.l+dx, shape.y+dy], + [shape.x+shape.r*2+shape.l+dx, shape.y+shape.r+dy], + [shape.x+shape.r+shape.l+dx, shape.y+shape.r*2+dy], + [shape.x+shape.r+dx, shape.y+shape.r*2+dy] + ]; + }, + + buildPath: function (ctx, shape) { + const list = this.dightMap[shape.v]||[]; + if (list.includes(1)) { + const model = { + points: this.getLPoints(shape, 0, 0) + }; + polyHelper.buildPath(ctx, model, true); + } + + if (list.includes(2)) { + const model = { + points: this.getLPoints(shape, 0, shape.l+shape.r*3+shape.dy*2) + }; + polyHelper.buildPath(ctx, model, true); + } + + if (list.includes(3)) { + const model = { + points: this.getLPoints(shape, 0, shape.l*2+shape.r*6+shape.dy*2) + }; + polyHelper.buildPath(ctx, model, true); + } + + if (list.includes(4)) { + const model = { + points: this.getVPoints(shape, -shape.dx, +shape.dy) + }; + polyHelper.buildPath(ctx, model, true); + } + + if (list.includes(5)) { + const model = { + points: this.getVPoints(shape, shape.l+shape.r*2+shape.dx, +shape.dy) + }; + polyHelper.buildPath(ctx, model, true); + } + + if (list.includes(6)) { + const model = { + points: this.getVPoints(shape, -shape.dx, shape.l+shape.r*3+shape.dy*2) + }; + polyHelper.buildPath(ctx, model, true); + } + + if (list.includes(7)) { + const model = { + points: this.getVPoints(shape, shape.l+shape.r*2+shape.dx, shape.l+shape.r*3+shape.dy*2) + }; + polyHelper.buildPath(ctx, model, true); + } + + } +}); diff --git a/src/iscs_new/graph/shape/Hover.js b/src/iscs_new/graph/shape/Hover.js new file mode 100644 index 000000000..88d4e027d --- /dev/null +++ b/src/iscs_new/graph/shape/Hover.js @@ -0,0 +1,44 @@ +import Path from 'zrender/src/graphic/Path'; + +export default Path.extend({ + + type: 'hover', + + shape: { + padding: 2, + x: 0, + y: 0, + with: 0, + height: 0 + }, + + style: { + stroke: '#fff', + fill: null + }, + + buildPath: function (ctx, shape) { + var x = shape.x - this.shape.padding; + var y = shape.y - this.shape.padding; + var w = shape.width + this.shape.padding * 2; + var h = shape.height + this.shape.padding * 2; + var ph = Math.min(h, w) / 4; + var pw = Math.min(h, w) / 4; + + ctx.moveTo(x, y + ph); + ctx.lineTo(x, y); + ctx.lineTo(x + pw, y); + + ctx.moveTo(x + w - pw, y); + ctx.lineTo(x + w, y); + ctx.lineTo(x + w, y + ph); + + ctx.moveTo(x, y + h - ph); + ctx.lineTo(x, y + h); + ctx.lineTo(x + pw, y + h); + + ctx.moveTo(x + w, y + h - ph); + ctx.lineTo(x + w, y + h); + ctx.lineTo(x + w - pw, y + h); + } +}); diff --git a/src/iscs_new/graph/shape/LinearScale/linearScale.js b/src/iscs_new/graph/shape/LinearScale/linearScale.js new file mode 100644 index 000000000..80d342751 --- /dev/null +++ b/src/iscs_new/graph/shape/LinearScale/linearScale.js @@ -0,0 +1,423 @@ +import * as graphic from '../../graphic'; +import * as color from 'zrender/src/tool/color'; + +export default class LinearScale extends graphic.Group { + constructor(option) { + super(); + + this._option = { + zlevel: option.zlevel || 0, + z: option.z || 0, + z2: option.z2 || 0, + cursor: option.cursor||null, + silent: option.silent||false, + shape: { + x: 0, + y: 0, + min: 0, + max: 100, + tickStart: 0, + tickEnd: 200, + angle: Math.PI, + splitNumber: 10, + value: 0, + ...option.shape + }, + style: { + axisLine: { + show: true, + lineStyle: { + color: [[0.2, '#91c7ae'], [0.8, '#63869e'], [1, '#c23531']], + lineWidth: 3 + }, + ...option.style.axisLine + }, + splitLine: { + show: true, + length: 8, + distance: -6.5, + lineStyle: { + width: 1, + stroke: 'auto' + }, + ...option.style.splitLine + }, + axisTick: { + show: true, + length: 3, + distance: -4.5, + splitNumber: 5, + lineStyle: { + width: 1, + stroke: 'auto', + shadowColor: '#fff', + shadowBlur: 10 + }, + ...option.style.axisTick + }, + axisLabel: { + show: true, + distance: -25, + textStyle: { + fontSize: 6, + textFill: 'auto' + }, + ...option.style.axisLabel + }, + pointer: { + show: true, + lineWidth: 3, + stroke: 'auto', + lineCap: 'round', + ...option.style.pointer + } + } + }; + + this.render(); + } + + render() { + this.removeAll(); + + var axisLine = this._option.style.axisLine; + + var showAxis = axisLine.show; + var axisLineStyle = axisLine.lineStyle; + var axisColorList = axisLineStyle.color; + var axisLineWidth = axisLineStyle.lineWidth; + + var shape = this._option.shape; + var angle = shape.angle; + var minTick = shape.tickStart; + var maxTick = shape.tickEnd; + + var lineRangeSpan = (maxTick - minTick); + var prevEndLine = 0; + var x = shape.x; + var y = shape.y; + + if (showAxis) { + for (var i = 0; i < axisColorList.length; i++) { + var percent = Math.min(Math.max(axisColorList[i][0], 0), 1); + var lineLen = lineRangeSpan * percent - prevEndLine; + var px = lineLen * Math.cos(angle); + var py = lineLen * Math.sin(angle); + + var line = new graphic.Line({ + zlevel: this._option.zlevel, + z: this._option.z, + z2: this._option.z2, + cursor: this._option.cursor, + silent: this._option.silent, + ...this._transformation(), + shape: { + x1: x, + y1: y, + x2: x + px, + y2: y + py + } + }); + + line.setStyle({ stroke: axisColorList[i][1], lineWidth: axisLineWidth }); + + this.add(line); + x += px; + y += py; + prevEndLine = lineRangeSpan * percent; + } + } + + var getColor = function (percent) { + if (percent <= 0) { + return axisColorList[0][1]; + } + for (var i = 0; i < axisColorList.length; i++) { + if (axisColorList[i][0] >= percent && + (i === 0 ? 0 : axisColorList[i - 1][0]) < percent + ) { + return axisColorList[i][1]; + } + } + + return axisColorList[i - 1][1]; + }; + + this._createTicks({getColor}); + + this._createPointer({getColor}); + } + + _createTicks({getColor}) { + var shape = this._option.shape; + var x = shape.x; + var y = shape.y; + var minTick = shape.tickStart; + var maxTick = shape.tickEnd; + var minVal = parseFloat(shape.min); + var maxVal = parseFloat(shape.max); + var splitNumber = shape.splitNumber; + var angle = shape.angle; + + var axisLabel = this._option.style.axisLabel; + var axisLabelShow = axisLabel.show; + var axisLabelDistance = axisLabel.distance; + var axisLabelStyle = axisLabel.textStyle; + + var axisTick = this._option.style.axisTick; + var axisTickShow = axisTick.show; + var axisTickLen = axisTick.length; + var axisTickDistance = axisTick.distance; + var axisTickLineStyle = axisTick.lineStyle; + + var subSplitNumber = axisTick.splitNumber; + + var splitLine = this._option.style.splitLine; + var splitLineShow = splitLine.show; + var splitLineLen = splitLine.length; + var splitLineDistance = splitLine.distance; + var splitLineStyle = splitLine.lineStyle; + + var step = (maxTick - minTick) / splitNumber; + var subStep = step / subSplitNumber; + + for (var i = 0; i <= splitNumber; i++) { + const unitX = Math.cos(angle); + const unitY = Math.sin(angle); + + if (splitLineShow) { + const line = new graphic.Line({ + zlevel: this._option.zlevel, + z: this._option.z, + z2: this._option.z2, + cursor: this._option.cursor, + silent: this._option.silent, + ...this._transformation(), + shape: { + x1: x + unitX * step * i + unitY * (splitLineLen + splitLineDistance), + y1: y + unitY * step * i - unitX * (splitLineLen + splitLineDistance), + x2: x + unitX * step * i - unitY * (splitLineLen - splitLineDistance), + y2: y + unitY * step * i + unitX * (splitLineLen - splitLineDistance) + }, + style: splitLineStyle + }); + + if (splitLineStyle.stroke === 'auto') { + line.setStyle({ stroke: getColor(i / splitNumber) }); + } + + this.add(line); + } + + if (axisLabelShow) { + const label = new graphic.Text({ + zlevel: this._option.zlevel, + z: this._option.z, + z2: this._option.z2, + cursor: this._option.cursor, + silent: this._option.silent, + ...this._transformation(), + style: { + textVerticalAlign: unitX < -0.4 ? 'bottom' : (unitX > 0.4 ? 'top' : 'middle'), + textAlign: unitY < -0.4 ? 'left' : (unitY > 0.4 ? 'right' : 'center'), + ...axisLabelStyle, + text: formatLabel( + round(i / splitNumber * (maxVal - minVal) + minVal), + axisLabel.formatter || null + ), + x: x + unitX * step * i + unitY * (splitLineLen + axisLabelDistance), + y: y + unitY * step * i - unitX * (splitLineLen + axisLabelDistance) + } + }); + + if (axisLabelStyle.textFill === 'auto') { + label.setStyle({ textFill: getColor(i / splitNumber) }); + } + + this.add(label); + } + + if (axisTickShow && i !== splitNumber) { + for (var j = 1; j < subSplitNumber; j++) { + const unitX = Math.cos(angle); + const unitY = Math.sin(angle); + + const tickLine = new graphic.Line({ + zlevel: this._option.zlevel, + z: this._option.z, + z2: this._option.z2, + cursor: this._option.cursor, + silent: this._option.silent, + ...this._transformation(), + shape: { + x1: x + unitX * (step * i + subStep * j) + unitY * (axisTickLen + axisTickDistance), + y1: y + unitY * (step * i + subStep * j) - unitX * (axisTickLen + axisTickDistance), + x2: x + unitX * (step * i + subStep * j) - unitY * (axisTickLen - axisTickDistance), + y2: y + unitY * (step * i + subStep * j) + unitX * (axisTickLen - axisTickDistance) + }, + style: axisTickLineStyle + }); + + if (axisTickLineStyle.stroke === 'auto') { + tickLine.setStyle({ stroke: getColor((i + j / subSplitNumber) / splitNumber) }); + } + + this.add(tickLine); + } + } + } + } + + _createPointer({getColor}) { + var shape = this._option.shape; + var x = shape.x; + var y = shape.y; + var minVal = parseFloat(shape.min); + var maxVal = parseFloat(shape.max); + var value = parseFloat(shape.value) || 0; + var minTick = shape.tickStart; + var maxTick = shape.tickEnd; + var angle = shape.angle; + var pointerStyle = this._option.style.pointer; + var pointerShow = pointerStyle.show; + var pointerLineWidth = pointerStyle.lineWidth; + var pointerLineCap = pointerStyle.lineCap; + + if (pointerShow) { + var valueExtent = [minVal, maxVal]; + var angleExtent = [minTick, maxTick]; + + var unitX = Math.cos(angle); + var unitY = Math.sin(angle); + + var valueLen = linearMap(value, valueExtent, angleExtent, true); + var specialStyleList = ['round', 'square']; + + var pointer = new graphic.Line({ + zlevel: this._option.zlevel, + z: this._option.z, + z2: this._option.z2, + cursor: this._option.cursor, + silent: this._option.silent, + ...this._transformation(), + shape: { + x1: x, + y1: y, + x2: x + unitX * (valueLen - (specialStyleList.includes(pointerLineCap)? pointerLineWidth/2:0)), + y2: y + unitY * (valueLen - (specialStyleList.includes(pointerLineCap)? pointerLineWidth/2:0)) + }, + style: pointerStyle + }); + + if (pointerStyle.stroke === 'auto') { + pointer.setStyle('stroke', color.lift(getColor(linearMap(value, valueExtent, [0, 1], true)), 0.3)); + } + + this.add(pointer); + } + } + + _traverse(target, attr) { + for (var key in attr) { + if (!(attr[key] instanceof Object) || !attr[key]) { + target[key] = attr[key]; + } else { + this._traverse(target[key], attr[key]); + } + } + } + + _transformation() { + var parent = this.parent||{}; + var origin = parent._origin||null; + var rotation = parent._rotation||null; + var scale = parent._scale||[1, 1]; + return { origin, rotation, scale }; + } + + dragging(e) { + this.traverse(el => { + if (el instanceof graphic.Text) { + el.setStyle({ + x: el.style.x + e.dx, + y: el.style.y + e.dy + }); + } else if (el instanceof graphic.Line) { + el.setShape({ + x1: el.shape.x1 + e.dx, + y1: el.shape.y1 + e.dy, + x2: el.shape.x2 + e.dx, + y2: el.shape.y2 + e.dy + }); + } + }, this); + } + + setShape(objs) { + this._traverse(this._option.shape, objs); + this.render(); + } + + setStyle(objs) { + this._traverse(this._option.style, objs); + this.render(); + } +} + +function formatLabel(label, labelFormatter) { + if (labelFormatter) { + if (typeof labelFormatter === 'string') { + label = labelFormatter.replace('{value}', label != null ? label : ''); + } else if (typeof labelFormatter === 'function') { + label = labelFormatter(label); + } + } + + return label; +} + +function round(x, precision, returnStr) { + if (precision == null) { + precision = 10; + } + + precision = Math.min(Math.max(0, precision), 20); + x = (+x).toFixed(precision); + return returnStr ? x : +x; +} + +function linearMap(val, domain, range, clamp) { + var subDomain = domain[1] - domain[0]; + var subRange = range[1] - range[0]; + + if (subDomain === 0) { + return subRange === 0 + ? range[0] + : (range[0] + range[1]) / 2; + } + + if (clamp) { + if (subDomain > 0) { + if (val <= domain[0]) { + return range[0]; + } else if (val >= domain[1]) { + return range[1]; + } + } else { + if (val >= domain[0]) { + return range[0]; + } else if (val <= domain[1]) { + return range[1]; + } + } + } else { + if (val === domain[0]) { + return range[0]; + } + if (val === domain[1]) { + return range[1]; + } + } + + return (val - domain[0]) / subDomain * subRange + range[0]; +} diff --git a/src/iscs_new/graph/shape/Pointer.js b/src/iscs_new/graph/shape/Pointer.js new file mode 100644 index 000000000..c14e205b4 --- /dev/null +++ b/src/iscs_new/graph/shape/Pointer.js @@ -0,0 +1,45 @@ +import Path from 'zrender/src/graphic/Path'; + +export default Path.extend({ + + type: 'Pointer', + + shape: { + angle: 0, + + width: 10, + + r: 10, + + x: 0, + + y: 0 + }, + + buildPath: function (ctx, shape) { + var mathCos = Math.cos; + var mathSin = Math.sin; + + var r = shape.r; + var width = shape.width; + var angle = shape.angle; + var x = shape.x - mathCos(angle) * width * (width >= r / 3 ? 1 : 2); + var y = shape.y - mathSin(angle) * width * (width >= r / 3 ? 1 : 2); + + angle = shape.angle - Math.PI / 2; + ctx.moveTo(x, y); + ctx.lineTo( + shape.x + mathCos(angle) * width, + shape.y + mathSin(angle) * width + ); + ctx.lineTo( + shape.x + mathCos(shape.angle) * r, + shape.y + mathSin(shape.angle) * r + ); + ctx.lineTo( + shape.x - mathCos(angle) * width, + shape.y - mathSin(angle) * width + ); + ctx.lineTo(x, y); + } +}); diff --git a/src/iscs_new/graph/shape/Sausage.js b/src/iscs_new/graph/shape/Sausage.js new file mode 100644 index 000000000..d2c8d141c --- /dev/null +++ b/src/iscs_new/graph/shape/Sausage.js @@ -0,0 +1,66 @@ +import Path from 'zrender/src/graphic/Path'; +/** + * Sausage: similar to sector, but have half circle on both sides + * @public + */ +export default Path.extend({ + + type: 'sausage', + + shape: { + cx: 0, + cy: 0, + r0: 0, + r: 0, + startAngle: 0, + endAngle: Math.PI * 2, + clockwise: true + }, + + buildPath: function (ctx, shape) { + var x = shape.cx; + var y = shape.cy; + var r0 = Math.max(shape.r0 || 0, 0); + var r = Math.max(shape.r, 0); + var dr = (r - r0) * 0.5; + var rCenter = r0 + dr; + var startAngle = shape.startAngle; + var endAngle = shape.endAngle; + var clockwise = shape.clockwise; + + var unitStartX = Math.cos(startAngle); + var unitStartY = Math.sin(startAngle); + var unitEndX = Math.cos(endAngle); + var unitEndY = Math.sin(endAngle); + + var lessThanCircle = clockwise + ? endAngle - startAngle < Math.PI * 2 + : startAngle - endAngle < Math.PI * 2; + + if (lessThanCircle) { + ctx.moveTo(unitStartX * r0 + x, unitStartY * r0 + y); + + ctx.arc( + unitStartX * rCenter + x, unitStartY * rCenter + y, dr, + -Math.PI + startAngle, startAngle, !clockwise + ); + } + + ctx.arc(x, y, r, startAngle, endAngle, !clockwise); + + ctx.moveTo(unitEndX * r + x, unitEndY * r + y); + + ctx.arc( + unitEndX * rCenter + x, unitEndY * rCenter + y, dr, + endAngle - Math.PI * 2, endAngle - Math.PI, !clockwise + ); + + if (r0 !== 0) { + ctx.arc(x, y, r0, endAngle, startAngle, clockwise); + + ctx.moveTo(unitStartX * r0 + x, unitEndY * r0 + y); + } + + ctx.closePath(); + } +}); diff --git a/src/iscs_new/graph/shape/Svg.js b/src/iscs_new/graph/shape/Svg.js new file mode 100644 index 000000000..8a49a67d5 --- /dev/null +++ b/src/iscs_new/graph/shape/Svg.js @@ -0,0 +1,26 @@ + +import zrender from 'zrender'; + +export default class Svg extends zrender.Path { + constructor(opts) { + super(zrender.path.createFromString(opts.shape.path, { + ...opts, + type: 'Svg' + })); + + super.attr('position', [opts.shape.x, opts.shape.y]); + } + + setShape(shape) { + super.setShape(shape); + this.attr('position', [shape.x, shape.y]); + } + + setStyle(style) { + super.setStyle(style); + } + + attr(key, value) { + super.attr(key, value); + } +} diff --git a/src/iscs_new/graph/shape/Table/cell.js b/src/iscs_new/graph/shape/Table/cell.js new file mode 100644 index 000000000..272fdf637 --- /dev/null +++ b/src/iscs_new/graph/shape/Table/cell.js @@ -0,0 +1,275 @@ +import * as graphic from '../../../graph/graphic'; +import Button from '@/assets/map/button.png'; + +const cellStyle = { + text: { + fontSize: 14, + fontWeight: 'normal', + fontFamily: '微软雅黑,Arial', + textFill: '#000', + textAlign: 'center', + textVerticalAlign: 'middle', + textPadding: null, + rich: { + sup: { + textVerticalAlign: 'top', + fontSize: 8 + }, + sub: { + textVerticalAlign: 'bottom', + fontSize: 8 + } + } + }, + order: { + r: 10, + lineWidth: 1, + stroke: '#F0F0f0', + fill: '#EFA5FF', + fontSize: 24, + fontWeight: 'bold', + fontFamily: '微软雅黑,Arial', + textFill: '#000', + textAlign: 'center', + textVerticalAlign: 'middle', + textPadding: null, + rich: { + sup: { + textVerticalAlign: 'top', + fontSize: 12 + }, + sub: { + textVerticalAlign: 'bottom', + fontSize: 12 + } + } + }, + button: { + url: Button, + width: 60, + height: 25, + fill: '#ffffff', + fontSize: 24, + fontWeight: 'bold', + fontFamily: '微软雅黑,Arial', + textFill: '#000', + textAlign: 'center', + textVerticalAlign: 'middle', + textPadding: null, + rich: { + sup: { + textVerticalAlign: 'top', + fontSize: 12 + }, + sub: { + textVerticalAlign: 'bottom', + fontSize: 12 + } + } + } +}; + +export default class Cell extends graphic.Group { + constructor(option) { + super(); + this._elMap = { + text: null, + order: null, + circle: null, + button: null + }; + this._option = { + zlevel: option.zlevel, + z: option.z, + z2: option.z2, + cursor: option.cursor, + silent: option.silent, + shape: { + x: 0, + y: 0, + ...option.shape + }, + style: { + ...option.style + } + }; + + this.render(); + } + + render() { + var shape = this._option.shape; + var style = this._option.style; + var x = shape.x; + var y = shape.y; + var w = shape.width; + var h = shape.height; + + switch (style.type) { + case 'order': this._createOrder(shape); break; + case 'text': this._createTextModel(shape); break; + case 'button': this._createButton({ + x: x - w / 2, + y: y - h / 2, + w, + h + }); break; + } + } + + _createTextModel(shape) { + const zlevel = this._option.zlevel; + const z = this._option.z; + const z2 = this._option.z2; + const style = this._option.style; + const cursor = this._option.cursor; + const silent = this._option.silent; + + this._elMap.text = new graphic.Text({ + zlevel: zlevel, + z: z, + z2: z2+1, + cursor, + silent, + style: { + x: shape.x, + y: shape.y, + fontSize: style.fontSize || cellStyle.text.fontSize, + fontWeight: style.fontWeight || cellStyle.text.fontWeight, + fontFamily: style.fontFamily || cellStyle.text.fontFamily, + textFill: style.textFill || cellStyle.text.textFill, + textAlign: style.textAlign || cellStyle.text.textAlign, + textVerticalAlign: style.textVerticalAlign || cellStyle.text.textVerticalAlign, + textPadding: style.textPadding|| cellStyle.text.textPadding, + text: style.text || '', + rich: style.rich || cellStyle.text.rich + } + }); + + this.add(this._elMap.text); + } + + _createOrder(shape) { + const zlevel = this._option.zlevel; + const z = this._option.z; + const z2 = this._option.z2; + const style = this._option.style; + const cursor = this._option.cursor; + const silent = this._option.silent; + + this._elMap.order = new graphic.Circle({ + zlevel: zlevel, + z: z, + z2: z2+1, + cursor, + silent, + shape: { + cx: shape.x, + cy: shape.y, + r: shape.r || cellStyle.order.r + }, + style: { + lineWidth: style.lineWidth || cellStyle.order.lineWidth, + stroke: style.stroke || cellStyle.order.stroke, + fill: style.fill || cellStyle.order.fill + } + }); + + this._elMap.text = new graphic.Text({ + zlevel: zlevel, + z: z, + z2: z2+1, + style: { + x: shape.x, + y: shape.y, + fontSize: style.fontSize || cellStyle.order.fontSize, + fontWeight: style.fontWeight || cellStyle.order.fontWeight, + fontFamily: style.fontFamily || cellStyle.order.fontFamily, + textFill: style.textFill || cellStyle.order.textFill, + textAlign: style.textAlign || cellStyle.order.textAlign, + textVerticalAlign: style.textVerticalAlign || cellStyle.order.textVerticalAlign, + textWidth: style.width || cellStyle.order.width, + textPadding: style.textPadding || cellStyle.order.textPadding, + textBorderWidth: style.textBorderWidth || cellStyle.order.textBorderWidth, + textBorderColor: style.textBorderColor || cellStyle.order.textBorderColor, + textBackgroundColor: cellStyle.order.textBackgroundColor, + rich: style.rich || cellStyle.order.rich, + text: style.text || '' + } + }); + + this.add(this._elMap.order); + this.add(this._elMap.text); + } + + _createButton(shape) { + const zlevel = this._option.zlevel; + const z = this._option.z; + const z2 = this._option.z2; + const style = this._option.style; + const width = style.width || cellStyle.button.width; + const height = style.height ||cellStyle.button.height; + const image = style.url || cellStyle.button.url; + + this._elMap.button = new graphic.Image({ + zlevel: zlevel, + z: z, + z2: z2+1, + style: { + x: shape.x + (shape.w - width)/2, + y: shape.y + (shape.h - height)/2, + width: width, + height: height, + image: image + } + }); + + this._elMap.text = new graphic.Text({ + zlevel: zlevel, + z: z, + z2: z2+1, + position: [shape.w/2, shape.h/2], + style: { + x: shape.x, + y: shape.y, + fontSize: style.fontSize || cellStyle.button.fontSize, + fontWeight: style.fontWeight || cellStyle.button.fontWeight, + fontFamily: style.fontFamily || cellStyle.button.fontFamily, + textFill: style.textFill || cellStyle.button.textFill, + textAlign: style.textAlign || cellStyle.button.textAlign, + textVerticalAlign: style.textVerticalAlign || cellStyle.button.textVerticalAlign, + textWidth: style.textWidth || cellStyle.button.width, + textPadding: style.textPadding || cellStyle.button.textPadding, + textBorderWidth: style.textBorderWidth || cellStyle.button.textBorderWidth, + textBorderColor: style.textBorderColor || cellStyle.button.textBorderColor, + textBackgroundColor: style.textBackgroundColor || cellStyle.button.textBackgroundColor, + rich: style.rich || cellStyle.button.rich, + text: style.text || '' + } + }); + + this.add(this._elMap.button); + this.add(this._elMap.text); + } + + dragging(e) { + this.traverse(el => { + if (el instanceof graphic.Text) { + el.setStyle({ + x: el.style.x + e.dx, + y: el.style.y + e.dy + }); + } else if (el instanceof graphic.Image) { + el.setStyle({ + x: el.style.x + e.dx, + y: el.style.y + e.dy + }); + } else if (el instanceof graphic.Circle) { + el.setShape({ + cx: el.shape.cx + e.dx, + cy: el.shape.cy + e.dy + }); + } + }, this); + } +} diff --git a/src/iscs_new/graph/shape/Table/table.js b/src/iscs_new/graph/shape/Table/table.js new file mode 100644 index 000000000..b9a19a579 --- /dev/null +++ b/src/iscs_new/graph/shape/Table/table.js @@ -0,0 +1,200 @@ +import * as graphic from '../../graphic'; +import Cell from './cell'; + +export default class Table extends graphic.Group { + constructor(option) { + super(); + + this.invTransform = [1, 0, 0, 1, 0, 0]; + + this._elMap = { + rowLines: [], + colLines: [], + cellArrs: [], + bg: null + }; + + this._option = { + zlevel: option.zlevel || 0, + z: option.z || 0, + z2: option.z || 0, + cursor: option.cursor||null, + silent: option.silent||false, + shape: { + dataSource: option.shape.dataSource || [], + wList: option.shape.wList || [], + hList: option.shape.hList || [], + point: option.shape.point || {x: 0, y: 0} + }, + style: { + backgroundColor: option.style.backgroundColor, + lineWidth: option.style.lineWidth || 1, + stroke: option.style.stroke || '#000000' + } + }; + + this.render(); + } + + render() { + this.removeAll(); + this._createLineModels(); + this._createCells(); + } + + _createLineModels() { + const zlevel = this._option.zlevel; + const z = this._option.z; + const z2 = this._option.z2; + const cursor = this._option.cursor; + const shape = this._option.shape; + const style = this._option.style; + const x = shape.point.x; + const y = shape.point.y; + const rowLen = shape.hList.length; + const colLen = shape.wList.length; + const sumW = colLen==0? 0: shape.wList.reduce((pre, item) => { return pre + item; }); + const sumH = rowLen==0? 0: shape.hList.reduce((pre, item) => { return pre + item; }); + + for (let i = 1; i < rowLen; i++) { + const line = new graphic.Line({ + zlevel: zlevel, + z: z, + z2: z2, + cursor, + shape: { + x1: x, + y1: y + shape.hList.reduce((pre, item, idx) => { return pre + (idx < i ? item || style.rowHeight: 0); }), + x2: x + sumW, + y2: y + shape.hList.reduce((pre, item, idx) => { return pre + (idx { return pre + (idx < i ? item || style.columnWidth: 0); }), + y1: y, + x2: x + shape.wList.reduce((pre, item, idx) => { return pre + (idx < i ? item || style.columnWidth: 0); }), + y2: y + sumH + }, + style: { + lineWidth: style.lineWidth, + stroke: style.stroke + } + }); + this._elMap.colLines.push(line); + this.add(line); + } + + this._elMap.bg = new graphic.Rect({ + zlevel: zlevel, + z: z, + z2: z2-1, + cursor, + shape: { + x: x, + y: y, + width: sumW, + height: sumH + }, + style: { + lineWidth: style.lineWidth, + stroke: style.stroke, + fill: style.backgroundColor + } + }); + this.add(this._elMap.bg); + } + + _createCells() { + const zlevel = this._option.zlevel; + const z = this._option.z; + const z2 = this._option.z2; + const cursor = this._option.cursor; + const silent = this._option.silent; + const shape = this._option.shape; + const style = this._option.style; + const x = shape.point.x; + const y = shape.point.y; + + this._elMap.cellArrs = []; + shape.dataSource.forEach((rowList, i) => { + const list = []; + if (rowList instanceof Array) { + rowList.forEach((elem, j) => { + const cell = new Cell({ + zlevel: zlevel, + z: z, + z2: z2+1, + cursor: cursor, + silent: silent, + shape: Object.assign({ + x: x + shape.wList.reduce((pre, item, idx) => { return pre + (idx <= j ? item || style.columnWidth: 0); }) - (shape.wList[j] || style.columnWidth) /2, + y: y + shape.hList.reduce((pre, item, idx) => { return pre + (idx <= i ? item || style.rowHeight: 0); }) - (shape.hList[i] || style.rowHeight) /2, + width: shape.wList[j] || style.cell.width, + height: shape.hList[i] || style.cell.Height + }), + style: elem || {} + }); + list.push(cell); + this.add(cell); + }); + } + this._elMap.cellArrs.push(list); + }); + } + + _traverse(target, attr) { + for (var key in attr) { + if (!(attr[key] instanceof Object) || !attr[key]) { + target[key] = attr[key]; + } else { + this._traverse(target[key], attr[key]); + } + } + } + + setShape(objs) { + this._traverse(this._option.shape, objs); + this.render(); + } + + setStyle(objs) { + this._traverse(this._option.style, objs); + this.render(); + } + + dragging(e) { + [...this._elMap.rowLines, ...this._elMap.colLines].forEach(elem => { + elem.setShape({ + x1: elem.shape.x1 + e.dx, + y1: elem.shape.y1 + e.dy, + x2: elem.shape.x2 + e.dx, + y2: elem.shape.y2 + e.dy + }); + }); + + this._elMap.cellArrs.forEach(list => { + list.forEach(elem => { + elem.dragging(e); + }); + }); + + this._elMap.bg.setShape({ + x: this._elMap.bg.shape.x + e.dx, + y: this._elMap.bg.shape.y + e.dy + }); + } +} diff --git a/src/iscs_new/keyboardHandle.js b/src/iscs_new/keyboardHandle.js new file mode 100644 index 000000000..f20c75765 --- /dev/null +++ b/src/iscs_new/keyboardHandle.js @@ -0,0 +1,33 @@ + +export default class KeyBoardHandle { + constructor(map, controller) { + this.$map = map; + this.$controller = controller; + this.keyStr = ''; + } + + execFunc(moduleName, funcName, args) { + const module = this.$controller[moduleName]||{}; + const func = module[funcName]; + if (func instanceof Function) { + func.apply(module, args); + } + } + + onKeydown(e) { + switch (e.key) { + case 'v': + this.execFunc('selectHandle', 'setDraggable', ['vertical']); + break; + case 'h': + this.execFunc('selectHandle', 'setDraggable', ['horizontal']); + break; + case 'Escape': + this.execFunc('selectHandle', 'setDraggable', [true]); + break; + } + } + + onKeyup(e) { + } +} diff --git a/src/iscs_new/map.js b/src/iscs_new/map.js new file mode 100644 index 000000000..c5cd974f7 --- /dev/null +++ b/src/iscs_new/map.js @@ -0,0 +1,512 @@ +import _ from 'lodash'; +// import * as zrUtil from 'zrender/src/core/util'; +import * as utils from './utils/utils'; +import Caches from './utils/container/Caches'; // 缓存模块 +import zrender from 'zrender'; +import Painter from './painter'; +import SubMap from './subMap/subMap'; +import Options from './options'; +import Controller from './controller'; // 事件集合 +import Style from './config/style'; // 样式集合 +import graphType from './constant/graphType'; + +const renderer = 'canvas'; +const devicePixelRatio = 1; +const localStore = { caches: null, cachesDraft: null }; +class Jlmap { + constructor(opts) { + // 回调事件 + this.methods = opts.methods; + + // 鼠标事件 + this.events = { + __Pan: '_pan', + __Zoom: '_zoom', + + __DragStart: '_dragStart', + __Dragging: '_draging', + __DragEnd: '_dragEnd', + + __SelectStart: '_selectStart', + __Selecting: '_selecting', + __SelectEnd: '_selectEnd', + __Selected: '_selected', + + Reflect: 'reflect', + Selected: 'selected', + ContextMenu: 'contextmenu', + DataZoom: 'dataZoom', + Keydown: 'keydown', + Keyup: 'keyup', + Keypress: 'keypress' + + }; + + // 状态对象 + this.state = { + mapShape: {}, + mapEntity: {}, + mapLink: {}, + parser: {} + }; + + // 缓存模块 + if (opts.isDraw) { + localStore.caches = null; + localStore.cachesDraft = null; + this.caches = new Caches(this); + this.cachesDraft = {}; + } else { + this.caches = localStore.caches ? localStore.caches : new Caches(this); + this.cachesDraft = localStore.cachesDraft ? localStore.cachesDraft : {}; + } + + // 子图模块 + this.subMap = new SubMap(this); + + // 数据依赖关系 + this.mapDependency = {}; + + // 默认状态 + this.defaultStateDict = this.loadDefaultState(); + + // 默认皮肤 + this.defaultStyleDict = this.loadDefaultStyle(); + + // 是否绘制 + this.draw = false; + + // 是否可拖拽 + this.draggle = false; + + this.initMapInstance(opts); + } + + // 初始化属性有鼠标事件 缩放等 + initMapInstance(opts) { + const width = opts.dom.clientWidth; + const height = opts.dom.clientHeight; + const optionsHandler = this.setOptions.bind(this); + + this.$zr = zrender.init(opts.dom, { renderer, devicePixelRatio, width, height, ...utils.deepClone(opts.config||{})}); + this.$zr.dom.setAttribute('tabIndex', -1); + this.$zr.dom.style.cursor = 'auto'; + + this.$options = new Options({ scaleRate: 1, offsetX: 0, offsetY: 0, ...utils.deepClone(opts.options||{})}, (dataZoom) => { this.$controller.trigger(this.events.DataZoom, dataZoom); }); // 缩放 + + this.$painter = new Painter(this); + this.$painter.updateZrSize({width: this.$zr.getWidth(), height: this.$zr.getHeight()}); + this.$painter.updateTransform(this.$options); + + this.$controller = new Controller(this); + this.$controller.enable({draggle: this.draggle, panEnable: this.panEnable, zoomEnable: this.zoomEnable, keyEnable: this.keyEnable, selectable: this.selectable, selecting: this.selecting, reflectable: this.draw}); + + this.$controller.on(this.events.__Pan, optionsHandler); + this.$controller.on(this.events.__Zoom, optionsHandler); + + this.disable = function() { + this.off(this.events.Pan, optionsHandler); + this.off(this.events.Zoom, optionsHandler); + }; + } + + loadDefaultState() { + return {}; + } + + loadDefaultStyle() { + return Style; + } + + setMap({state, draggle, panEnable, zoomEnable, keyEnable, selectable, selecting, draw}) { + // 是否可拖拽 + this.draggle = draggle; + + // 鼠标移动 + this.panEnable = panEnable; + + // 视图缩放 + this.zoomEnable = zoomEnable; + + // 键盘事件 + this.keyEnable = keyEnable; + + // 选择事件 + this.selectable = selectable; + + // 区域选择 + this.selecting = selecting; + + // 是否绘图 + this.draw = state.isDraw = draw; + + // 解析模块 + this.parser = state.parser; + + // 状态对象 + this.state = state; + + if (state.dataZoom) { + this.$options.scaleRate = state.dataZoom.scaleRate || 1; + this.$options.offsetX = state.dataZoom.offsetX || 0; + this.$options.offsetY = state.dataZoom.offsetY || 0; + } + + // 分析依赖关系 + this.mapDependency = this.parser.analysis ? this.parser.analysis(state) : {}; + + // 绑定事件 + this.$controller.enable({draggle: this.draggle, panEnable: this.panEnable, zoomEnable: this.zoomEnable, keyEnable: this.keyEnable, selectable: this.selectable, selecting: this.selecting, reflectable: this.draw}); + + // 更新视图位置 + this.$painter.updateTransform({ scaleRate: this.$options.scaleRate, offsetX: this.$options.offsetX, offsetY: this.$options.offsetY }); + + // 数据加载完成 回调 + if (this.methods.dataLoaded instanceof Function) { this.methods.dataLoaded(this.state.mapShape); } + + // 初次渲染视图 + this.repaint(); + + // 视图加载完成 回调 + if (this.methods.viewLoaded instanceof Function) { this.methods.viewLoaded(this.state.mapShape); } + + // 设置默认状态 + this.setDefaultState(); + + // 返回视图缩放偏移 + this.$options.trigger(this.$options); + } + + setDefaultState() { + if (this.methods.stateLoaded instanceof Function) { this.methods.stateLoaded(); } + } + + setOptions(opts) { + const options = this.pullBack(opts); + + this.$options.update(options); + this.$painter.updateTransform(this.$options); + + this.$controller.disable(); + this.$controller.enable({...opts, draggle: this.draggle, panEnable: this.panEnable, zoomEnable: this.zoomEnable, keyEnable: this.keyEnable, selectable: this.selectable, selecting: this.selecting, reflectable: this.draw}); + + if (this.methods.optionsUpdate instanceof Function) { this.methods.optionsUpdate(this.$options); } + } + + setDragging(e) { + if (e.dragTarget) { + const scaleRate = this.$options.getScaleRate(); + e.dx /= scaleRate; + e.dy /= scaleRate; + e.dragTarget.instance.dragging(e); + } + } + + setCenter(shapeCode) { + const shape = this.state.mapShape[shapeCode]; + if (shape && shape.instance) { + var rect = utils.createBoundingRect(shape.instance); + var center = utils.calculateDCenter(rect, { width: this.$zr.getWidth(), height: this.$zr.getHeight() }); + this.setOptions(center); + } + } + + setBackgroundColor(color) { + this.$zr.setBackgroundColor(color); + } + + setCursorStyle(cursorStyle) { + this.$zr.setCursorStyle(cursorStyle); + } + + buildShape(elem, shape) { + return Object.assign(shape, {model: Object.assign(shape.model, elem), style: this.defaultStyleDict, draw: this.draw}); + } + + // 初次渲染 + repaint() { + this.$painter.clear(); + Object.values(this.state.mapShape).forEach(shape => { + this.$painter.add(this.buildShape({}, shape)); + }); + } + + restate() { + Object.values(this.state.mapShape).forEach(shape => { + this.$painter.update(shape); + }); + } + + render(list) { + (list||[]).forEach(elem => { + const code = elem.code; + const type = elem._type; + const entity = this.getEntityByModel(elem)||{}; + const mapShape = this.state.mapShape||{}; + const oShape = mapShape[code] || this.parser.newShape(entity, type, elem); + this.$painter.delete(oShape); + if (elem._dispose) { + delete mapShape[code]; + } else { + const nShape = this.buildShape(elem, oShape); + mapShape[code] = nShape; + this.$painter.add(nShape); + } + }); + + if (this.methods.viewUpdate instanceof Function) { this.methods.viewUpdate(list); } + } + + update(list) { + (list||[]).forEach(elem => { + this.$painter.update(elem); // 更新设备状态 + }); + + if (this.methods.stateUpdate instanceof Function) { this.methods.stateUpdate(list); } + } + + pullBack(payload) { + if (payload.type == this.events.__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||{}; + } + + isDraw() { + return this.draw; + } + + isHover(code) { + return this.$controller + ? this.$controller.storage.has(code) + : false; + } + + // 设置图层显示 + setLayerVisible(parserType, typeList) { + this.$painter.setLayerVisible(parserType, typeList); + } + + // 设置资源显示 + setVisible4Resource(types) { + Object.values(this.state.mapShape).filter(({model}) => { return model._type == graphType.Resource; }).forEach(({model, instance}) => { + const entity = this.getEntityByModel(model); + if (instance && entity && entity.type) { + this.$painter.setResourceVisible(instance, types.includes(entity.type)); + } + }); + } + + getZr() { + return this.$zr; + } + + getOptions() { + return this.$options; + } + + getPainter() { + return this.$painter; + } + + getController() { + return this.$controller; + } + + getEvents() { + return this.events; + } + + getState() { + return this.state; + } + + getMapDependency() { + return this.mapDependency; + } + + getMapShape() { + return this.state.mapShape; + } + + getMapEntity() { + return this.state.mapEntity; + } + + getMapLink() { + return this.state.mapLink; + } + + getDefaultStateDict() { + return this.defaultStateDict; + } + + getDefaultStyleDict() { + return this.defaultStyleDict; + } + + getViewTipsPoint(step) { + const shape = this.state.mapShape[step.code]; + if (shape) { + return this.$painter.getViewTipsPoint(step); + } else { + return this.subMap.getViewTipsPoint(step); + } + } + + getEntityByModel(model) { + return utils.getEntityByModel(this.state.mapEntity, this.state.mapLink, model); + } + + getShapeByCode(code) { + return this.state.mapShape[code]; + } + + getLinkByModel(model) { + return utils.getLinkByModel(this.state.mapLink, model); + } + + resize(opt) { + this.$zr.resize(opt); + this.$painter.updateZrSize(opt); + } + + refresh() { + this.$painter.refresh(); + } + + // 清除缓存 + clearCaches() { + localStore.caches = null; + this.caches.clear(); + } + + // 清除草稿缓存 + clearCachesDraft() { + localStore.cachesDraft = null; + this.cachesDraft = null; + } + + clear() { + this.state.mapShape = {}; + this.$controller.clear(); + this.$painter.clear(); + } + + // 设置画面缓存 + cache(state) { + const source = state.source; + if (source && source.id) { + this.caches.set(source.id, {...state}); + } + } + + // 设置草稿画面缓存 + handleCachesDraft(key, state) { + if (key) { + if (this.cachesDraft && this.cachesDraft[key]) { + const data = this.cachesDraft[key]; + if (!data[state.id]) { + const source = JSON.parse(JSON.stringify(state.value)); + delete source.mapEntity; + data[state.id] = source; + } + } else { + this.cachesDraft = {}; + // const map = new Map(); + // const data = map.set(state.id, state.value); + // this.cachesDraft.set(key, data); + const source = JSON.parse(JSON.stringify(state.value)); + delete source.mapEntity; + this.cachesDraft[key] = { + [state.id]: source, + mapEntity: state.value.mapEntity + }; + } + } + } + + dispose() { + this.disable(); + this.clear(); + this.$controller.dispose(); + this.$painter.dispose(); + + localStore.caches = this.caches; + + if (this.$zr) { + this.$zr.dispose(); + } + } + + on(name, cb, context) { + const idx = Object.values(this.events).indexOf(name); + if (idx >= 0) { + switch (name) { + case this.events.Reflect: + this.$controller.on(this.events.Reflect, _.throttle(cb, 200), context); + break; + case this.events.Selected: + this.$controller.on(this.events.Selected, cb, context); + break; + case this.events.ContextMenu: + this.$controller.on(this.events.ContextMenu, cb, context); + break; + case this.events.DataZoom: + this.$controller.on(this.events.DataZoom, cb, context); + break; + case this.events.Keydown: + this.$controller.on(this.events.Keydown, cb, context); + break; + case this.events.Keypress: + this.$controller.on(this.events.Keypress, cb, context); + break; + case this.events.Keyup: + this.$controller.on(this.events.Keyup, cb, context); + break; + } + } + } + + off(name, cb) { + const idx = Object.values(this.events).indexOf(name); + if (idx >= 0) { + switch (name) { + case this.events.Reflect: + this.$controller.on(this.events.Reflect, _.throttle(cb, 200)); + break; + case this.events.Selected: + this.$controller.off(this.events.Selected, cb); + break; + case this.events.ContextMenu: + this.$controller.off(this.events.ContextMenu, cb); + break; + case this.events.DataZoom: + this.$controller.off(this.events.DataZoom, cb); + break; + case this.events.Keydown: + this.$controller.off(this.events.Keydown, cb); + break; + case this.events.Keypress: + this.$controller.off(this.events.Keypress, cb); + break; + case this.events.Keyup: + this.$controller.off(this.events.Keyup, cb); + break; + } + } + } +} + +export default Jlmap; diff --git a/src/iscs_new/mapper.js b/src/iscs_new/mapper.js new file mode 100644 index 000000000..d83dd2c9b --- /dev/null +++ b/src/iscs_new/mapper.js @@ -0,0 +1,990 @@ +import graphType from './constant/graphType'; +// import * as utils from './utils/utils'; +import store from '@/store'; +import { MapTypeEnum, DcsModeEnum } from '@/scripts/ConstDic'; +class Mapper { + constructor() { + this.__Dialog = {}; + this.__mapper = {}; + this.loadDialogData(); + + this.loadMapper(); + } + + loadDialogData() { + this.__Dialog['tpsq'] = { + ElectricGlobeValve: { + DCS: { + Left: { + command: 'ElectricGlobeValve', + dialogName: 'Adjust-Power' + }, + Right: [] + } + }, + ElectricPlowUnloader: { // 犁 + DCS: { + Left: { + command: 'ElectricPlowUnloader', + dialogName: 'Adjust-Powload' + }, + Right: [] + } + }, + MagneticGlobeValve: { + DCS: { + Left: { + command: 'MagneticGlobeValve', + dialogName: 'Adjust-Power' + }, + Right: [] + } + }, + PneumaticGlobeValve: { + DCS: { + Left: { + command: 'PneumaticGlobeValve', + dialogName: 'Adjust-Power' + }, + Right: [] + } + }, + Motor: { + DCS: { + Left: { + command: 'Motor', + dialogName: 'Adjust-Power' + }, + Right: [] + } + }, + Burner: { + DCS: { + Left: { + command: 'Burner', + dialogName: 'Adjust-Power' + }, + Right: [] + } + }, + ElectricControlValve: { + DCS: { + Left: { + command: 'ElectricControlValve', + dialogName: 'Adjust-Setting' + }, + Right: [] + } + }, + FrequencyConverter: { + DCS: { + Left: { + command: 'FrequencyConverter', + dialogName: 'Adjust-Setting' + }, + Right: [] + } + }, + ManualGlobeValve: { + DCS: { + Left: { + command: 'ManualGlobeValve', + dialogName: 'Hand-Switch-Power' + }, + Right: [] + } + }, + ThreePortValve: { // 三通阀 + DCS: { + Left: { + command: 'ThreePortValve', + dialogName: 'Hand-Side-Forward' + }, + Right: [] + } + }, + [graphType.Popup]: { + DCS: { + Left: { + command: 'Popup', + dialogName: 'Popup-Panel' + }, + Right: [] + } + }, + [graphType.Pid]: { + DCS: { + Left: { + command: 'Pid', + dialogName: 'Popup-Pid-Panel' + }, + Right: [] + } + }, + [graphType.ProgramControl]: { + DCS: { + Left: { + command: 'ProgramControl', + dialogName: 'Popup-Program-Panel' + }, + Right: [] + } + }, + [graphType.Switching]: { + DCS: { + Left: { + command: 'Switching', + dialogName: 'Switching' + }, + Right: [] + } + } + }; + this.__Dialog['neepu'] = { + // N质量流量控制器 + NMassFlowController: { + DCS: { + Left: {}, + Right: [ + { + name: '自动调节', + sign: 'AUTO_REGULATING', + dialogName: 'Auto-Regulating' + } + ] + }, + Site: { + Left: {}, + Right: [ + { + name: '自动调节', + sign: 'AUTO_REGULATING', + dialogName: 'Auto-Regulating' + } + ] + } + }, + // 报警温度计 + NAlarmThermometer: { + System: { + Left: {}, + Right: [ + { + name: '清除报警', + sign: 'CANCEL_WARNING', + command: 'CANCEL_WARNING' + } + ] + } + }, + // 恒温装置 + NThermostat: { + System: { + Left: {}, + Right: [ + { + name: '启动/停止', + sign: 'SWITCH_TO', + dialogName: 'Switch-Power', + signParams: { + open: 'OPEN', + close: 'CLOSE' + } + } + ] + } + }, + // N辅助油泵 + NAuxiliaryOilPump: { + DCS: { + Left: {}, + Right: [ + { + name: '启动/停止', + dialogName: 'Switch-Power', + signParams: { + open: 'OPEN', + close: 'CLOSE' + } + } + ] + } + }, + // N凝结水泵 + NCondensatePump: { + DCS: { + Left: {}, + Right: [ + { + name: '启动/停止', + dialogName: 'Switch-Power', + signParams: { + open: 'OPEN', + close: 'CLOSE' + } + } + ] + } + }, + // N计量泵 + NDosingPump: { + DCS: { + Left: {}, + Right: [ + { + name: '启动/停止', + sign: 'SWITCH_TO', + dialogName: 'Switch-Power', + signParams: { + open: 'OPEN', + close: 'CLOSE' + }, + isShow: (el) => { return el.controlMode === 'Remote'; } + }, + { + name: '设置频率', + sign: 'SET_FREQ', + dialogName: 'Frequency-Input', + isShow: (el) => { return el.controlMode === 'Remote'; } + }, + { + name: 'PID调节', + sign: 'PID_REGULATING', + dialogName: 'Dosing-Pump-Target', + isShow: (el) => { return el.controlMode === 'Remote'; } + } + ] + }, + Site: { + Left: {}, + Right: [ + { + name: '手动冲程', + sign: 'SET_STROKE', + dialogName: 'Frequency-Setting' + } + ] + } + }, + // N搅拌电机 + NMixingMotor: { + DCS: { + Left: {}, + Right: [ + { + name: '启动/停止', + dialogName: 'Switch-Power', + signParams: { + open: 'OPEN', + close: 'CLOSE' + }, + isShow: (el) => { return el.controlMode === 'Remote'; } + } + ] + } + }, + // N虚拟组合阀 + NVirtualCombinationValve: { + DCS: { + Left: {}, + Right: [ + { + name: '打开/关闭', + dialogName: 'Switch-Power', + signParams: { + open: 'OPEN', + close: 'CLOSE' + } + } + ] + } + }, + // 电动截止阀 + ElectricGlobeValve: { + DCS: { + Left: {}, + Right: [ + { + name: '打开/关闭', + sign: 'SWITCH_TO', + dialogName: 'Switch-Power', + signParams: { + open: 'OPEN', + close: 'CLOSE' + }, + isShow: (el) => { return el.controlMode == null || el.controlMode === 'Remote'; } + } + ] + } + }, + // 手动截止阀 + ManualGlobeValve: { + Site: { + Left: {}, + Right: [ + { + name: '打开/关闭', + sign: 'SWITCH_TO', + dialogName: 'Switch-Power', + signParams: { + open: 'OPEN', + close: 'CLOSE' + } + } + ] + }, + System: { + Left: {}, + Right: [ + { + name: '打开/关闭', + sign: 'SWITCH_TO', + dialogName: 'Switch-Power', + signParams: { + open: 'OPEN', + close: 'CLOSE' + } + } + ] + } + }, + // N溶液箱 + NStirredSolutionTank: { + DCS: { + Left: {}, + Right: [ + { + name: '设置为标液', + sign: 'SET_STANDARD', + dialogName: 'Standard-Input', + isShow: (el) => !el.solidDosing + + }, + { + name: '设置为标液', + sign: 'SET_STANDARD', + dialogName: 'Standard-Setting', + isShow: (el) => el.solidDosing + }, + { + name: '取消设置', + sign: 'CANCEL_SET', + command: 'CANCEL_SET' + } + ] + // SET_STANDARD({model, instance}) { + // const attrObj = utils.getObjFormListBySign(model.attrList, 'solidDosingDeviceCode'); + // return attrObj && attrObj.val ? 'StandardSetting': 'StandardInput'; + // } + }, + Site: { + Left: {}, + Right: [ + { + name: '设置为标液', + sign: 'SET_STANDARD', + dialogName: 'Standard-Input', + isShow: (el) => !el.solidDosing + }, + { + name: '设置为标液', + sign: 'SET_STANDARD', + dialogName: 'Standard-Setting', + isShow: (el) => el.solidDosing + }, + { + name: '取消设置', + sign: 'CANCEL_SET', + command: 'CANCEL_SET' + } + ] + // SET_STANDARD({model, instance}) { + // const attrObj = utils.getObjFormListBySign(model.attrList, 'solidDosingDeviceCode'); + // return attrObj && attrObj.val ? 'StandardSetting': 'StandardInput'; + // } + } + }, + // N固体加药器 + NSolidDoser: { + DCS: { + Left: {}, + Right: [ + { + name: '加药', + sign: 'DOSE', + dialogName: 'Solid-Dosing-Input' + } + ] + }, + Site: { + Left: {}, + Right: [ + { + name: '加药', + sign: 'DOSE', + dialogName: 'Solid-Dosing-Input' + } + ] + } + }, + // N带灯按钮 + NIlluminatedButton: { + DCS: { + Left: {}, + Right: [] + }, + Site: { + Left: { + command: 'CLICK' + }, + Right: [] + } + }, + // 转换开关 + NChangeoverSwitch: { + DCS: {}, + Site: { + Left: { + command: 'CHANGE_OVER' + }, + Right: [] + } + }, + // 手轮 + NHandWheel: { + DCS: {}, + Site: { + Left: { + command: 'ADJUST', + dialogName: 'Adjust-Opening' + }, + Right: [ + // { + // name: '调频', + // sign: 'ADJUST', + // dialogName: 'Adjust-Opening' + // } + ] + } + } + }; + } + + loadMapper() { + this.__menus = { + // 质量流量控制器 + MassFlowController: [ + { + mode: 'Right', + name: '说明', + sign: 'MENU_EXPLAIN', + graphType: 'DCS' + }, + { + mode: 'Right', + name: '说明', + sign: 'MENU_EXPLAIN', + graphType: 'Site' + } + ] + }; + } + + filter(sign, node) { // 根据模式过滤菜单 + const mapper = { + PID_REGULATING() { + return store.state.map.dcsMode == DcsModeEnum.Auto + ? node : null; + }, + AUTO_REGULATING() { + return store.state.map.dcsMode == DcsModeEnum.Auto || store.state.map.mapType == MapTypeEnum.Site + ? node : null; + }, + __default() { + return store.state.map.dcsMode == DcsModeEnum.Auto + ? null: node; + } + }; + return mapper[sign]? mapper[sign](): mapper.__default(); + } + + concat(menus, type) { + const _menus = this.__menus[type]; + return _menus? menus.concat(_menus.map(el => { return Object.assign(el, {local: true}); })) : menus; + } + + getPopUp({type, graphType, projectSign}, device, isLeft) { + const dialog = this.__Dialog[projectSign]; + graphType = graphType || 'Other'; + if (dialog[type] && dialog[type][graphType]) { + if (isLeft) { + return dialog[type][graphType]['Left'] ? dialog[type][graphType]['Left'] : null; + } else { + return dialog[type][graphType]['Right']; + } + } + } +} + +export default new Mapper(); + +[ + { + 'name': '加药控制柜', + 'type': 'DosingControlCabinet', + 'operationList': [{ + 'id': '32', + 'name': '切换控制模式', + 'graphType': 'Site', + 'sign': 'SWITCH_TO', + 'mode': 'Other', + 'param': '', + 'popup': '' + }, { + 'id': '33', + 'name': '切换控制模式', + 'graphType': 'DCS', + 'sign': 'SWITCH_TO', + 'mode': 'Other', + 'param': '', + 'popup': '' + }] + }, + { + 'name': '搅拌溶液箱', + 'type': 'StirredSolutionTank', + 'operationList': [{ + 'id': '28', + 'name': '设置为标液', + 'graphType': 'Site', + 'sign': 'SET_STANDARD', + 'mode': 'Right', + 'param': '', + 'popup': 'standard-setting' + }, { + 'id': '29', + 'name': '取消设置', + 'graphType': 'Site', + 'sign': 'CANCEL_SET', + 'mode': 'Right', + 'param': '', + 'popup': '' + }, { + 'id': '30', + 'name': '设置为标液', + 'graphType': 'DCS', + 'sign': 'SET_STANDARD', + 'mode': 'Right', + 'param': '', + 'popup': 'standard-setting' + }, { + 'id': '31', + 'name': '取消设置', + 'graphType': 'DCS', + 'sign': 'CANCEL_SET', + 'mode': 'Right', + 'param': '', + 'popup': '' + }] + }, + { + 'id': '4', + 'name': '手动球阀', + 'type': 'ManualBallValve', + 'operationList': [{ + 'id': '3', + 'name': '打开/关闭', + 'graphType': 'Site', + 'sign': 'SWITCH_TO', + 'mode': 'Right', + 'param': '', + 'popup': 'switch-status' + }, { + 'id': '19', + 'name': '打开/关闭', + 'graphType': 'System', + 'sign': 'SWITCH_TO', + 'mode': 'Right', + 'param': '', + 'popup': 'switch-status' + }] + }, + { + 'id': '5', + 'name': '电动球阀', + 'type': 'ElectronicBallValve', + 'operationList': [{ + 'id': '14', + 'name': '打开', + 'graphType': 'Site', + 'sign': 'OPEN', + 'mode': 'Other', + 'param': '', + 'popup': '' + }, { + 'id': '15', + 'name': '关闭', + 'graphType': 'Site', + 'sign': 'CLOSE', + 'mode': 'Other', + 'param': '', + 'popup': '' + }, { + 'id': '16', + 'name': '打开/关闭', + 'graphType': 'DCS', + 'sign': 'SWITCH_TO', + 'mode': 'Right', + 'param': '', + 'popup': 'power-status' + }] + }, + { + 'name': '搅拌电机', + 'type': 'MixingMotor', + 'operationList': [{ + 'id': '2', + 'name': '启动/停止', + 'graphType': 'DCS', + 'sign': 'SWITCH_TO', + 'mode': 'Right', + 'param': '', + 'popup': 'switch-status' + }, { + 'id': '17', + 'name': '启动', + 'graphType': 'Site', + 'sign': 'OPEN', + 'mode': 'Other', + 'param': '', + 'popup': '' + }, { + 'id': '18', + 'name': '停止', + 'graphType': 'Site', + 'sign': 'CLOSE', + 'mode': 'Other', + 'param': '', + 'popup': '' + }, { + 'id': '22', + 'name': '设置故障', + 'graphType': 'DCS', + 'sign': 'SET_FAULT', + 'mode': 'Fault', + 'param': '', + 'popup': '' + }, { + 'id': '23', + 'name': '取消故障', + 'graphType': 'DCS', + 'sign': 'CANCEL_FAULT', + 'mode': 'Fault', + 'param': '', + 'popup': '' + }] + }, + { + 'id': '8', + 'name': '带灯按钮', + 'type': 'IlluminatedButton', + 'operationList': [{ + 'id': '5', + 'name': '开/关', + 'graphType': 'Site', + 'sign': 'IlluminatedButton', + 'mode': 'Left', + 'param': '', + 'popup': '' + }] + }, + { + 'name': '转换开关', + 'type': 'ChangeoverSwitch', + 'operationList': [{ + 'id': '4', + 'name': '开/关', + 'graphType': 'Site', + 'sign': '{{mapMode}}', + 'mode': 'Left', + 'param': '', + 'popup': '' + }] + }, + { + 'name': '电磁球阀', + 'type': 'ElectromagneticBallValve', + 'operationList': [{ + 'id': '48', + 'name': '关闭', + 'graphType': 'Site', + 'sign': 'CLOSE', + 'mode': 'Other', + 'param': '', + 'popup': '' + }, { + 'id': '49', + 'name': '打开', + 'graphType': 'Site', + 'sign': 'OPEN', + 'mode': 'Other', + 'param': '', + 'popup': '' + }] + }, + { + 'name': '加药计量泵', + 'type': 'DosingPump', + 'operationList': [{ + 'id': '8', + 'name': '启动', + 'graphType': 'Site', + 'sign': 'OPEN', + 'mode': 'Other', + 'param': '', + 'popup': '' + }, { + 'id': '9', + 'name': '停止', + 'graphType': 'Site', + 'sign': 'CLOSE', + 'mode': 'Other', + 'param': '', + 'popup': '' + }, { + 'id': '13', + 'name': '启动/停止', + 'graphType': 'DCS', + 'sign': 'SWITCH_TO', + 'mode': 'Right', + 'param': '', + 'popup': 'switch-status' + }, { + 'id': '24', + 'name': '设置故障', + 'graphType': 'Site', + 'sign': 'SET_FAULT', + 'mode': 'Fault', + 'param': '', + 'popup': '' + }, { + 'id': '25', + 'name': '取消故障', + 'graphType': 'Site', + 'sign': 'CANCEL_FAULT', + 'mode': 'Fault', + 'param': '', + 'popup': '' + }, { + 'id': '26', + 'name': '设置频率', + 'graphType': 'DCS', + 'sign': 'SET_FREQ', + 'mode': 'Right', + 'param': '', + 'popup': 'frequency-input' + }, { + 'id': '27', + 'name': '手动冲程', + 'graphType': 'Site', + 'sign': 'SET_STROKE', + 'mode': 'Right', + 'param': '', + 'popup': 'frequency-setting' + }, { + 'id': '51', + 'name': 'PID调节', + 'graphType': 'DCS', + 'sign': 'PID_REGULATING', + 'mode': 'Right', + 'param': '' + }] + }, + { + 'name': '高温高压阀', + 'type': 'ManualNeedleValve', + 'operationList': [{ + 'id': '20', + 'name': '打开/关闭', + 'graphType': 'System', + 'sign': 'SWITCH_TO', + 'mode': 'Right', + 'param': '', + 'popup': 'switch-status' + }, { + 'id': '21', + 'name': '打开/关闭', + 'graphType': 'Site', + 'sign': 'SWITCH_TO', + 'mode': 'Right', + 'param': '', + 'popup': 'switch-status' + }] + }, + { + 'name': '温度表', + 'type': 'Thermometer', + 'operationList': [{ + 'id': '38', + 'name': '取消报警', + 'graphType': 'System', + 'sign': 'CANCEL_WARNING', + 'mode': 'Right', + 'param': '', + 'popup': '' + }] + }, + { + 'name': '恒温装置', + 'type': 'Thermostat', + 'operationList': [{ + 'id': '36', + 'name': '切换', + 'graphType': 'Site', + 'sign': 'SWITCH_TO', + 'mode': 'Other', + 'param': '', + 'popup': '' + }] + }, + { + 'name': '固体加药器', + 'type': 'SolidDoser', + 'operationList': [{ + 'id': '34', + 'name': '加药', + 'graphType': 'Site', + 'sign': 'DOSE', + 'mode': 'Right', + 'param': '', + 'popup': 'solid-dosing-setting' + }, { + 'id': '35', + 'name': '加药', + 'graphType': 'DCS', + 'sign': 'DOSE', + 'mode': 'Right', + 'param': '', + 'popup': 'solid-dosing-setting' + }] + }, + { + 'name': '虚拟组合阀', + 'type': 'VirtualCombinationValve', + 'operationList': [{ + 'id': '39', + 'name': '打开/关闭', + 'graphType': 'DCS', + 'sign': 'SWITCH_TO', + 'mode': 'Right', + 'param': '', + 'popup': 'switch-status' + }] + }, + { + 'name': '高压阀', + 'type': 'HighPressureValve', + 'operationList': [{ + 'id': '50', + 'name': '调节', + 'graphType': '', + 'sign': 'ADJUST_OPENING', + 'mode': 'Other', + 'param': '' + }] + }, + { + 'name': '减压阀', + 'type': 'ReductionValve', + 'operationList': [{ + 'id': '43', + 'name': '打开/关闭', + 'graphType': 'Site', + 'sign': 'SWITCH_TO', + 'mode': 'Right', + 'param': '', + 'popup': 'switch-status' + }, { + 'id': '44', + 'name': '打开/关闭', + 'graphType': 'System', + 'sign': 'SWITCH_TO', + 'mode': 'Right', + 'param': '', + 'popup': 'switch-status' + }] + }, + { + 'name': '止回阀', + 'type': 'CheckValve', + 'operationList': [{ + 'id': '45', + 'name': '打开/关闭', + 'graphType': 'Site', + 'sign': 'SWITCH_TO', + 'mode': 'Right', + 'param': '', + 'popup': 'switch-status' + }, { + 'id': '46', + 'name': '打开/关闭', + 'graphType': 'System', + 'sign': 'SWITCH_TO', + 'mode': 'Right', + 'param': '', + 'popup': 'switch-status' + }] + }, + { + 'name': '质量流量控制器', + 'type': 'MassFlowController', + 'operationList': [{ + 'id': '52', + 'name': '自动调节', + 'graphType': 'Site', + 'sign': 'AUTO_REGULATING', + 'mode': 'Right', + 'param': '' + }, { + 'id': '53', + 'name': '自动调节', + 'graphType': 'DCS', + 'sign': 'AUTO_REGULATING', + 'mode': 'Right', + 'param': '' + }] + }, + { + 'name': '调节阀', + 'type': 'ControlValve', + 'operationList': [{ + 'id': '47', + 'name': '调节', + 'graphType': '', + 'sign': 'ADJUST_OPENING', + 'mode': 'Other', + 'param': '' + }] + }, + { + 'name': '加氧控制柜', + 'type': 'OxygenationControlCabinet', + 'operationList': [{ + 'id': '40', + 'name': '切换控制模式', + 'graphType': '', + 'sign': 'SWITCH_TO', + 'mode': 'Other', + 'param': '', + 'popup': '' + }, { + 'id': '41', + 'name': '切换控制模式', + 'graphType': 'DCS', + 'sign': 'SWITCH_TO', + 'mode': 'Other', + 'param': '', + 'popup': '' + }] + } +]; diff --git a/src/iscs_new/maps.js b/src/iscs_new/maps.js new file mode 100644 index 000000000..867003982 --- /dev/null +++ b/src/iscs_new/maps.js @@ -0,0 +1,128 @@ +import * as utils from './utils/utils'; +import * as Dom from './utils/dom'; +import Emap from './map'; + +const DOM_ATTRIBUTE_KEY = '_maps_instance_'; + +class Emaps { + constructor() { + this._version = '1.1.1'; + this.instances = {}; + this.mapShape = {}; + this.mapEntity = {}; + this.mapLink = {}; + } + + init(opts) { + if (!opts) { + throw new Error('Initialize failed: invalid params.'); + } + + if (!opts.dom && opts.el) { + opts['dom'] = document.getElementById(opts.el); + } + + if (!opts.dom) { + throw new Error('Initialize failed: invalid dom and el.'); + } + + const existInstance = this.getInstanceByDom(opts.dom); + if (existInstance) { + console.warn('There is a chart instance already initialized on the dom.'); + return existInstance; + } + + if (Dom.isDom(opts.dom) && opts.dom.nodeName.toUpperCase() !== 'CANVAS' && + ( + (!opts.dom.clientWidth && (!opts || opts.width == null)) || + (!opts.dom.clientHeight && (!opts || opts.height == null)) + ) + ) { + console.warn('Can\'t get DOM width or height. Please check ' + + 'dom.clientWidth and dom.clientHeight. They should not be 0.' + + 'For example, you may need to call this in the callback ' + + 'of window.onload.'); + } + + const emap = new Emap(opts); + + this.instances[opts.el] = emap; + + Dom.setAttribute(opts.dom, DOM_ATTRIBUTE_KEY, opts.el); + + return emap; + } + + loadState(state) { + // 解析后的数据 + this.mapShape = utils.assignByDeep(this.mapShape, state.mapShape||{}, 0); + + // 实体数据 + this.mapEntity = utils.assignByDeep(this.mapEntity, state.mapEntity||{}, 0); + + // 实体关系 + this.mapLink = utils.assignByDeep(this.mapLink, state.mapLink||{}, 1); + } + + setMap(map, opts, judge = false) { + const { state } = opts; + if (!judge) { + this.loadState(state); + } + map.setMap(opts); + } + + getVersion() { + return this._version; + } + + getInstanceByDom(dom) { + return this.instances[Dom.getAttribute(dom, DOM_ATTRIBUTE_KEY)]; + } + + getInstanceById(el) { + return this.instances[el]; + } + + getMapShape() { + return this.mapShape; + } + + getMapEntity() { + return this.mapEntity; + } + + getMapLink() { + return this.mapLink; + } + + getShapeByCode(code) { + return this.mapShape[code]; + } + + getEntityByModel(model) { + return utils.getEntityByModel(this.mapEntity, this.mapLink, model); + } + + getLinkByModel(model) { + return utils.getLinkByModel(this.mapLink, model); + } + + clearMapEntity() { + this.mapEntity = {}; + } + + dispose(emap) { + if (utils.isString(emap)) { + emap = this.instances[emap]; + } else if (!utils.isInstanceOf(emap, Emap)) { + emap = this.getInstanceByDom(emap.getDom()); + } + + if (emap) { + emap.dispose(); + } + } +} + +export default Emaps; diff --git a/src/iscs_new/options.js b/src/iscs_new/options.js new file mode 100644 index 000000000..b22645e16 --- /dev/null +++ b/src/iscs_new/options.js @@ -0,0 +1,101 @@ +class Options { + constructor(opts, trigger) { + this.scaleIndex = 0; + this.scaleList = [ + 0.2, 0.3, 0.4, 0.5, + 0.6, 0.7, 0.8, 0.9, + 1, 1.2, 1.4, 1.6, 1.8, + 2, 2.2, 2.4, 2.6, 2.8, + 3, 3.2, 3.4, 3.6, 3.8, + 4, 4.2, 4.4, 4.6, 4.8, + 5, 5.2, 5.4, 5.6, 5.8, + 6, 6.2, 6.4, 6.6, 6.8, + 7, 7.2, 7.4, 7.6, 7.8, + 8, 8.2, 8.4, 8.6, 8.8 + ]; + + if (Number.isFinite(opts.scaleRate)) { + const idx = this.scaleList.indexOf(opts.scaleRate); + if (idx >= 0) { + this.scaleIndex = idx; + } + } + + this.scaleRate = opts.scaleRate || this.scaleList[this.scaleIndex]; // 缩放 + + this.offsetX = opts.offsetX || 0; // x偏移 + + this.offsetY = opts.offsetY || 0; // y偏移 + + this.throttle = opts.throttle || 100; // 刷新频率 + + this.disabled = false; + + this.panEnable = true; + + this.zoomEnable = false; + + this.preventDefaultMouseMove = true; + + this.trigger = trigger; + } + + update(payload) { + if (Number.isFinite(payload.dx)) { + this.offsetX -= payload.dx; + } + if (Number.isFinite(payload.dy)) { + this.offsetY -= payload.dy; + } + + if (Number.isFinite(payload.offsetX)) { + this.offsetX = payload.offsetX; + } + if (Number.isFinite(payload.offsetY)) { + this.offsetY = payload.offsetY; + } + + if (Number.isFinite(payload.scale)) { + if (Number.isFinite(payload.scale)) { + if ((this.scaleIndex + payload.scale) >= 0 && (this.scaleIndex + payload.scale) < this.scaleList.length) { + this.scaleIndex = this.scaleIndex + payload.scale; + } + } + this.scaleRate = this.scaleList[this.scaleIndex]; + } + + if (Number.isFinite(payload.scaleRate)) { + const idx = this.scaleList.indexOf(payload.scaleRate); + if (idx < 0) { + return; + } + this.scaleIndex = idx; + this.scaleRate = payload.scaleRate; + } + + if (payload.disabled === true || payload.disabled === false) { + this.disabled = payload.disabled; + } + + if (payload.panEnable === true || payload.panEnable === false) { + this.panEnable = payload.panEnable; + } + + if (payload.zoomEnable === true || payload.zoomEnable === false) { + this.zoomEnable = payload.zoomEnable; + } + + if (this.trigger instanceof Function) { this.trigger(this); } + } + + getScaleRate(scale) { + if (Number.isFinite(scale)) { + if ((this.scaleIndex + scale) >= 0 && (this.scaleIndex + scale) < this.scaleList.length) { + return this.scaleList[this.scaleIndex + scale]; + } + } + return this.scaleList[this.scaleIndex]; + } +} + +export default Options; diff --git a/src/iscs_new/package/graph/LinePipe/index.js b/src/iscs_new/package/graph/LinePipe/index.js new file mode 100644 index 000000000..fe609e2b4 --- /dev/null +++ b/src/iscs_new/package/graph/LinePipe/index.js @@ -0,0 +1,623 @@ +import * as graphic from '../../../graph/graphic'; +import * as utils from '../../../utils/utils'; +import RadialGradient from 'zrender/src/graphic/RadialGradient'; +import LinearGradient from 'zrender/src/graphic/LinearGradient'; +import panelType from '../../../constant/panelType'; +import ConstSelect from '@/scripts/ConstConfig'; +import { handleColor } from '@/map/utils/utils.js'; +import store from '@/store'; +import { MapTypeEnum } from '@/scripts/ConstDic.js'; +import Vue from 'vue'; + +class Adaptor { + constructor({model}, state, graph) { + this.__graph = graph; + this.__model = model; + this.__state = state; + } + + get() { + const model = this.__model; + const sceneType = this.__state.mapType; + const block = sceneType ? utils.getBlockBySceneType(model, sceneType) : null; + + this.__graph._block = block; + + return Object.assign(model, block); + } +} + +export default class LinePipe extends graphic.Group { + constructor(painter, shape, state) { + super(); + this._code = shape.model.code; + this._type = shape.model._type; + this._shape = shape; + this._painter = painter; + this._state = state; + this._block = null; + this._adaptor = new Adaptor(shape, state, this); + this._elMap = { + lines: [], + circles: [], + line: null, + flow: null, + lArrow: null, + rArrow: null, + lText: null, + rText: null + }; + + this.create(); + + this.on('mouseover', this.mouseover, this); + this.on('mouseout', this.mouseout, this); + } + + mouseover(e) { + if (this._shape.draw) { + this.doActive(this.__zr); + } + } + + mouseout(e) { + const map = this._painter.$map; + if (this._shape.draw && !map.isHover(this._code)) { + this.doInactive(this.__zr); + } + } + + create() { + const mapType = store.state.map.mapType; + const model = this._adaptor.get(); + const style = this._shape.style; + const draw = this._shape.draw; + const color = model.color; + const isVisible = this._state.isDraw + ? true + : model.hasOwnProperty('visible') ? model.visible: true; + + let modelData = {}; + if (model.sceneTypes) { + const modelIndex = model.sceneTypes.indexOf(mapType); + modelData = model.graphList[modelIndex]; // 对应模式下数据 + } else { + modelData = Object.assign(modelData, model); + } + + if (isVisible && this._block) { + if (model && modelData.points && modelData.points.length >= 2) { + + if (mapType == MapTypeEnum.Site) { + modelData.points.forEach((point, index) => { + if (index) { + const line = new graphic.Polyline({ + zlevel: model.zlevel, + z: model.z, + z2: this.getZ2(index, mapType), + silent: !draw, + shape: { + smooth: model.smooth / 10 + }, + style: { + blend: 'source-over', + lineWidth: parseFloat(modelData.width), + stroke: this.getLinearGradient(color) + } + }); + this._elMap.lines.push(utils.lineProxy(line, modelData.points[index-1], modelData.points[index])); + + if (index > 0 && index < modelData.points.length-1) { + const circle = new graphic.Circle({ + zlevel: model.zlevel, + z: model.z, + z2: model.layer || 0, + silent: !draw, + shape: { + cx: modelData.points[index].x, + cy: modelData.points[index].y, + r: parseFloat(modelData.width || 2) / 2 + }, + style: { + blend: 'source-over', + fill: this.getRadialGradient(color) + } + }); + this._elMap.circles.push(circle); + } + } + }); + } else { + this._elMap.line = new graphic.Polyline({ + zlevel: model.zlevel, + z: model.z, + z2: model.layer || 0, + silent: !draw, + shape: { + points: modelData.points.map(elem => { return [elem.x, elem.y]; }), + smooth: model.smooth / 10 + }, + style: { + lineJoin: 'round', + lineWidth: parseFloat(modelData.width) || style[panelType.LinePipe].line.lineWidth, + stroke: color + } + }); + } + + // 文字和状态 + if (!this._shape.draw) { + this._elMap.flow = new graphic.Polyline({ + zlevel: model.zlevel, + // z: model.z, + // z2: model.layer + 5, + z: model.z + 1, + z2: model.layer || 0, + silent: true, + shape: { + points: modelData.points.map(elem => { return [elem.x, elem.y]; }), + smooth: model.smooth / 10 + }, + style: { + lineDash: [8, 8], + lineWidth: parseFloat(modelData.width) * (mapType == MapTypeEnum.Site? 0.8 : 1) + } + }); + this._elMap.flow.hide(); + } + const lradian = utils.getRadian(modelData.points[1], modelData.points[0]); + this._elMap.lText = new graphic.Text({ + zlevel: model.zlevel, + z: model.z+9, + z2: (model.layer || 0), + silent: true, + style: { + x: modelData.points[0].x+Math.sin(lradian)*(parseFloat(modelData.width/2)+style.fontSize+5), + y: modelData.points[0].y+Math.cos(lradian)*(parseFloat(modelData.width/2)+style.fontSize+5), + fontWeight: 'normal', + fontSize: style.fontSize, + fontFamily: style.fontFamily, + text: 'A', + textFill: '#fff', + textAlign: 'left', + textVerticalAlign: 'top', + textPadding: [2, 2] + } + }); + this._elMap.lText.hide(); + + const rradian = utils.getRadian(modelData.points[modelData.points.length-2], modelData.points[modelData.points.length-1]); + this._elMap.rText = new graphic.Text({ + zlevel: model.zlevel, + z: model.z+9, + z2: (model.layer || 0), + silent: true, + style: { + x: modelData.points[modelData.points.length-1].x+Math.sin(rradian)*(parseFloat(modelData.width/2)+style.fontSize+5), + y: modelData.points[modelData.points.length-1].y+Math.cos(rradian)*(parseFloat(modelData.width/2)+style.fontSize+5), + fontWeight: 'normal', + fontSize: style.fontSize, + fontFamily: style.fontFamily, + text: 'B', + textFill: '#fff', + textAlign: 'right', + textVerticalAlign: 'bottom', + textPadding: [2, 2] + } + }); + this._elMap.rText.hide(); + // 左侧显示 + if (['Inlet', 'Outlet'].includes(modelData.leftArrow)) { + if (mapType !== MapTypeEnum.Site) { + const dx = modelData.points[1].x - modelData.points[0].x; + const dy = modelData.points[1].y - modelData.points[0].y; + + this._elMap.lArrow = new graphic.ArrowLine({ + zlevel: model.zlevel, + z: model.z, + z2: model.layer || 0, + silent: true, + origin: [ + modelData.points[0].x, + modelData.points[0].y + ], + rotation: -Math.atan2(dy, dx), + shape: { + x: modelData.points[0].x, + y: modelData.points[0].y, + isLeft: true, + toLeft: modelData.leftArrow == 'Outlet' + }, + style: { + lineWidth: style[panelType.LinePipe].arrow.lineWidth, + stroke: color + } + }); + } else { + const circle = new graphic.Circle({ + zlevel: model.zlevel, + z: model.z, + z2: model.layer || 0, + silent: !draw, + shape: { + cx: modelData.points[0].x, + cy: modelData.points[0].y, + r: parseFloat(modelData.width) / 2 + }, + style: { + blend: 'source-over', + fill: this.getRadialGradient(color) + } + }); + this._elMap.circles.push(circle); + } + } + // 右侧显示 + if (['Inlet', 'Outlet'].includes(modelData.rightArrow)) { + const arrowIndex = modelData.points.length - 1; + if (mapType !== MapTypeEnum.Site) { + const dx = modelData.points[arrowIndex].x - modelData.points[arrowIndex-1].x; + const dy = modelData.points[arrowIndex].y - modelData.points[arrowIndex-1].y; + + this._elMap.rArrow = new graphic.ArrowLine({ + zlevel: model.zlevel, + z: model.z, + z2: model.layer || 0, + silent: true, + origin: [ + modelData.points[arrowIndex].x, + modelData.points[arrowIndex].y + ], + rotation: -Math.atan2(dy, dx), + shape: { + x: modelData.points[arrowIndex].x, + y: modelData.points[arrowIndex].y, + isLeft: arrowIndex == 0, + toLeft: modelData.rightArrow == 'Inlet' + }, + style: { + lineWidth: style[panelType.LinePipe].arrow.lineWidth, + stroke: color + } + }); + } else { + const circle = new graphic.Circle({ + zlevel: model.zlevel, + z: model.z, + z2: model.layer || 0, + silent: !draw, + shape: { + cx: modelData.points[arrowIndex].x, + cy: modelData.points[arrowIndex].y, + r: parseFloat(modelData.width) / 2 + }, + style: { + blend: 'source-over', + fill: this.getRadialGradient(color) + } + }); + this._elMap.circles.push(circle); + } + } + + if ((ConstSelect.ConstMap.LSvgs[modelData.leftArrow]||{}).path) { + const rotation = -Math.atan2( + modelData.points[1].y-modelData.points[0].y, + modelData.points[1].x-modelData.points[0].x + ); + const path = ConstSelect.ConstMap.LSvgs[modelData.leftArrow].path; + this._elMap.lArrow = new graphic.Svg({ + zlevel: model.zlevel, + z: model.z, + z2: (model.layer || 0), + origin: [0, 0], + rotation, + shape: { + x: modelData.points[0].x, + y: modelData.points[0].y, + path + }, + style: { + lineWidth: style[panelType.LinePipe].arrow.lineWidth, + stroke: path.includes('stroke')? modelData.color: 'transparent ', + fill: path.includes('fill')? modelData.color: 'transparent ' + } + }); + } + + if ((ConstSelect.ConstMap.RSvgs[modelData.rightArrow]||{}).path) { + const len = modelData.points.length-1; + const rotation = -Math.atan2( + modelData.points[len].y-modelData.points[len-1].y, + modelData.points[len].x-modelData.points[len-1].x + ); + const path = ConstSelect.ConstMap.RSvgs[modelData.rightArrow].path; + this._elMap.rArrow = new graphic.Svg({ + zlevel: model.zlevel, + z: model.z, + z2: (model.layer || 0), + origin: [0, 0], + rotation, + shape: { + x: modelData.points[len].x, + y: modelData.points[len].y, + path + }, + style: { + lineWidth: style[panelType.LinePipe].arrow.lineWidth, + stroke: path.includes('stroke')? modelData.color: 'transparent ', + fill: path.includes('fill')? modelData.color: 'transparent ' + } + }); + } + + if (this._elMap.lines) { + this._elMap.lines.forEach(item => { + item.setStyle('lineDash', { + 'Solid': null, // 实线 + 'Dotted': [12, 6], // 虚线 + 'Point': [4, 4], // 点线 + 'DotPointA': [12, 4, 4, 4], // 一类虚点线 + 'DotPointB': [12, 4, 4, 4, 4, 4] // 二类虚点线 + }[model.type]); + }); + } + if (this._elMap.line) { + this._elMap.line.setStyle('lineDash', { + 'Solid': null, // 实线 + 'Dotted': [12, 6], // 虚线 + 'Point': [4, 4], // 点线 + 'DotPointA': [12, 4, 4, 4], // 一类虚点线 + 'DotPointB': [12, 4, 4, 4, 4, 4] // 二类虚点线 + }[model.type]); + } + } + } + + this.setState(model); + + Object.values(this._elMap).forEach(elem => { elem && elem instanceof Array? elem.forEach(el => this.add(el)): this.add(elem); }); + + } + + getRadialGradient(color) { + return store.state.map.mapType == MapTypeEnum.Site + ? new RadialGradient(0.5, 0.5, 0.5, + [ + {offset: 0, color: '#FFFFFF'}, + {offset: 1, color: color} + ]) + : color; + } + + getLinearGradient(color) { + return store.state.map.mapType == MapTypeEnum.Site + ? new LinearGradient(0, 0, 0, 1, + [ + {offset: 0, color: color}, + {offset: 0.5, color: '#FFFFFF'}, + {offset: 1, color: color} + ]) + : color; + } + + getZ2(index, mapType) { + const model = this._adaptor.get(mapType); + const layer = model.layer || 0; + const dx = model.points[index].x-model.points[index-1].x; + const dy = model.points[index].y-model.points[index-1].y; + return model.points.length>2? dx==0? layer : dy==0? layer+2 : layer+1 : layer+2; + } + + setShape(model) { + const style = this._shape.style; + + if (this._elMap.lines && this._elMap.lines.length) { + this._elMap.lines.forEach((line, index) => { + utils.lineProxy(line, model.points[index], model.points[index+1]); + }); + } + + if (this._elMap.circles && this._elMap.circles.length) { + this._elMap.circles.forEach((circle, index) => { + circle.setShape({ + cx: model.points[index+1].x, + cy: model.points[index+1].y + }); + }); + } + + if (this._elMap.lText) { + const lradian = utils.getRadian(model.points[1], model.points[0]); + this._elMap.lText.setStyle({ + x: model.points[0].x + Math.sin(lradian) * (parseFloat(model.width/2) + style.fontSize + 5), + y: model.points[0].y + Math.cos(lradian) * (parseFloat(model.width/2) + style.fontSize + 5) + }); + } + if (this._elMap.rText) { + const rradian = utils.getRadian(model.points[model.points.length-2], model.points[model.points.length-1]); + this._elMap.rText.setStyle({ + x: model.points[model.points.length-1].x + Math.sin(rradian) * (parseFloat(model.width/2) + style.fontSize + 5), + y: model.points[model.points.length-1].y + Math.cos(rradian) * (parseFloat(model.width/2) + style.fontSize + 5) + }); + } + + if (model.graphList) { + const index = model.sceneTypes.findIndex(ele => ele == Vue.prototype.$map.state.mapType); + model.graphList[index].points = JSON.parse(JSON.stringify(model.points)); + } + + if (this._elMap.line) { + this._elMap.line.setShape({ + points: model.points.map(elem => { return [elem.x, elem.y]; }) + }); + } + + if (this._elMap.flow) { + this._elMap.flow.setShape({ + points: model.points.map(elem => { return [elem.x, elem.y]; }) + }); + } + + if (this._elMap.lArrow) { + const rotation = -Math.atan2( + model.points[1].y-model.points[0].y, + model.points[1].x-model.points[0].x + ); + this._elMap.lArrow.attr('rotation', rotation); + this._elMap.lArrow.setShape({ + x: model.points[0].x, + y: model.points[0].y + }); + } + + if (this._elMap.rArrow) { + const len = model.points.length-1; + const rotation = -Math.atan2( + model.points[len].y-model.points[len-1].y, + model.points[len].x-model.points[len-1].x + ); + this._elMap.rArrow.attr('rotation', rotation); + this._elMap.rArrow.setShape({ + x: model.points[len].x, + y: model.points[len].y + }); + } + } + + setState(model) { + const data = model.entity.data; + const mapType = store.state.map.mapType; + const pipeColorMap = store.state.map.pipeColorMap; + const projectSign = store.state.project.sign; + + if (data && this._elMap.flow) { + if (data.filled) { + this._elMap.flow.show(); + switch (data.from) { + case 'A': this.setFlowRun(data, true); break; + case 'B': this.setFlowRun(data, false); break; + default: this.setFlowStop(); break; + } + + if (data.filler) { + if (projectSign == 'neepu') { + pipeColorMap[data.filler] && this._elMap.flow.setStyle({stroke: pipeColorMap[data.filler].name}); + } else { + const stroke = model.color; + this._elMap.flow.setStyle({stroke}); + } + if (mapType !== MapTypeEnum.Site) { + this._elMap.line.hide(); + } + // this._elMap.line.hide(); + } + } else { + this._elMap.flow.hide(); + if (mapType !== MapTypeEnum.Site) { + this._elMap.line.show(); + } + } + } + } + + dragging(e) { + const model = this._shape.model; + model.points.map(elem => { + elem.x += e.dx; + elem.y += e.dy; + }); + + this.setShape(model); + } + + setFlowRun(data, clockwise) { + const offsetMap = clockwise ? [32, 16, 0] : [0, 16, 32]; + // const flowSpeed = Math.ceil(data.speed); + const flowSpeed = 5; + if (this._elMap.flow) { + this._elMap.flow.stopAnimation(); + if (flowSpeed > 0) { + this._elMap.flow.animate('style', true) + .when(0, { lineDashOffset: offsetMap[0] * flowSpeed }) + .when(1000, { lineDashOffset: offsetMap[1] * flowSpeed }) + .when(2000, { lineDashOffset: offsetMap[2] * flowSpeed }) + .start(); + } + } + + } + + setFlowStop() { + if (this._elMap.flow) { + this._elMap.flow.stopAnimation(); + } + } + + setFlowClear() { + if (this._elMap.flow) { + this.remove(this._elMap.flow); + } + } + + doActive(zr) { + if (zr||this.__zr) { + const style = this._shape.style; + const level = zr||this.__zr; + const falg = handleColor(this._shape.model.color, '#fff'); + const stroke = falg ? style.pipeHover2Color : style.pipeHover2ColorDef; + if (this._elMap.line) { + level.addHover(this._elMap.line, { stroke }); + } + + this._elMap.lines.forEach(elem => { + if (elem) { + level.addHover(elem, { stroke }); + } + }); + + this._elMap.lText && this._elMap.lText.show(); + + this._elMap.rText && this._elMap.rText.show(); + + if (!( + ['Inlet', 'Outlet'].includes(this._shape.model.leftArrow) || + ['Inlet', 'Outlet'].includes(this._shape.model.rightArrow))) { + [this._elMap.lArrow, this._elMap.rArrow].forEach(el =>{ + if (el) { + level.addHover(el, { + stroke: el.shape.path.includes('stroke') + ? stroke + : 'transparent', + fill: el.shape.path.includes('fill') + ? stroke + : 'transparent' + }); + } + }); + } + } + } + + doInactive(zr) { + if (zr||this.__zr) { + const level = zr||this.__zr; + [this._elMap.line, + ...this._elMap.lines, + this._elMap.lText, + this._elMap.rText, + this._elMap.lArrow, + this._elMap.rArrow + ].forEach(elem => { + if (elem) { + level.removeHover(elem); + } + }); + this._elMap.lText && this._elMap.lText.hide(); + + this._elMap.rText && this._elMap.rText.hide(); + } + } + + getViewTipsPoint() {} +} diff --git a/src/iscs_new/package/graph/Measure/index.js b/src/iscs_new/package/graph/Measure/index.js new file mode 100644 index 000000000..46753f758 --- /dev/null +++ b/src/iscs_new/package/graph/Measure/index.js @@ -0,0 +1,183 @@ +import * as color from 'zrender/src/tool/color'; +import * as graphic from '../../../graph/graphic'; +import * as utils from '../../../utils/utils'; +import Vue from 'vue'; +import store from '@/store'; +import ConstConfig from '@/scripts/ConstConfig'; + +class Adaptor { + constructor({model}, state, graph) { + this.__graph = graph; + this.__model = model; + this.__state = state; + } + + get() { + const model = this.__model; + const sceneType = this.__state.mapType; + const block = sceneType ? utils.getBlockBySceneType(model, sceneType) : null; + + this.__graph._block = block; + + return Object.assign(model, block); + } +} + +export default class Measure extends graphic.Group { + constructor(painter, shape, state) { + super(); + this._code = shape.model.code; + this._type = shape.model._type; + this._shape = shape; + this._state = state; + this._painter = painter; + this._state = state; + this._block = null; + this._adaptor = new Adaptor(shape, state, this); + this._elMap = { + text: null + }; + + this.create(); + + this.on('mouseover', this.mouseover, this); + this.on('mouseout', this.mouseout, this); + } + + mouseover(e) { + const model = this._shape.model; + if (this._shape.draw) { + this.doActive(this.__zr); + } else if (model.description) { + this._painter.$tipsHandle.trigger('show', { + x: e.offsetX, + y: e.offsetY, + text: model.description, + target: e.target + }); + } + } + + mouseout(e) { + const map = this._painter.$map; + if (this._shape.draw &&!map.isHover(this._code)) { + this.doInactive(this.__zr); + } else { + this._painter.$tipsHandle.trigger('hide'); + } + } + + create() { + const model = this._adaptor.get(); + const modelLink = Vue.prototype.$maps.getLinkByModel(model); // 关联关系 + let textFill = model.color || '#fff'; + if (modelLink) { + textFill = modelLink.writable ? '#13f95a': model.color || '#fff'; + } + + if (this._block) { + this._elMap.text = new graphic.Text({ + zlevel: model.zlevel, + z: model.z, + style: { + x: model.point.x, + y: model.point.y, + fontFamily: 'Times New Roman', + fontWeight: 'normal', + fontSize: model.size, + textVerticalAlign: 'middle', + textBackgroundColor: 'transparent', + text: this.format('--', model.unit), + textFill: model.color || '#fff', + textAlign: 'center', + textPadding: [3, 3, 1, 3], + rich: { + txt: { + fontSize: model.size, + textVerticalAlign: 'middle', + textFill: textFill + }, + sup: { + fontSize: parseInt(model.size / 3), + textVerticalAlign: 'top' + }, + sub: { + fontSize: parseInt(model.size / 3), + textVerticalAlign: 'bottom' + } + } + } + }); + } + + this.setState(model); + + Object.values(this._elMap).forEach(elem => { elem && elem instanceof Array? elem.forEach(el => this.add(el)): this.add(elem); }); + } + + setShape(model) { + if (this._elMap.text) { + this._elMap.text.setStyle({ + x: model.point.x, + y: model.point.y + }); + } + } + + setState(model) { + const data = model.entity.data ||{}; + const decimalPlace = model.decimalPlace||0; + + if (this._elMap.text && data) { + const value = data.value == undefined? '--' : Number(data.value||0).toFixed(decimalPlace); + this._elMap.text.setStyle({text: this.format(value, model.unit) }); + } + } + + format(value, unit) { + const projectSign = store.state.project.sign; + let msg = value; + if (projectSign != 'neepu') { + const obj = ConstConfig.ConstSelect.UnitTypeList.find(el => el.value == unit); + if (value != '--' && obj && obj.convert) { + msg = obj.convert(value); + } + return `{txt|${msg}} ${unit}`; + } + return `{txt|${msg}} ${unit}`; + } + + dragging(e) { + const model = this._shape.model; + + model.point.x += e.dx; + model.point.y += e.dy; + this.setShape(model); + } + + doActive(zr) { + const style = this._shape.style; + const level = zr||this.__zr; + if (this._elMap.text && level) { + level.addHover(this._elMap.text, { + opacity: style.maskOpacity, + textBackgroundColor: color.lift(style.measureHover2Color, style.liftLevel) + }); + } + } + + doInactive(zr) { + const level = zr||this.__zr; + if (this._elMap.text &&level) { + level.removeHover(this._elMap.text); + } + } + + getViewTipsPoint() { + const model = this._shape.model; + return { + x: model.point.x, + y: model.point.y + }; + } +} diff --git a/src/iscs_new/package/graph/Pid/index.js b/src/iscs_new/package/graph/Pid/index.js new file mode 100644 index 000000000..6f165235b --- /dev/null +++ b/src/iscs_new/package/graph/Pid/index.js @@ -0,0 +1,159 @@ +import * as color from 'zrender/src/tool/color'; +import * as graphic from '../../../graph/graphic'; +import panelType from '../../../constant/panelType'; + +export default class Pid extends graphic.Group { + constructor(painter, shape) { + super(); + this._code = shape.model.code; + this._type = shape.model._type; + this._shape = shape; + this._painter = painter; + this._elMap = { + text: null, + button: null + }; + + this.create(); + + this.on('mouseover', this.mouseover, this); + this.on('mouseout', this.mouseout, this); + } + + mouseover(e) { + const model = this._shape.model; + if (this._shape.draw) { + this._elMap.button.attr({cursor: 'pointer'}); + this.doActive(this.__zr); + } else if (model.description) { + this._painter.$tipsHandle.trigger('show', { + x: e.offsetX, + y: e.offsetY, + text: model.description, + target: e.target + }); + } + } + + mouseout(e) { + const map = this._painter.$map; + if (this._shape.draw && !map.isHover(this._code)) { + this._elMap.button.attr({cursor: 'default'}); + this.doInactive(this.__zr); + } else { + this._painter.$tipsHandle.trigger('hide'); + } + } + + create() { + const model = this._shape.model; + const style = this._shape.style; + + this._elMap.button = new graphic.Rect({ + zlevel: model.zlevel, + z: model.z, + shape: { + x: model.point.x-model.width/2, + y: model.point.y-model.height/2, + width: model.width, + height: model.height, + r: [1] + }, + style: { + fill: style[panelType.Pid].button.fill, + stroke: style[panelType.Pid].button.stroke, + lineWidth: style[panelType.Pid].button.lineWidth, + shadowColor: '#dfdfdf', + shadowOffsetX: 1, + shadowOffsetY: 1 + } + }); + + this._elMap.text = new graphic.Text({ + zlevel: model.zlevel, + z: model.z, + z2: 2, + style: { + x: model.point.x, + y: model.point.y, + fontWeight: style[panelType.Pid].text.fontWeight, + fontFamily: style.fontFamily, + fontSize: model.fontSize, + text: model.text, + textFill: '#000', + textPadding: [4, 4], + textAlign: 'center', + textVerticalAlign: 'middle' + } + }); + + this.setState(model); + + Object.values(this._elMap).forEach(elem => { elem && elem instanceof Array? elem.forEach(el => this.add(el)): this.add(elem); }); + } + + setShape(model) { + if (this._elMap.button) { + this._elMap.button.setShape({ + x: model.point.x-model.width/2, + y: model.point.y-model.height/2 + }); + } + + if (this._elMap.text) { + this._elMap.text.setStyle({ + x: model.point.x, + y: model.point.y + }); + } + } + + setState(model) {} + + dragging(e) { + const model = this._shape.model; + + model.point.x += e.dx; + model.point.y += e.dy; + this.setShape(model); + } + + doActive(zr) { + const style = this._shape.style; + const level = zr||this.__zr; + if (this._elMap.button && level) { + level.addHover(this._elMap.button, { + opacity: style.maskOpacity, + fill: color.lift(style.graphHover2Color, style.liftLevel) + }); + } + + if (this._elMap.text && level) { + level.addHover(this._elMap.text, { + opacity: style.maskOpacity, + textFill: color.lift(style.textHover2Color, style.liftLevel) + }); + } + } + + doInactive(zr) { + const level = zr||this.__zr; + if ( this._elMap.button && level) { + level.removeHover(this._elMap.button); + } + + if ( this._elMap.text && level) { + level.removeHover(this._elMap.text); + } + } + + getViewTipsPoint() { + if (this._elMap.button) { + const button = this._elMap.button.getBoundingRect(); + return { + x: button.x + button.width/2, + y: button.y + }; + } + } +} diff --git a/src/iscs_new/package/graph/Popup/index.js b/src/iscs_new/package/graph/Popup/index.js new file mode 100644 index 000000000..84c05207e --- /dev/null +++ b/src/iscs_new/package/graph/Popup/index.js @@ -0,0 +1,149 @@ +import * as color from 'zrender/src/tool/color'; +import * as graphic from '../../../graph/graphic'; +import panelType from '../../../constant/panelType'; + +export default class Popup extends graphic.Group { + constructor(painter, shape) { + super(); + this._code = shape.model.code; + this._type = shape.model._type; + this._shape = shape; + this._painter = painter; + this._elMap = { + text: null, + button: null + }; + + this.create(); + + this.on('mouseover', this.mouseover, this); + this.on('mouseout', this.mouseout, this); + } + + mouseover(e) { + if (this._shape.draw) { + this._elMap.button.attr({cursor: 'pointer'}); + this.doActive(this.__zr); + } + } + + mouseout(e) { + const map = this._painter.$map; + if (this._shape.draw && !map.isHover(this._code)) { + this._elMap.button.attr({cursor: 'default'}); + this.doInactive(this.__zr); + } + } + + create() { + const model = this._shape.model; + const style = this._shape.style; + + this._elMap.button = new graphic.Rect({ + zlevel: model.zlevel, + z: model.z, + shape: { + x: model.point.x-model.width/2, + y: model.point.y-model.height/2, + width: model.width, + height: model.height, + r: [1] + }, + style: { + fill: style[panelType.Popup].button.fill, + stroke: style[panelType.Popup].button.stroke, + lineWidth: style[panelType.Popup].button.lineWidth, + shadowColor: '#dfdfdf', + shadowOffsetX: 1, + shadowOffsetY: 1 + } + }); + + this._elMap.text = new graphic.Text({ + zlevel: model.zlevel, + z: model.z, + z2: 2, + style: { + x: model.point.x, + y: model.point.y, + fontWeight: style[panelType.Popup].text.fontWeight, + fontFamily: style.fontFamily, + fontSize: model.fontSize, + text: model.text, + textFill: '#000', + textPadding: [4, 4], + textAlign: 'center', + textVerticalAlign: 'middle' + } + }); + + this.setState(model); + + Object.values(this._elMap).forEach(elem => { elem && elem instanceof Array? elem.forEach(el => this.add(el)): this.add(elem); }); + } + + setShape(model) { + if (this._elMap.button) { + this._elMap.button.setShape({ + x: model.point.x-model.width/2, + y: model.point.y-model.height/2 + }); + } + + if (this._elMap.text) { + this._elMap.text.setStyle({ + x: model.point.x, + y: model.point.y + }); + } + } + + setState(model) {} + + dragging(e) { + const model = this._shape.model; + + model.point.x += e.dx; + model.point.y += e.dy; + this.setShape(model); + } + + doActive(zr) { + const style = this._shape.style; + const level = zr||this.__zr; + if (this._elMap.button && level) { + level.addHover(this._elMap.button, { + opacity: style.maskOpacity, + fill: color.lift(style.graphHover2Color, style.liftLevel) + }); + } + + if (this._elMap.text && level) { + level.addHover(this._elMap.text, { + opacity: style.maskOpacity, + textFill: color.lift(style.textHover2Color, style.liftLevel) + }); + } + } + + doInactive(zr) { + const level = zr||this.__zr; + if ( this._elMap.button && level) { + level.removeHover(this._elMap.button); + } + + if ( this._elMap.text && level) { + level.removeHover(this._elMap.text); + } + } + + getViewTipsPoint() { + if (this._elMap.button) { + const button = this._elMap.button.getBoundingRect(); + return { + x: button.x + button.width/2, + y: button.y + }; + } + } +} diff --git a/src/iscs_new/package/graph/ProgramControl/index.js b/src/iscs_new/package/graph/ProgramControl/index.js new file mode 100644 index 000000000..01b80058c --- /dev/null +++ b/src/iscs_new/package/graph/ProgramControl/index.js @@ -0,0 +1,308 @@ +import * as color from 'zrender/src/tool/color'; +import * as graphic from '../../../graph/graphic'; +import panelType from '../../../constant/panelType'; + +export default class ProgramControl extends graphic.Group { + constructor(painter, shape) { + super(); + this._code = shape.model.code; + this._type = shape.model._type; + this._shape = shape; + this._painter = painter; + this._elMap = { + line: null, + button: null, + blockStart: null, + blockReset: null, + blockStop: null, + start: null, + reset: null, + stop: null + }; + + this.create(); + + this.on('mouseover', this.mouseover, this); + this.on('mouseout', this.mouseout, this); + } + + mouseover(e) { + const model = this._shape.model; + if (this._shape.draw) { + this._elMap.button.attr({cursor: 'pointer'}); + this.doActive(this.__zr); + } else if (model.description) { + this._painter.$tipsHandle.trigger('show', { + x: e.offsetX, + y: e.offsetY, + text: model.description, + target: e.target + }); + } + } + + mouseout(e) { + const map = this._painter.$map; + if (this._shape.draw && !map.isHover(this._code)) { + this._elMap.button.attr({cursor: 'default'}); + this.doInactive(this.__zr); + } else { + this._painter.$tipsHandle.trigger('hide'); + } + } + + create() { + const model = this._shape.model; + const style = this._shape.style; + + this._elMap.line = new graphic.Line({ + zlevel: model.zlevel, + z: model.z, + z2: 9, + shape: { + x1: model.point.x+style[panelType.ProgramControl].button.width/2, + y1: model.point.y+style[panelType.ProgramControl].button.height/2, + x2: model.point.x-style[panelType.ProgramControl].button.width/2, + y2: model.point.y-style[panelType.ProgramControl].button.height/2 + }, + style: { + stroke: style[panelType.ProgramControl].line.stroke, + lineWidth: style[panelType.ProgramControl].line.lineWidth, + lineCap: 'round' + } + }); + + this._elMap.button = new graphic.Rect({ + zlevel: model.zlevel, + z: model.z, + shape: { + x: model.point.x-style[panelType.ProgramControl].button.width/2, + y: model.point.y-style[panelType.ProgramControl].button.height/2, + width: style[panelType.ProgramControl].button.width, + height: style[panelType.ProgramControl].button.height, + r: [1] + }, + style: { + fill: style[panelType.ProgramControl].button.fill, + stroke: style[panelType.ProgramControl].button.stroke, + lineWidth: style[panelType.ProgramControl].button.lineWidth + } + }); + + this._elMap.blockStart = new graphic.Rect({ + zlevel: model.zlevel, + z: model.z, + z2: 3, + shape: { + x: model.point.x-style[panelType.ProgramControl].button.width/2, + y: model.point.y-style[panelType.ProgramControl].button.height/2, + width: style[panelType.ProgramControl].button.width/3, + height: style[panelType.ProgramControl].button.height, + r: [1] + }, + style: { + fill: style[panelType.ProgramControl].block.fill, + stroke: style[panelType.ProgramControl].block.stroke, + lineWidth: style[panelType.ProgramControl].block.lineWidth + } + }); + + this._elMap.blockReset = new graphic.Rect({ + zlevel: model.zlevel, + z: model.z, + z2: 3, + shape: { + x: model.point.x-style[panelType.ProgramControl].button.width/2+style[panelType.ProgramControl].button.width/3, + y: model.point.y-style[panelType.ProgramControl].button.height/2, + width: style[panelType.ProgramControl].button.width/3, + height: style[panelType.ProgramControl].button.height, + r: [1] + }, + style: { + fill: style[panelType.ProgramControl].block.fill, + stroke: style[panelType.ProgramControl].block.stroke, + lineWidth: style[panelType.ProgramControl].block.lineWidth + } + }); + + this._elMap.blockStop = new graphic.Rect({ + zlevel: model.zlevel, + z: model.z, + z2: 3, + shape: { + x: model.point.x-style[panelType.ProgramControl].button.width/2+style[panelType.ProgramControl].button.width/3*2, + y: model.point.y-style[panelType.ProgramControl].button.height/2, + width: style[panelType.ProgramControl].button.width/3, + height: style[panelType.ProgramControl].button.height, + r: [1] + }, + style: { + fill: style[panelType.ProgramControl].block.fill, + stroke: style[panelType.ProgramControl].block.stroke, + lineWidth: style[panelType.ProgramControl].block.lineWidth, + r: [1] + } + }); + + this._elMap.start = new graphic.Svg({ + zlevel: model.zlevel, + z: model.z, + z2: 5, + origin: [0, 0], + rotation: 0, + scale: [1, 1], + shape: { + x: model.point.x-style[panelType.ProgramControl].button.width/2 + style[panelType.ProgramControl].button.width/6, + y: model.point.y-style[panelType.ProgramControl].button.height/2, + path: 'M6 12 L-4 6 L-4 18Z' + }, + style: { + fill: style[panelType.ProgramControl].indicate.fill + } + }); + + this._elMap.reset = new graphic.Svg({ + zlevel: model.zlevel, + z: model.z, + z2: 5, + origin: [0, 0], + rotation: 0, + scale: [1, 1], + shape: { + x: model.point.x-style[panelType.ProgramControl].button.width/2+style[panelType.ProgramControl].button.width/3 + style[panelType.ProgramControl].button.width/6, + y: model.point.y-style[panelType.ProgramControl].button.height/2, + path: 'M6 6 L6 18 L1 18 L1 6Z M-6 6 L-6 18 L-1 18 L-1 6Z' + }, + style: { + fill: style[panelType.ProgramControl].indicate.fill + } + }); + + this._elMap.stop = new graphic.Svg({ + zlevel: model.zlevel, + z: model.z, + z2: 5, + origin: [0, 0], + rotation: 0, + scale: [1, 1], + shape: { + x: model.point.x-style[panelType.ProgramControl].button.width/2+style[panelType.ProgramControl].button.width/3*2 + style[panelType.ProgramControl].button.width/6, + y: model.point.y-style[panelType.ProgramControl].button.height/2, + path: 'M6 6 L6 18 L-6 18 L-6 6Z' + }, + style: { + fill: style[panelType.ProgramControl].indicate.fill + } + }); + + this.setState(model); + + Object.values(this._elMap).forEach(elem => { elem && elem instanceof Array? elem.forEach(el => this.add(el)): this.add(elem); }); + } + + setShape(model) { + const style = this._shape.style; + if (this._elMap.line) { + this._elMap.line.setShape({ + x1: model.point.x+style[panelType.ProgramControl].button.width/2, + y1: model.point.y+style[panelType.ProgramControl].button.height/2, + x2: model.point.x-style[panelType.ProgramControl].button.width/2, + y2: model.point.y-style[panelType.ProgramControl].button.height/2 + }); + } + + if (this._elMap.button) { + this._elMap.button.setShape({ + x: model.point.x-style[panelType.ProgramControl].button.width/2, + y: model.point.y-style[panelType.ProgramControl].button.height/2 + }); + } + + if (this._elMap.blockStart) { + this._elMap.blockStart.setShape({ + x: model.point.x-style[panelType.ProgramControl].button.width/2, + y: model.point.y-style[panelType.ProgramControl].button.height/2, + width: style[panelType.ProgramControl].button.width/3, + height: style[panelType.ProgramControl].button.height + }); + } + + if (this._elMap.blockReset) { + this._elMap.blockReset.setShape({ + x: model.point.x-style[panelType.ProgramControl].button.width/2+style[panelType.ProgramControl].button.width/3, + y: model.point.y-style[panelType.ProgramControl].button.height/2, + width: style[panelType.ProgramControl].button.width/3, + height: style[panelType.ProgramControl].button.height + }); + } + + if (this._elMap.blockStop) { + this._elMap.blockStop.setShape({ + x: model.point.x-style[panelType.ProgramControl].button.width/2+style[panelType.ProgramControl].button.width/3*2, + y: model.point.y-style[panelType.ProgramControl].button.height/2, + width: style[panelType.ProgramControl].button.width/3, + height: style[panelType.ProgramControl].button.height + }); + } + + if (this._elMap.start) { + this._elMap.start.setShape({ + x: model.point.x-style[panelType.ProgramControl].button.width/2 + style[panelType.ProgramControl].button.width/6, + y: model.point.y-style[panelType.ProgramControl].button.height/2 + }); + } + + if (this._elMap.reset) { + this._elMap.reset.setShape({ + x: model.point.x-style[panelType.ProgramControl].button.width/2+style[panelType.ProgramControl].button.width/3 + style[panelType.ProgramControl].button.width/6, + y: model.point.y-style[panelType.ProgramControl].button.height/2 + }); + } + + if (this._elMap.stop) { + this._elMap.stop.setShape({ + x: model.point.x-style[panelType.ProgramControl].button.width/2+style[panelType.ProgramControl].button.width/3*2 + style[panelType.ProgramControl].button.width/6, + y: model.point.y-style[panelType.ProgramControl].button.height/2 + }); + } + } + + setState(model) {} + + dragging(e) { + const model = this._shape.model; + + model.point.x += e.dx; + model.point.y += e.dy; + this.setShape(model); + } + + doActive(zr) { + const style = this._shape.style; + const level = zr||this.__zr; + if (this._elMap.button && level) { + level.addHover(this._elMap.button, { + opacity: style.maskOpacity, + fill: color.lift(style.graphHover2Color, style.liftLevel), + stroke: color.lift(style.graphHover2Color, style.liftLevel) + }); + } + } + + doInactive(zr) { + const level = zr||this.__zr; + if ( this._elMap.button && level) { + level.removeHover(this._elMap.button); + } + } + + getViewTipsPoint() { + if (this._elMap.button) { + const button = this._elMap.button.getBoundingRect(); + return { + x: button.x + button.width/2, + y: button.y + }; + } + } +} diff --git a/src/iscs_new/package/graph/Switching/index.js b/src/iscs_new/package/graph/Switching/index.js new file mode 100644 index 000000000..8a0e47d05 --- /dev/null +++ b/src/iscs_new/package/graph/Switching/index.js @@ -0,0 +1,195 @@ +import * as color from 'zrender/src/tool/color'; +import * as graphic from '../../../graph/graphic'; +import panelType from '../../../constant/panelType'; + +export default class Switching extends graphic.Group { + constructor(painter, shape) { + super(); + this._code = shape.model.code; + this._type = shape.model._type; + this._shape = shape; + this._painter = painter; + this._elMap = { + text: null, + button: null + }; + + this.create(); + + this.on('mouseover', this.mouseover, this); + this.on('mouseout', this.mouseout, this); + this.on('mousedown', this.mousedown, this); + this.on('mouseup', this.mouseup, this); + } + + mousedown(e) { + const model = this._shape.model; + if (model.isReset && + !this._shape.draw && + this._elMap.button) { + this._elMap.button.setStyle({ + fill: '#FF0000' + }); + } + } + + mouseup(e) { + const model = this._shape.model; + const style = this._shape.style; + if (model.isReset && + !this._shape.draw && + this._elMap.button) { + setTimeout(() => { + this._elMap.button.setStyle({ + fill: style[panelType.Switching].button.fill + }); + }, 200); + + } + } + + mouseover(e) { + if (this._shape.draw) { + this._elMap.button.attr({cursor: 'pointer'}); + this.doActive(this.__zr); + } + } + + mouseout(e) { + const map = this._painter.$map; + if (this._shape.draw && !map.isHover(this._code)) { + this._elMap.button.attr({cursor: 'default'}); + this.doInactive(this.__zr); + } + } + + create() { + const model = this._shape.model; + const style = this._shape.style; + + this._elMap.button = new graphic.Rect({ + zlevel: model.zlevel, + z: model.z, + shape: { + x: model.point.x-model.width/2, + y: model.point.y-model.height/2, + width: model.width, + height: model.height, + r: [1] + }, + style: { + fill: style[panelType.Switching].button.fill, + stroke: style[panelType.Switching].button.stroke, + lineWidth: style[panelType.Switching].button.lineWidth, + shadowColor: '#dfdfdf', + shadowOffsetX: 1, + shadowOffsetY: 1 + } + }); + + this._elMap.text = new graphic.Text({ + zlevel: model.zlevel, + z: model.z, + z2: 2, + style: { + x: model.point.x, + y: model.point.y, + fontWeight: style[panelType.Switching].text.fontWeight, + fontFamily: style.fontFamily, + fontSize: model.fontSize, + text: model.putInText, + textFill: '#000', + textPadding: [4, 4], + textAlign: 'center', + textVerticalAlign: 'middle' + } + }); + + this.setState(model); + + Object.values(this._elMap).forEach(elem => { elem && elem instanceof Array? elem.forEach(el => this.add(el)): this.add(elem); }); + } + + setShape(model) { + if (this._elMap.button) { + this._elMap.button.setShape({ + x: model.point.x-model.width/2, + y: model.point.y-model.height/2 + }); + } + + if (this._elMap.text) { + this._elMap.text.setStyle({ + x: model.point.x, + y: model.point.y + }); + } + } + + setState(model) { + const entity = model.entity||{}; + const data = entity.data ||{}; + if (!model.isReset && + !this._shape.draw && + entity.data) { + if (this._elMap.button) { + this._elMap.button.setStyle({ + fill: data.status? '#FF0000' : '#3CB371' + }); + } + + if (this._elMap.text) { + this._elMap.text.setStyle({ + text: data.status? model.putInText: model.cutOffText + }); + } + } + } + + dragging(e) { + const model = this._shape.model; + + model.point.x += e.dx; + model.point.y += e.dy; + this.setShape(model); + } + + doActive(zr) { + const style = this._shape.style; + const level = zr||this.__zr; + if (this._elMap.button && level) { + level.addHover(this._elMap.button, { + opacity: style.maskOpacity, + fill: color.lift(style.graphHover2Color, style.liftLevel) + }); + } + + if (this._elMap.text && level) { + level.addHover(this._elMap.text, { + opacity: style.maskOpacity, + textFill: color.lift(style.textHover2Color, style.liftLevel) + }); + } + } + + doInactive(zr) { + const level = zr||this.__zr; + if ( this._elMap.button && level) { + level.removeHover(this._elMap.button); + } + + if ( this._elMap.text && level) { + level.removeHover(this._elMap.text); + } + } + + getViewTipsPoint() { + if (this._elMap.button) { + const button = this._elMap.button.getBoundingRect(); + return { + x: button.x + button.width/2, + y: button.y + }; + } + } +} diff --git a/src/iscs_new/package/graph/Table/constant/export.js b/src/iscs_new/package/graph/Table/constant/export.js new file mode 100644 index 000000000..15557e243 --- /dev/null +++ b/src/iscs_new/package/graph/Table/constant/export.js @@ -0,0 +1,12 @@ +export {default as Table_Template} from './table-template.js'; +export {default as Table_Water_Device_Screen} from './table-water-device-screen.js'; +export {default as Table_Water_Elements} from './table-water-elements.js'; +export {default as Table_Supercritical_Furnace_Sampling} from './table-supercritical-furnace-sampling.js'; + +export const templateList = [ + {value: 'Table-Template', label: '模板示例'}, + {value: 'Table-Water-Device-Screen', label: '水汽取样装置-设备表'}, + {value: 'Table-Water-Elements', label: '水汽取样装置-元素表'}, + {value: 'Table-Supercritical-Furnace-Sampling', label: '超临界直流炉取样点-设备表'} +] +; diff --git a/src/iscs_new/package/graph/Table/constant/table-supercritical-furnace-sampling.js b/src/iscs_new/package/graph/Table/constant/table-supercritical-furnace-sampling.js new file mode 100644 index 000000000..742d19ca4 --- /dev/null +++ b/src/iscs_new/package/graph/Table/constant/table-supercritical-furnace-sampling.js @@ -0,0 +1,176 @@ +const textStyle = { + fontSize: 14, + fontWeight: 'bold', + fontFamily: 'consolas', + textFill: '#0000FF', + textAlign: 'center', + textVerticalAlign: 'middle' +}; + +const orderStyle = { + fontSize: 14, + fontWeight: 'bold', + fontFamily: 'consolas', + textFill: '#000000', + textAlign: 'center', + textVerticalAlign: 'middle' +}; + +export default { + z2: 1, + shape: { + dataSource: [ + [ + { + type: 'text', + text: '序号', + ...textStyle + }, + { + type: 'order', + text: '1', + ...orderStyle + }, + { + type: 'order', + text: '2', + ...orderStyle + }, + { + type: 'order', + text: '3', + ...orderStyle + }, + { + type: 'order', + text: '4', + ...orderStyle + }, + { + type: 'order', + text: '5', + ...orderStyle + }, + { + type: 'order', + text: '6', + ...orderStyle + }, + { + type: 'order', + text: '7', + ...orderStyle + }, + { + type: 'order', + text: '8', + ...orderStyle + }, + { + type: 'order', + text: '9', + ...orderStyle + }, + { + type: 'order', + text: '10', + ...orderStyle + }, + { + type: 'order', + text: '11', + ...orderStyle + }, + { + type: 'order', + text: '12', + ...orderStyle + }, + { + type: 'order', + text: '13', + ...orderStyle + } + ], + [ + { + type: 'text', + text: '名称', + ...textStyle + }, + { + type: 'text', + text: '除氧器出口', + ...textStyle + }, + { + type: 'text', + text: '除氧器入口', + ...textStyle + }, + { + type: 'text', + text: '省煤器入口', + ...textStyle + }, + { + type: 'text', + text: '启动分离器排水', + ...textStyle + }, + { + type: 'text', + text: '顶棚入口', + ...textStyle + }, + { + type: 'text', + text: '饱和蒸汽', + ...textStyle + }, + { + type: 'text', + text: '过热蒸汽', + ...textStyle + }, + { + type: 'text', + text: '再热蒸汽出口', + ...textStyle + }, + { + type: 'text', + text: '凝结水泵出口', + ...textStyle + }, + { + type: 'text', + text: '高压加热器疏水', + ...textStyle + }, + { + type: 'text', + text: '低压加热器疏水', + ...textStyle + }, + { + type: 'text', + text: '加氨、加氧点后', + ...textStyle + }, + { + type: 'text', + text: '凝补水箱入口', + ...textStyle + } + ] + ], + wList: [60, ...new Array(13).fill(110)], + hList: new Array(2).fill(32) + }, + style: { + lineWidth: 1, + backgroundColor: '#ffffcc', + stroke: '#000000' + } +}; diff --git a/src/iscs_new/package/graph/Table/constant/table-template.js b/src/iscs_new/package/graph/Table/constant/table-template.js new file mode 100644 index 000000000..85f33647f --- /dev/null +++ b/src/iscs_new/package/graph/Table/constant/table-template.js @@ -0,0 +1,58 @@ +export default { + z2: 1, + shape: { + dataSource: [ + [ + { + type: 'order', + fontSize: 14, + fontWeight: 'bold', + fontFamily: 'consolas', + text: '1', + textFill: '#000', + textAlign: 'center', + textVerticalAlign: 'middle' + }, { + type: 'button', + fontSize: 16, + fontWeight: 'normal', + fontFamily: 'consolas', + text: 'button', + textFill: '#000', + textAlign: 'center', + textVerticalAlign: 'middle' + } + ], + [ + { + type: 'element', + fontSize: 16, + fontWeight: 'bold', + fontFamily: 'consolas', + text: 'element', + textFill: '#000', + textAlign: 'center', + textVerticalAlign: 'middle' + }, + { + type: 'text', + name: '3', + fontSize: 22, + fontWeight: 'bold', + fontFamily: 'consolas', + text: 'text', + textFill: '#000', + textAlign: 'center', + textVerticalAlign: 'middle' + } + ] + ], + wList: [180, 180, 180], + hList: [36, 36, 36] + }, + style: { + lineWidth: 1, + backgroundColor: '#ffffcc', + stroke: '#000000' + } +}; diff --git a/src/iscs_new/package/graph/Table/constant/table-water-device-screen.js b/src/iscs_new/package/graph/Table/constant/table-water-device-screen.js new file mode 100644 index 000000000..9acadf497 --- /dev/null +++ b/src/iscs_new/package/graph/Table/constant/table-water-device-screen.js @@ -0,0 +1,176 @@ +const textStyle = { + fontSize: 14, + fontWeight: 'bold', + fontFamily: 'consolas', + textFill: '#0000FF', + textAlign: 'center', + textVerticalAlign: 'middle' +}; + +const orderStyle = { + fontSize: 14, + fontWeight: 'bold', + fontFamily: 'consolas', + textFill: '#000000', + textAlign: 'center', + textVerticalAlign: 'middle' +}; + +export default { + z2: 1, + shape: { + dataSource: [ + [ + { + type: 'text', + text: '序号', + ...textStyle + }, + { + type: 'order', + text: '1', + ...orderStyle + }, + { + type: 'order', + text: '2', + ...orderStyle + }, + { + type: 'order', + text: '3', + ...orderStyle + }, + { + type: 'order', + text: '4', + ...orderStyle + }, + { + type: 'order', + text: '5', + ...orderStyle + }, + { + type: 'order', + text: '6', + ...orderStyle + }, + { + type: 'order', + text: '7', + ...orderStyle + }, + { + type: 'order', + text: '8', + ...orderStyle + }, + { + type: 'order', + text: '9', + ...orderStyle + }, + { + type: 'order', + text: '10', + ...orderStyle + }, + { + type: 'order', + text: '11', + ...orderStyle + }, + { + type: 'order', + text: '12', + ...orderStyle + }, + { + type: 'order', + text: '13', + ...orderStyle + } + ], + [ + { + type: 'text', + text: '名称', + ...textStyle + }, + { + type: 'text', + text: '凝结水泵出口', + ...textStyle + }, + { + type: 'text', + text: '除氧器入口', + ...textStyle + }, + { + type: 'text', + text: '除氧器出口', + ...textStyle + }, + { + type: 'text', + text: '省煤器进口', + ...textStyle + }, + { + type: 'text', + text: '主蒸汽', + ...textStyle + }, + { + type: 'text', + text: '饱和蒸汽', + ...textStyle + }, + { + type: 'text', + text: '炉水', + ...textStyle + }, + { + type: 'text', + text: '再热气入口', + ...textStyle + }, + { + type: 'text', + text: '再热气出口', + ...textStyle + }, + { + type: 'text', + text: '低加热出口', + ...textStyle + }, + { + type: 'text', + text: '精处理', + ...textStyle + }, + { + type: 'text', + text: '补给水箱入口', + ...textStyle + }, + { + type: 'text', + text: '补给水泵出口', + ...textStyle + } + ] + ], + wList: [60, ...new Array(13).fill(110)], + hList: new Array(2).fill(32) + }, + style: { + lineWidth: 1, + backgroundColor: '#ffffcc', + stroke: '#000000' + } +}; diff --git a/src/iscs_new/package/graph/Table/constant/table-water-elements.js b/src/iscs_new/package/graph/Table/constant/table-water-elements.js new file mode 100644 index 000000000..144cf2857 --- /dev/null +++ b/src/iscs_new/package/graph/Table/constant/table-water-elements.js @@ -0,0 +1,129 @@ +const textStyle = { + fontSize: 14, + fontWeight: 'bold', + fontFamily: 'consolas', + textFill: '#0000FF', + textAlign: 'center', + textVerticalAlign: 'middle' +}; + +const richStyle = { + fontSize: 14, + fontWeight: 'bold', + fontFamily: 'consolas', + textFill: '#0000FF', + textAlign: 'center', + rich: { + sup: { + fontSize: 6, + textVerticalAlign: 'top' + }, + sub: { + fontSize: 6, + textVerticalAlign: 'bottom' + } + } +}; + +export default { + z2: 1, + shape: { + dataSource: [ + [ + { + type: 'text', + text: 'PH', + ...richStyle + }, + { + type: 'text', + text: 'PH分析仪', + ...textStyle + }, + { + type: 'text', + text: 'N{sub|2}H{sub|4}', + ...richStyle + }, + { + type: 'text', + text: '联氨分析仪', + ...textStyle + } + ], + [ + { + type: 'text', + text: 'CC', + ...richStyle + }, + { + type: 'text', + text: '阳电导率分析仪', + ...textStyle + }, + { + type: 'text', + text: 'SO{sub|2}', + ...richStyle + }, + { + type: 'text', + text: '硅酸根分析仪', + ...textStyle + } + ], + [ + { + type: 'text', + text: 'SC', + ...richStyle + }, + { + type: 'text', + text: '比电导率分析仪', + ...textStyle + }, + { + type: 'text', + text: 'PO{sub|4}{sup|3-}', + ...richStyle + }, + { + type: 'text', + text: '磷酸根分析仪', + ...textStyle + } + ], + [ + { + type: 'text', + text: 'O{sub|2}', + ...richStyle + }, + { + type: 'text', + text: '溶解氧分析仪', + ...textStyle + }, + { + type: 'text', + text: 'NA', + ...richStyle + }, + { + type: 'text', + text: '钠离子分析仪', + ...textStyle + } + ] + ], + wList: [60, 140, 60, 140], + hList: [32, 32, 32, 32] + }, + style: { + lineWidth: 1, + backgroundColor: '#ffffcc', + stroke: '#000000' + } +}; diff --git a/src/iscs_new/package/graph/Table/index.js b/src/iscs_new/package/graph/Table/index.js new file mode 100644 index 000000000..b6aaf5f44 --- /dev/null +++ b/src/iscs_new/package/graph/Table/index.js @@ -0,0 +1,144 @@ +import * as graphic from '../../../graph/graphic'; +import panelType from '../../../constant/panelType'; + +export default class Table extends graphic.Group { + constructor(painter, shape) { + super(); + this._code = shape.model.code; + this._type = shape.model._type; + this._shape = shape; + this._painter = painter; + this._elMap = { + table: null + }; + + this.create(); + + this.on('mouseover', this.mouseover, this); + this.on('mouseout', this.mouseout, this); + } + + mouseover(e) { + if (this._shape.draw) { + this.doActive(this.__zr); + } + } + + mouseout(e) { + const map = this._painter.$map; + if (this._shape.draw && !map.isHover(this._code)) { + this.doInactive(this.__zr); + } + } + + create() { + const draw = this._shape.draw; + const model = this._shape.model; + const style = this._shape.style; + + this._elMap.header = new graphic.Rect({ + zlevel: model.zlevel, + z: model.z, + z2: -1, + cursor: draw? 'pointer': 'default', + shape: { + x: model.point.x, + y: model.point.y, + width: model.width, + height: style[panelType.Table].header.height + }, + style: { + stroke: model.lineColor, + lineWidth: model.lineWidth, + fill: model.headerBg + } + }); + + this._elMap.body = new graphic.Rect({ + zlevel: model.zlevel, + z: model.z, + z2: -1, + silent: true, + shape: { + x: model.point.x, + y: model.point.y+style[panelType.Table].header.height, + width: model.width, + height: model.height + }, + style: { + stroke: model.lineColor, + lineWidth: model.lineWidth, + fill: model.bodyBg + } + }); + + this._elMap.title = new graphic.Text({ + zlevel: model.zlevel, + z: model.z, + z2: 0, + cursor: draw? 'pointer': 'default', + style: { + x: model.point.x+model.width/2, + y: model.point.y+style[panelType.Table].header.height/2, + fontWeight: style[panelType.Table].header.fontWeight, + fontSize: style[panelType.Table].header.fontSize, + fontFamily: style.fontFamily, + text: model.title||'标题', + textAlign: 'center', + textVerticalAlign: 'middle' + } + }); + + Object.values(this._elMap).forEach(elem => { elem && elem instanceof Array? elem.forEach(el => this.add(el)): this.add(elem); }); + + } + + setShape(model) { + const style = this._shape.style; + + if (this._elMap.header) { + this._elMap.header.setShape({ + x: model.point.x, + y: model.point.y + }); + } + + if (this._elMap.body) { + this._elMap.body.setShape({ + x: model.point.x, + y: model.point.y+style[panelType.Table].header.height + }); + } + + if (this._elMap.title) { + this._elMap.title.setStyle({ + x: model.point.x+model.width/2, + y: model.point.y+style[panelType.Table].header.height/2 + }); + } + } + + setState(model, e) { + + } + + dragging(e) { + const model = this._shape.model; + + model.point.x += e.dx; + model.point.y += e.dy; + + this.setShape(model); + } + + doActive(zr) { + + } + + doInactive(zr) { + + } + + getViewTipsPoint() {} + +} diff --git a/src/iscs_new/package/graph/Table/tableIndex.js b/src/iscs_new/package/graph/Table/tableIndex.js new file mode 100644 index 000000000..1dbf9eb57 --- /dev/null +++ b/src/iscs_new/package/graph/Table/tableIndex.js @@ -0,0 +1,111 @@ +import store from '@/store'; +import * as color from 'zrender/src/tool/color'; +import * as graphic from '../../../graph/graphic'; +import * as View from './constant/export.js'; +import { transformed } from '../../../utils/transform'; + +export default class Table extends graphic.Group { + constructor(painter, shape) { + super(); + this._code = shape.model.code; + this._type = shape.model._type; + this._shape = shape; + this._painter = painter; + this._elMap = { + table: null + }; + + this.create(); + + this.on('mouseover', this.mouseover, this); + this.on('mouseout', this.mouseout, this); + } + + mouseover(e) { + if (this._shape.draw) { + this.doActive(this.__zr); + } + } + + mouseout(e) { + const map = this._painter.$map; + if (this._shape.draw && !map.isHover(this._code)) { + this.doInactive(this.__zr); + } + } + + create() { + const draw = this._shape.draw; + const mapType = store.state.map.mapType; + const model = this._shape.model; + const template = (model.template || 'Table-Template').replace(/-/g, '_'); + const option = View[template]; + + if (model.sceneTypes && model.sceneTypes.includes(mapType)) { + this._elMap.table = new graphic.Table({ + zlevel: model.zlevel || option.zlevel, + z: model.z || option.z, + z2: model.z2 || option.z2, + cursor: draw? 'pointer': 'default', + shape: { + point: model.point, + ...option.shape + }, + style: option.style + }); + + transformed(this._elMap.table, { + scale: [model.scale, model.scale], + rotation: model.rotation || 0 + }); + } + + Object.values(this._elMap).forEach(elem => { elem && elem instanceof Array? elem.forEach(el => this.add(el)): this.add(elem); }); + + } + + setShape(model) { + + } + + setState(model, e) { + + } + + dragging(e) { + const model = this._shape.model; + const scale = model.scale; + + model.point.x += e.dx / scale; + model.point.y += e.dy / scale; + + if (this._elMap.table) { + this._elMap.table.dragging({dx: e.dx/scale, dy: e.dy/scale}); + } + + this.setShape(model); + } + + doActive(zr) { + const style = this._shape.style; + const table = this._elMap.table; + const level = zr||this.__zr; + if (table && table._elMap.bg && level) { + level.addHover(table._elMap.bg, { + opacity: style.maskOpacity, + fill: color.lift(style.maskHover2Color, style.liftLevel) + }); + } + } + + doInactive(zr) { + const table = this._elMap.table; + const level = zr||this.__zr; + if (table && table._elMap.bg && level) { + level.removeHover(table._elMap.bg); + } + } + + getShapeTipsPoint(step) {} + +} diff --git a/src/iscs_new/package/graph/Text/index.js b/src/iscs_new/package/graph/Text/index.js new file mode 100644 index 000000000..a090263f4 --- /dev/null +++ b/src/iscs_new/package/graph/Text/index.js @@ -0,0 +1,136 @@ +import * as color from 'zrender/src/tool/color'; +import * as graphic from '../../../graph/graphic'; +import store from '@/store'; + +export default class Text2 extends graphic.Group { + constructor(painter, shape) { + super(); + this._code = shape.model.code; + this._type = shape.model._type; + this._shape = shape; + this._painter = painter; + + this._rotation = null; + this._origin = null; + + this._elMap = { + text: null + }; + + this.create(); + + this.on('mouseover', this.mouseover, this); + this.on('mouseout', this.mouseout, this); + } + + mouseover(e) { + if (this._shape.draw) { + this.doActive(this.__zr); + } + } + + mouseout(e) { + const map = this._painter.$map; + if (this._shape.draw && !map.isHover(this._code)) { + this.doInactive(this.__zr); + } + } + + create() { + const draw = this._shape.draw; + const mapType = store.state.map.mapType; + const model = this._shape.model; + const backGroundColor = this.getTextBgColor(model); + const textStyle = this.getTextStyle(model); + + this._rotation = -Math.PI / 180 * Number(model.rotate||0); + this._origin = [model.point.x, model.point.y]; + + if (model.sceneTypes && model.sceneTypes.includes(mapType)) { + this._elMap.text = new graphic.Text({ + zlevel: model.zlevel, + z: model.z, + origin: this._origin, + rotation: this._rotation, + silent: !draw, + style: { + x: model.point.x, + y: model.point.y, + fontWeight: 'normal', + textBackgroundColor: backGroundColor, + fontSize: model.fontSize, + fontFamily: model.font, + text: textStyle.textValue || textStyle.value || '', + textLineHeight: model.fontSize+4, + textFill: model.fontColor, + textPadding: [4, 4], + textAlign: textStyle.textAlign, + textVerticalAlign: 'middle' + } + }); + } + + this.setState(model); + + Object.values(this._elMap).forEach(elem => { elem && elem instanceof Array? elem.forEach(el => this.add(el)): this.add(elem); }); + } + + getTextStyle(model) { + const pattern = /\{<(?\w+)>\}\{<(?\w+)>\}(?(.|\n)*)|(?(.|\n)*)/; + const groups = (pattern.exec(model.name)||{}).groups||{}; + return groups; + } + + getTextBgColor(model) { + const pattern = /\{<(?\w+)>\}(?(.|\n)*)/; + const groups = (pattern.exec(model.backGroundColor)||{}).groups||{}; + + return groups.active == 'image' + ? { image: `${process.env.VUE_APP_BASE_RESOURCE_URL}${groups.string}` } + : groups.active == 'color' + ? groups.string + : model.backGroundColor; + } + + setShape(model) { + if (this._elMap.text) { + this._origin = [model.point.x, model.point.y]; + this._elMap.text.attr('origin', this._origin); + this._elMap.text.setStyle({ + x: model.point.x, + y: model.point.y + }); + } + } + + setState(model) { + } + + dragging(e) { + const model = this._shape.model; + + model.point.x += e.dx; + model.point.y += e.dy; + this.setShape(model); + } + + doActive(zr) { + const style = this._shape.style; + const level = zr||this.__zr; + if (this._elMap.text && level) { + level.addHover(this._elMap.text, { + opacity: style.maskOpacity, + textBackgroundColor: color.lift(style.textHover2Color, style.liftLevel) + }); + } + } + + doInactive(zr) { + const level = zr||this.__zr; + if (this._elMap.text && level) { + level.removeHover(this._elMap.text); + } + } + + getViewTipsPoint() {} +} diff --git a/src/iscs_new/package/graph/Warning/index.js b/src/iscs_new/package/graph/Warning/index.js new file mode 100644 index 000000000..9d025978a --- /dev/null +++ b/src/iscs_new/package/graph/Warning/index.js @@ -0,0 +1,172 @@ +import RadialGradient from 'zrender/src/graphic/RadialGradient'; +import * as color from 'zrender/src/tool/color'; +import * as graphic from '../../../graph/graphic'; +import panelType from '../../../constant/panelType'; +import ConstConfig from '@/scripts/ConstConfig'; + +export default class Warning extends graphic.Group { + constructor(painter, shape, state) { + super(); + this._code = shape.model.code; + this._type = shape.model._type; + this._shape = shape; + this._state = state; + this._painter = painter; + this._state = state; + this._elMap = { + circle: null + }; + + this.create(); + + this.on('mouseover', this.mouseover, this); + this.on('mouseout', this.mouseout, this); + } + + mouseover(e) { + const model = this._shape.model; + if (this._shape.draw) { + this.doActive(this.__zr); + } else if (model.description) { + this._painter.$tipsHandle.trigger('show', { + x: e.offsetX, + y: e.offsetY, + text: model.description, + target: e.target + }); + } + } + + mouseout(e) { + const map = this._painter.$map; + if (this._shape.draw && !map.isHover(this._code)) { + this.doInactive(this.__zr); + } else { + this._painter.$tipsHandle.trigger('hide'); + } + } + + create() { + const model = this._shape.model; + const style = this._shape.style; + const distance = 8; + + this._elMap.circle = new graphic.Circle({ + zlevel: model.zlevel, + z: model.z, + shape: { + cx: model.point.x, + cy: model.point.y, + r: model.radius||10 + }, + style: { + lineWidth: style[panelType.Warning].circle.lineWidth, + stroke: style[panelType.Warning].circle.stroke, + fill: new RadialGradient(0.5, 0.5, 0.5, [ + {offset: 0, color: '#eeeeee'}, + {offset: 1, color: '#666666'} + ]) + } + }); + + const signX = ConstConfig.ConstMap.LocationMode.Left.value == model.showPosition + ? -1 + : ConstConfig.ConstMap.LocationMode.Right.value == model.showPosition + ? 1 + : 0; + const signY = ConstConfig.ConstMap.LocationMode.Top.value == model.showPosition + ? -1 + : ConstConfig.ConstMap.LocationMode.Bottom.value == model.showPosition + ? 1 + : 0; + this._elMap.text = new graphic.Text({ + zlevel: model.zlevel, + z: model.z, + style: { + x: model.point.x + signX*(model.radius+distance), + y: model.point.y + signY*(model.radius+distance*2), + fontFamily: style.fontFamily, + fontWeight: style[panelType.Warning].text.fontWeight, + fontSize: style[panelType.Warning].text.fontSize, + textFill: style[panelType.Warning].text.textFill, + textVerticalAlign: 'middle', + text: model.description, + textAlign: ConstConfig.ConstMap.LocationMode.Left.value == model.showPosition + ? 'right' + : ConstConfig.ConstMap.LocationMode.Right.value == model.showPosition + ? 'left' + : 'center' + } + }); + + model.textShow? this._elMap.text.show(): this._elMap.text.hide(); + + this.setState(model); + + Object.values(this._elMap).forEach(elem => { elem && elem instanceof Array? elem.forEach(el => this.add(el)): this.add(elem); }); + } + + setShape(model) { + if (this._elMap.circle) { + this._elMap.circle.setShape({ + cx: model.point.x, + cy: model.point.y + }); + } + + if (this._elMap.text) { + const distance = 8; + const signX = ConstConfig.ConstMap.LocationMode.Left.value == model.showPosition + ? -1 + : ConstConfig.ConstMap.LocationMode.Right.value == model.showPosition + ? 1 + : 0; + const signY = ConstConfig.ConstMap.LocationMode.Top.value == model.showPosition + ? -1 + : ConstConfig.ConstMap.LocationMode.Bottom.value == model.showPosition + ? 1 + : 0; + this._elMap.text.setStyle({ + x: model.point.x + signX*(model.radius+distance), + y: model.point.y + signY*(model.radius+distance*2) + }); + } + } + + setState(model) { + } + + dragging(e) { + const model = this._shape.model; + + model.point.x += e.dx; + model.point.y += e.dy; + this.setShape(model); + } + + doActive(zr) { + const style = this._shape.style; + const level = zr||this.__zr; + if (this._elMap.circle && level) { + level.addHover(this._elMap.circle, { + opacity: style.maskOpacity, + fill: color.lift(style.graphHover2Color, style.liftLevel) + }); + } + } + + doInactive(zr) { + const level = zr||this.__zr; + if (this._elMap.circle &&level) { + level.removeHover(this._elMap.circle); + } + } + + getViewTipsPoint() { + const model = this._shape.model; + return { + x: model.point.x, + y: model.point.y + }; + } +} diff --git a/src/iscs_new/package/graph/index.js b/src/iscs_new/package/graph/index.js new file mode 100644 index 000000000..717c5e74b --- /dev/null +++ b/src/iscs_new/package/graph/index.js @@ -0,0 +1,31 @@ +import graphType from '../../constant/graphType'; + +import Text2 from './Text/index'; +import Table from './Table/index'; +import Table1 from './Table/tableIndex'; +import LinePipe from './LinePipe/index'; +import Resource from './Resource/index'; +import Measure from './Measure/index'; +import Warning from './Warning/index'; +import Switching from './Switching/index'; +import Popup from './Popup/index'; +import ProgramControl from './ProgramControl/index'; +import Pid from './Pid/index'; + +/** 图库*/ +const mapShape = {}; + +mapShape[graphType.Text] = Text2; +mapShape[graphType.Table] = Table; +mapShape[graphType.Table1] = Table1; +mapShape[graphType.LinePipe] = LinePipe; +mapShape[graphType.Resource] = Resource; +mapShape[graphType.Measure] = Measure; +mapShape[graphType.Warning] = Warning; +mapShape[graphType.Switching] = Switching; +mapShape[graphType.Popup] = Popup; +mapShape[graphType.ProgramControl] = ProgramControl; +mapShape[graphType.Pid] = Pid; + +export default mapShape; + diff --git a/src/iscs_new/package/index.js b/src/iscs_new/package/index.js new file mode 100644 index 000000000..8655123cd --- /dev/null +++ b/src/iscs_new/package/index.js @@ -0,0 +1,17 @@ +import graphMapShape from './graph'; +import panelMapShape from './panel'; + +export default { + __Shape: { + ...graphMapShape, + ...panelMapShape, + ...resourceMapShape + }, + getBuilder(type) { + const ShapeClazz = this.__Shape[type]; + return (...args) => { + return ShapeClazz? new ShapeClazz(...args) : null; + }; + } +}; + diff --git a/src/iscs_new/package/panel/LinePipe/index.js b/src/iscs_new/package/panel/LinePipe/index.js new file mode 100644 index 000000000..a58a001e5 --- /dev/null +++ b/src/iscs_new/package/panel/LinePipe/index.js @@ -0,0 +1,312 @@ +import * as color from 'zrender/src/tool/color'; +import * as graphic from '../../../graph/graphic'; +import * as utils from '../../../utils/utils'; +import panelType from '../../../constant/panelType'; +import ConstSelect from '@/scripts/ConstConfig'; + +export default class LinePipe extends graphic.Group { + constructor(painter, shape, state) { + super(); + this._code = shape.model.code; + this._type = shape.model._type; + this._shape = shape; + this._painter = painter; + this._state = state; + this._elMap = { + lines: [], + line: null, + flow: null, + lArrow: null, + rArrow: null + }; + + this.create(); + + this.on('mouseover', this.mouseover, this); + this.on('mouseout', this.mouseout, this); + } + + mouseover(e) { + if (this._shape.draw) { + this.doActive(this.__zr); + } + } + + mouseout(e) { + const map = this._painter.$map; + if (this._shape.draw && !map.isHover(this._code)) { + this.doInactive(this.__zr); + } + } + + create() { + const model = this._shape.model; + const style = this._shape.style; + + const isVisible = this._state.isDraw ? true : model.visible; + + if (isVisible) { + if (model.points.length >= 2) { + this._elMap.line = new graphic.Polyline({ + zlevel: model.zlevel, + z: model.z, + z2: (model.layer || 0), + shape: { + points: model.points.map(elem => { return [elem.x, elem.y]; }), + smooth: model.smooth / 10 + }, + style: { + lineWidth: model.width||style[panelType.LinePipe].line.lineWidth, + stroke: model.color + } + }); + + // 文字和状态 + if (!this._shape.draw) { + this._elMap.flow = new graphic.Polyline({ + zlevel: model.zlevel, + z: model.z, + z2: (model.layer || 0)+1, + silent: true, + shape: { + points: model.points.map(elem => { return [elem.x, elem.y]; }), + smooth: model.smooth / 10 + }, + style: { + lineDash: [8, 8], + lineWidth: model.width + } + }); + this._elMap.flow.hide(); + } + + if ((ConstSelect.ConstMap.LSvgs[model.leftArrow]||{}).path) { + const rotation = -Math.atan2( + model.points[1].y-model.points[0].y, + model.points[1].x-model.points[0].x + ); + const path = ConstSelect.ConstMap.LSvgs[model.leftArrow].path; + this._elMap.lArrow = new graphic.Svg({ + zlevel: model.zlevel, + z: model.z, + z2: (model.layer || 0), + origin: [0, 0], + rotation, + shape: { + x: model.points[0].x, + y: model.points[0].y, + path + }, + style: { + lineWidth: style[panelType.LinePipe].arrow.lineWidth, + stroke: path.includes('stroke')? model.color: 'transparent ', + fill: path.includes('fill')? model.color: 'transparent ' + } + }); + } + + if ((ConstSelect.ConstMap.RSvgs[model.rightArrow]||{}).path) { + const len = model.points.length-1; + const rotation = -Math.atan2( + model.points[len].y-model.points[len-1].y, + model.points[len].x-model.points[len-1].x + ); + const path = ConstSelect.ConstMap.RSvgs[model.rightArrow].path; + this._elMap.rArrow = new graphic.Svg({ + zlevel: model.zlevel, + z: model.z, + z2: (model.layer || 0), + origin: [0, 0], + rotation, + shape: { + x: model.points[len].x, + y: model.points[len].y, + path + }, + style: { + lineWidth: style[panelType.LinePipe].arrow.lineWidth, + stroke: path.includes('stroke')? model.color: 'transparent ', + fill: path.includes('fill')? model.color: 'transparent ' + } + }); + } + + this._elMap.line.setStyle('lineDash', { + 'Solid': null, // 实线 + 'Dotted': [12, 6], // 虚线 + 'Point': [4, 4], // 点线 + 'DotPointA': [12, 4, 4, 4], // 一类虚点线 + 'DotPointB': [12, 4, 4, 4, 4, 4] // 二类虚点线 + }[model.type]); + } + } + + this.setState(model); + + Object.values(this._elMap).forEach(elem => { elem && elem instanceof Array? elem.forEach(el => this.add(el)): this.add(elem); }); + + } + + setShape(model) { + if (this._elMap.lines && this._elMap.lines.length) { + this._elMap.lines.forEach((line, index) => { + utils.lineProxy(line, model.points[index], model.points[index+1]); + }); + } + + if (this._elMap.line) { + this._elMap.line.setShape({ + points: model.points.map(elem => { return [elem.x, elem.y]; }) + }); + } + + if (this._elMap.flow) { + this._elMap.flow.setShape({ + points: model.points.map(elem => { return [elem.x, elem.y]; }) + }); + } + + if (this._elMap.lArrow) { + const rotation = -Math.atan2( + model.points[1].y-model.points[0].y, + model.points[1].x-model.points[0].x + ); + this._elMap.lArrow.attr('rotation', rotation); + this._elMap.lArrow.setShape({ + x: model.points[0].x, + y: model.points[0].y + }); + } + + if (this._elMap.rArrow) { + const len = model.points.length-1; + const rotation = -Math.atan2( + model.points[len].y-model.points[len-1].y, + model.points[len].x-model.points[len-1].x + ); + this._elMap.rArrow.attr('rotation', rotation); + this._elMap.rArrow.setShape({ + x: model.points[len].x, + y: model.points[len].y + }); + } + } + + setState(model) { + const data = model.entity.data; + const stroke = model.color; + + if (data && this._elMap.flow) { + if (data.filled) { + this._elMap.flow.show(); + switch (data.from) { + case 'A': this.setFlowRun(data, true); break; + case 'B': this.setFlowRun(data, false); break; + default: this.setFlowStop(); break; + } + + if (data.filler) { + this._elMap.flow.setStyle({stroke}); + this._elMap.line.hide(); + } + } else { + this._elMap.flow.hide(); + this._elMap.line.show(); + } + } + } + + dragging(e) { + const model = this._shape.model; + + model.points.map(elem => { + elem.x += e.dx; + elem.y += e.dy; + }); + + this.setShape(model); + } + + setFlowRun(data, clockwise) { + const offsetMap = clockwise ? [32, 16, 0] : [0, 16, 32]; + const flowSpeed = Math.ceil(data.speed); + if (this._elMap.flow) { + this._elMap.flow.stopAnimation(); + if (flowSpeed > 0) { + this._elMap.flow.animate('style', true) + .when(0, { lineDashOffset: offsetMap[0] * flowSpeed }) + .when(1000, { lineDashOffset: offsetMap[1] * flowSpeed }) + .when(2000, { lineDashOffset: offsetMap[2] * flowSpeed }) + .start(); + } + } + + } + + setFlowStop() { + if (this._elMap.flow) { + this._elMap.flow.stopAnimation(); + } + } + + setFlowClear() { + if (this._elMap.flow) { + this.remove(this._elMap.flow); + } + } + + doActive(zr) { + if (zr||this.__zr) { + const style = this._shape.style; + const level = zr||this.__zr; + + if (this._elMap.line) { + level.addHover(this._elMap.line, { + stroke: color.lift(style.pipeHover2Color, style.liftLevel), + opacity: 0.8 + }); + } + + this._elMap.lines.forEach(elem => { + if (elem) { + level.addHover(elem, { + stroke: color.lift(style.pipeHover2Color, style.liftLevel), + opacity: 0.8 + }); + } + }); + + [this._elMap.lArrow, this._elMap.rArrow].forEach(el =>{ + if (el) { + level.addHover(el, { + stroke: el.shape.path.includes('stroke') + ? color.lift(style.pipeHover2Color, style.liftLevel) + : 'transparent', + fill: el.shape.path.includes('fill') + ? color.lift(style.pipeHover2Color, style.liftLevel) + : 'transparent' + }); + } + }); + } + } + + doInactive(zr) { + if (zr||this.__zr) { + const level = zr||this.__zr; + [this._elMap.line, + ...this._elMap.lines, + this._elMap.lText, + this._elMap.rText, + this._elMap.lArrow, + this._elMap.rArrow + ].forEach(elem => { + if (elem) { + level.removeHover(elem); + } + }); + } + } + + getViewTipsPoint() {} +} diff --git a/src/iscs_new/package/panel/Measure/index.js b/src/iscs_new/package/panel/Measure/index.js new file mode 100644 index 000000000..4bd36ba43 --- /dev/null +++ b/src/iscs_new/package/panel/Measure/index.js @@ -0,0 +1,144 @@ +import * as color from 'zrender/src/tool/color'; +import * as graphic from '../../../graph/graphic'; +// import panelType from '../../../constant/panelType'; + +export default class Measure extends graphic.Group { + constructor(painter, shape, state) { + super(); + this._code = shape.model.code; + this._type = shape.model._type; + this._shape = shape; + this._state = state; + this._painter = painter; + this._state = state; + this._elMap = { + text: null + }; + + this.create(); + + this.on('mouseover', this.mouseover, this); + this.on('mouseout', this.mouseout, this); + } + + mouseover(e) { + const model = this._shape.model; + if (this._shape.draw) { + this.doActive(this.__zr); + } else if (model.description) { + this._painter.$tipsHandle.trigger('show', { + x: e.offsetX, + y: e.offsetY, + text: model.description, + target: e.target + }); + } + } + + mouseout(e) { + const map = this._painter.$map; + if (this._shape.draw &&!map.isHover(this._code)) { + this.doInactive(this.__zr); + } else { + this._painter.$tipsHandle.trigger('hide'); + } + } + + create() { + const model = this._shape.model; + + this._elMap.text = new graphic.Text({ + zlevel: model.zlevel, + z: model.z, + style: { + x: model.point.x, + y: model.point.y, + fontFamily: 'Times New Roman', + fontWeight: 'normal', + fontSize: model.size, + textVerticalAlign: 'middle', + textBackgroundColor: 'transparent', + text: this.format('--', model.unit), + textFill: model.color||'#fff', + textAlign: 'center', + textPadding: [3, 3, 1, 3], + rich: { + txt: { + fontSize: model.size, + textVerticalAlign: 'middle', + textFill: model.color||'#fff' + }, + sup: { + fontSize: parseInt(model.size/3), + textVerticalAlign: 'top' + }, + sub: { + fontSize: parseInt(model.size/3), + textVerticalAlign: 'bottom' + } + } + } + }); + + this.setState(model); + + Object.values(this._elMap).forEach(elem => { elem && elem instanceof Array? elem.forEach(el => this.add(el)): this.add(elem); }); + } + + setShape(model) { + if (this._elMap.text) { + this._elMap.text.setStyle({ + x: model.point.x, + y: model.point.y + }); + } + } + + setState(model) { + const data = model.entity.data ||{}; + const decimalPlace = model.decimalPlace||0; + + if (this._elMap.text && data) { + const value = data.value == undefined? '--' : Number(data.value||0).toFixed(decimalPlace); + this._elMap.text.setStyle({text: this.format(value, model.unit) }); + } + } + + format(value, unit) { + return `{txt|${value}} ${unit}`; + } + + dragging(e) { + const model = this._shape.model; + + model.point.x += e.dx; + model.point.y += e.dy; + this.setShape(model); + } + + doActive(zr) { + const style = this._shape.style; + const level = zr||this.__zr; + if (this._elMap.text && level) { + level.addHover(this._elMap.text, { + opacity: style.maskOpacity, + textBackgroundColor: color.lift(style.measureHover2Color, style.liftLevel) + }); + } + } + + doInactive(zr) { + const level = zr||this.__zr; + if (this._elMap.text &&level) { + level.removeHover(this._elMap.text); + } + } + + getViewTipsPoint() { + const model = this._shape.model; + return { + x: model.point.x, + y: model.point.y + }; + } +} diff --git a/src/iscs_new/package/panel/Pid/index.js b/src/iscs_new/package/panel/Pid/index.js new file mode 100644 index 000000000..6f165235b --- /dev/null +++ b/src/iscs_new/package/panel/Pid/index.js @@ -0,0 +1,159 @@ +import * as color from 'zrender/src/tool/color'; +import * as graphic from '../../../graph/graphic'; +import panelType from '../../../constant/panelType'; + +export default class Pid extends graphic.Group { + constructor(painter, shape) { + super(); + this._code = shape.model.code; + this._type = shape.model._type; + this._shape = shape; + this._painter = painter; + this._elMap = { + text: null, + button: null + }; + + this.create(); + + this.on('mouseover', this.mouseover, this); + this.on('mouseout', this.mouseout, this); + } + + mouseover(e) { + const model = this._shape.model; + if (this._shape.draw) { + this._elMap.button.attr({cursor: 'pointer'}); + this.doActive(this.__zr); + } else if (model.description) { + this._painter.$tipsHandle.trigger('show', { + x: e.offsetX, + y: e.offsetY, + text: model.description, + target: e.target + }); + } + } + + mouseout(e) { + const map = this._painter.$map; + if (this._shape.draw && !map.isHover(this._code)) { + this._elMap.button.attr({cursor: 'default'}); + this.doInactive(this.__zr); + } else { + this._painter.$tipsHandle.trigger('hide'); + } + } + + create() { + const model = this._shape.model; + const style = this._shape.style; + + this._elMap.button = new graphic.Rect({ + zlevel: model.zlevel, + z: model.z, + shape: { + x: model.point.x-model.width/2, + y: model.point.y-model.height/2, + width: model.width, + height: model.height, + r: [1] + }, + style: { + fill: style[panelType.Pid].button.fill, + stroke: style[panelType.Pid].button.stroke, + lineWidth: style[panelType.Pid].button.lineWidth, + shadowColor: '#dfdfdf', + shadowOffsetX: 1, + shadowOffsetY: 1 + } + }); + + this._elMap.text = new graphic.Text({ + zlevel: model.zlevel, + z: model.z, + z2: 2, + style: { + x: model.point.x, + y: model.point.y, + fontWeight: style[panelType.Pid].text.fontWeight, + fontFamily: style.fontFamily, + fontSize: model.fontSize, + text: model.text, + textFill: '#000', + textPadding: [4, 4], + textAlign: 'center', + textVerticalAlign: 'middle' + } + }); + + this.setState(model); + + Object.values(this._elMap).forEach(elem => { elem && elem instanceof Array? elem.forEach(el => this.add(el)): this.add(elem); }); + } + + setShape(model) { + if (this._elMap.button) { + this._elMap.button.setShape({ + x: model.point.x-model.width/2, + y: model.point.y-model.height/2 + }); + } + + if (this._elMap.text) { + this._elMap.text.setStyle({ + x: model.point.x, + y: model.point.y + }); + } + } + + setState(model) {} + + dragging(e) { + const model = this._shape.model; + + model.point.x += e.dx; + model.point.y += e.dy; + this.setShape(model); + } + + doActive(zr) { + const style = this._shape.style; + const level = zr||this.__zr; + if (this._elMap.button && level) { + level.addHover(this._elMap.button, { + opacity: style.maskOpacity, + fill: color.lift(style.graphHover2Color, style.liftLevel) + }); + } + + if (this._elMap.text && level) { + level.addHover(this._elMap.text, { + opacity: style.maskOpacity, + textFill: color.lift(style.textHover2Color, style.liftLevel) + }); + } + } + + doInactive(zr) { + const level = zr||this.__zr; + if ( this._elMap.button && level) { + level.removeHover(this._elMap.button); + } + + if ( this._elMap.text && level) { + level.removeHover(this._elMap.text); + } + } + + getViewTipsPoint() { + if (this._elMap.button) { + const button = this._elMap.button.getBoundingRect(); + return { + x: button.x + button.width/2, + y: button.y + }; + } + } +} diff --git a/src/iscs_new/package/panel/Popup/index.js b/src/iscs_new/package/panel/Popup/index.js new file mode 100644 index 000000000..84c05207e --- /dev/null +++ b/src/iscs_new/package/panel/Popup/index.js @@ -0,0 +1,149 @@ +import * as color from 'zrender/src/tool/color'; +import * as graphic from '../../../graph/graphic'; +import panelType from '../../../constant/panelType'; + +export default class Popup extends graphic.Group { + constructor(painter, shape) { + super(); + this._code = shape.model.code; + this._type = shape.model._type; + this._shape = shape; + this._painter = painter; + this._elMap = { + text: null, + button: null + }; + + this.create(); + + this.on('mouseover', this.mouseover, this); + this.on('mouseout', this.mouseout, this); + } + + mouseover(e) { + if (this._shape.draw) { + this._elMap.button.attr({cursor: 'pointer'}); + this.doActive(this.__zr); + } + } + + mouseout(e) { + const map = this._painter.$map; + if (this._shape.draw && !map.isHover(this._code)) { + this._elMap.button.attr({cursor: 'default'}); + this.doInactive(this.__zr); + } + } + + create() { + const model = this._shape.model; + const style = this._shape.style; + + this._elMap.button = new graphic.Rect({ + zlevel: model.zlevel, + z: model.z, + shape: { + x: model.point.x-model.width/2, + y: model.point.y-model.height/2, + width: model.width, + height: model.height, + r: [1] + }, + style: { + fill: style[panelType.Popup].button.fill, + stroke: style[panelType.Popup].button.stroke, + lineWidth: style[panelType.Popup].button.lineWidth, + shadowColor: '#dfdfdf', + shadowOffsetX: 1, + shadowOffsetY: 1 + } + }); + + this._elMap.text = new graphic.Text({ + zlevel: model.zlevel, + z: model.z, + z2: 2, + style: { + x: model.point.x, + y: model.point.y, + fontWeight: style[panelType.Popup].text.fontWeight, + fontFamily: style.fontFamily, + fontSize: model.fontSize, + text: model.text, + textFill: '#000', + textPadding: [4, 4], + textAlign: 'center', + textVerticalAlign: 'middle' + } + }); + + this.setState(model); + + Object.values(this._elMap).forEach(elem => { elem && elem instanceof Array? elem.forEach(el => this.add(el)): this.add(elem); }); + } + + setShape(model) { + if (this._elMap.button) { + this._elMap.button.setShape({ + x: model.point.x-model.width/2, + y: model.point.y-model.height/2 + }); + } + + if (this._elMap.text) { + this._elMap.text.setStyle({ + x: model.point.x, + y: model.point.y + }); + } + } + + setState(model) {} + + dragging(e) { + const model = this._shape.model; + + model.point.x += e.dx; + model.point.y += e.dy; + this.setShape(model); + } + + doActive(zr) { + const style = this._shape.style; + const level = zr||this.__zr; + if (this._elMap.button && level) { + level.addHover(this._elMap.button, { + opacity: style.maskOpacity, + fill: color.lift(style.graphHover2Color, style.liftLevel) + }); + } + + if (this._elMap.text && level) { + level.addHover(this._elMap.text, { + opacity: style.maskOpacity, + textFill: color.lift(style.textHover2Color, style.liftLevel) + }); + } + } + + doInactive(zr) { + const level = zr||this.__zr; + if ( this._elMap.button && level) { + level.removeHover(this._elMap.button); + } + + if ( this._elMap.text && level) { + level.removeHover(this._elMap.text); + } + } + + getViewTipsPoint() { + if (this._elMap.button) { + const button = this._elMap.button.getBoundingRect(); + return { + x: button.x + button.width/2, + y: button.y + }; + } + } +} diff --git a/src/iscs_new/package/panel/ProgramControl/index.js b/src/iscs_new/package/panel/ProgramControl/index.js new file mode 100644 index 000000000..01b80058c --- /dev/null +++ b/src/iscs_new/package/panel/ProgramControl/index.js @@ -0,0 +1,308 @@ +import * as color from 'zrender/src/tool/color'; +import * as graphic from '../../../graph/graphic'; +import panelType from '../../../constant/panelType'; + +export default class ProgramControl extends graphic.Group { + constructor(painter, shape) { + super(); + this._code = shape.model.code; + this._type = shape.model._type; + this._shape = shape; + this._painter = painter; + this._elMap = { + line: null, + button: null, + blockStart: null, + blockReset: null, + blockStop: null, + start: null, + reset: null, + stop: null + }; + + this.create(); + + this.on('mouseover', this.mouseover, this); + this.on('mouseout', this.mouseout, this); + } + + mouseover(e) { + const model = this._shape.model; + if (this._shape.draw) { + this._elMap.button.attr({cursor: 'pointer'}); + this.doActive(this.__zr); + } else if (model.description) { + this._painter.$tipsHandle.trigger('show', { + x: e.offsetX, + y: e.offsetY, + text: model.description, + target: e.target + }); + } + } + + mouseout(e) { + const map = this._painter.$map; + if (this._shape.draw && !map.isHover(this._code)) { + this._elMap.button.attr({cursor: 'default'}); + this.doInactive(this.__zr); + } else { + this._painter.$tipsHandle.trigger('hide'); + } + } + + create() { + const model = this._shape.model; + const style = this._shape.style; + + this._elMap.line = new graphic.Line({ + zlevel: model.zlevel, + z: model.z, + z2: 9, + shape: { + x1: model.point.x+style[panelType.ProgramControl].button.width/2, + y1: model.point.y+style[panelType.ProgramControl].button.height/2, + x2: model.point.x-style[panelType.ProgramControl].button.width/2, + y2: model.point.y-style[panelType.ProgramControl].button.height/2 + }, + style: { + stroke: style[panelType.ProgramControl].line.stroke, + lineWidth: style[panelType.ProgramControl].line.lineWidth, + lineCap: 'round' + } + }); + + this._elMap.button = new graphic.Rect({ + zlevel: model.zlevel, + z: model.z, + shape: { + x: model.point.x-style[panelType.ProgramControl].button.width/2, + y: model.point.y-style[panelType.ProgramControl].button.height/2, + width: style[panelType.ProgramControl].button.width, + height: style[panelType.ProgramControl].button.height, + r: [1] + }, + style: { + fill: style[panelType.ProgramControl].button.fill, + stroke: style[panelType.ProgramControl].button.stroke, + lineWidth: style[panelType.ProgramControl].button.lineWidth + } + }); + + this._elMap.blockStart = new graphic.Rect({ + zlevel: model.zlevel, + z: model.z, + z2: 3, + shape: { + x: model.point.x-style[panelType.ProgramControl].button.width/2, + y: model.point.y-style[panelType.ProgramControl].button.height/2, + width: style[panelType.ProgramControl].button.width/3, + height: style[panelType.ProgramControl].button.height, + r: [1] + }, + style: { + fill: style[panelType.ProgramControl].block.fill, + stroke: style[panelType.ProgramControl].block.stroke, + lineWidth: style[panelType.ProgramControl].block.lineWidth + } + }); + + this._elMap.blockReset = new graphic.Rect({ + zlevel: model.zlevel, + z: model.z, + z2: 3, + shape: { + x: model.point.x-style[panelType.ProgramControl].button.width/2+style[panelType.ProgramControl].button.width/3, + y: model.point.y-style[panelType.ProgramControl].button.height/2, + width: style[panelType.ProgramControl].button.width/3, + height: style[panelType.ProgramControl].button.height, + r: [1] + }, + style: { + fill: style[panelType.ProgramControl].block.fill, + stroke: style[panelType.ProgramControl].block.stroke, + lineWidth: style[panelType.ProgramControl].block.lineWidth + } + }); + + this._elMap.blockStop = new graphic.Rect({ + zlevel: model.zlevel, + z: model.z, + z2: 3, + shape: { + x: model.point.x-style[panelType.ProgramControl].button.width/2+style[panelType.ProgramControl].button.width/3*2, + y: model.point.y-style[panelType.ProgramControl].button.height/2, + width: style[panelType.ProgramControl].button.width/3, + height: style[panelType.ProgramControl].button.height, + r: [1] + }, + style: { + fill: style[panelType.ProgramControl].block.fill, + stroke: style[panelType.ProgramControl].block.stroke, + lineWidth: style[panelType.ProgramControl].block.lineWidth, + r: [1] + } + }); + + this._elMap.start = new graphic.Svg({ + zlevel: model.zlevel, + z: model.z, + z2: 5, + origin: [0, 0], + rotation: 0, + scale: [1, 1], + shape: { + x: model.point.x-style[panelType.ProgramControl].button.width/2 + style[panelType.ProgramControl].button.width/6, + y: model.point.y-style[panelType.ProgramControl].button.height/2, + path: 'M6 12 L-4 6 L-4 18Z' + }, + style: { + fill: style[panelType.ProgramControl].indicate.fill + } + }); + + this._elMap.reset = new graphic.Svg({ + zlevel: model.zlevel, + z: model.z, + z2: 5, + origin: [0, 0], + rotation: 0, + scale: [1, 1], + shape: { + x: model.point.x-style[panelType.ProgramControl].button.width/2+style[panelType.ProgramControl].button.width/3 + style[panelType.ProgramControl].button.width/6, + y: model.point.y-style[panelType.ProgramControl].button.height/2, + path: 'M6 6 L6 18 L1 18 L1 6Z M-6 6 L-6 18 L-1 18 L-1 6Z' + }, + style: { + fill: style[panelType.ProgramControl].indicate.fill + } + }); + + this._elMap.stop = new graphic.Svg({ + zlevel: model.zlevel, + z: model.z, + z2: 5, + origin: [0, 0], + rotation: 0, + scale: [1, 1], + shape: { + x: model.point.x-style[panelType.ProgramControl].button.width/2+style[panelType.ProgramControl].button.width/3*2 + style[panelType.ProgramControl].button.width/6, + y: model.point.y-style[panelType.ProgramControl].button.height/2, + path: 'M6 6 L6 18 L-6 18 L-6 6Z' + }, + style: { + fill: style[panelType.ProgramControl].indicate.fill + } + }); + + this.setState(model); + + Object.values(this._elMap).forEach(elem => { elem && elem instanceof Array? elem.forEach(el => this.add(el)): this.add(elem); }); + } + + setShape(model) { + const style = this._shape.style; + if (this._elMap.line) { + this._elMap.line.setShape({ + x1: model.point.x+style[panelType.ProgramControl].button.width/2, + y1: model.point.y+style[panelType.ProgramControl].button.height/2, + x2: model.point.x-style[panelType.ProgramControl].button.width/2, + y2: model.point.y-style[panelType.ProgramControl].button.height/2 + }); + } + + if (this._elMap.button) { + this._elMap.button.setShape({ + x: model.point.x-style[panelType.ProgramControl].button.width/2, + y: model.point.y-style[panelType.ProgramControl].button.height/2 + }); + } + + if (this._elMap.blockStart) { + this._elMap.blockStart.setShape({ + x: model.point.x-style[panelType.ProgramControl].button.width/2, + y: model.point.y-style[panelType.ProgramControl].button.height/2, + width: style[panelType.ProgramControl].button.width/3, + height: style[panelType.ProgramControl].button.height + }); + } + + if (this._elMap.blockReset) { + this._elMap.blockReset.setShape({ + x: model.point.x-style[panelType.ProgramControl].button.width/2+style[panelType.ProgramControl].button.width/3, + y: model.point.y-style[panelType.ProgramControl].button.height/2, + width: style[panelType.ProgramControl].button.width/3, + height: style[panelType.ProgramControl].button.height + }); + } + + if (this._elMap.blockStop) { + this._elMap.blockStop.setShape({ + x: model.point.x-style[panelType.ProgramControl].button.width/2+style[panelType.ProgramControl].button.width/3*2, + y: model.point.y-style[panelType.ProgramControl].button.height/2, + width: style[panelType.ProgramControl].button.width/3, + height: style[panelType.ProgramControl].button.height + }); + } + + if (this._elMap.start) { + this._elMap.start.setShape({ + x: model.point.x-style[panelType.ProgramControl].button.width/2 + style[panelType.ProgramControl].button.width/6, + y: model.point.y-style[panelType.ProgramControl].button.height/2 + }); + } + + if (this._elMap.reset) { + this._elMap.reset.setShape({ + x: model.point.x-style[panelType.ProgramControl].button.width/2+style[panelType.ProgramControl].button.width/3 + style[panelType.ProgramControl].button.width/6, + y: model.point.y-style[panelType.ProgramControl].button.height/2 + }); + } + + if (this._elMap.stop) { + this._elMap.stop.setShape({ + x: model.point.x-style[panelType.ProgramControl].button.width/2+style[panelType.ProgramControl].button.width/3*2 + style[panelType.ProgramControl].button.width/6, + y: model.point.y-style[panelType.ProgramControl].button.height/2 + }); + } + } + + setState(model) {} + + dragging(e) { + const model = this._shape.model; + + model.point.x += e.dx; + model.point.y += e.dy; + this.setShape(model); + } + + doActive(zr) { + const style = this._shape.style; + const level = zr||this.__zr; + if (this._elMap.button && level) { + level.addHover(this._elMap.button, { + opacity: style.maskOpacity, + fill: color.lift(style.graphHover2Color, style.liftLevel), + stroke: color.lift(style.graphHover2Color, style.liftLevel) + }); + } + } + + doInactive(zr) { + const level = zr||this.__zr; + if ( this._elMap.button && level) { + level.removeHover(this._elMap.button); + } + } + + getViewTipsPoint() { + if (this._elMap.button) { + const button = this._elMap.button.getBoundingRect(); + return { + x: button.x + button.width/2, + y: button.y + }; + } + } +} diff --git a/src/iscs_new/package/panel/Resource/caches.js b/src/iscs_new/package/panel/Resource/caches.js new file mode 100644 index 000000000..a6ee10965 --- /dev/null +++ b/src/iscs_new/package/panel/Resource/caches.js @@ -0,0 +1,62 @@ +import * as utils from '../../../utils/utils'; + +class Caches { + constructor () { + this.registerMap = {}; + } + + register(model, statuses) { + const type = model.entity.type; + const resourceId = model.resourceId; + const cacheMap = this.getCacheMap(this.registerMap, type); + + if (!cacheMap[resourceId]) { + cacheMap[resourceId] = this.buildMapper(statuses); + } + + return new Proxy(cacheMap[resourceId], { + get: function(source, key) { return source[key]||source.none; } + }); + } + + buildMapper(statuses) { + const map = {}; + if (statuses instanceof Array) { + statuses.forEach(el => { + const urls = el.urls; + if (urls.length == 1) { + map[el.status] = utils.getResourceUrl(el.urls[0]); + } else { + map[el.status] = []; + urls.forEach(url => { + map[el.status].push(utils.getResourceUrl(url)); + }); + } + }); + } else { + Object.keys(statuses).forEach(status => { + const urls = statuses[status].urls; + if (urls.length == 1) { + map[status] = utils.getResourceUrl(urls[0]); + } else { + map[status] = []; + urls.forEach(url => { + map[status].push(utils.getResourceUrl(url)); + }); + } + }); + } + return map; + } + + getCacheMap(target, type) { + if (!target[type]) { target[type]= {}; } + return target[type]; + } + + clear() { + this.registerMap = {}; + } +} + +export default new Caches(); diff --git a/src/iscs_new/package/panel/Resource/index.js b/src/iscs_new/package/panel/Resource/index.js new file mode 100644 index 000000000..b09e00d11 --- /dev/null +++ b/src/iscs_new/package/panel/Resource/index.js @@ -0,0 +1,251 @@ +import * as utils from '../../../utils/utils'; +import * as graphic from '../../../graph/graphic'; +import panelType from '../../../constant/panelType'; +import StateHandle from './stateHandle.js'; +import Caches from './caches'; +class Adaptor { + constructor({model, state}) { + this.__model = model; + this.__state = state; + } + + get() { + const model = this.__model; + const resource = (this.__state.mapResource||{})[model.resourceId] || {}; + const size = (resource.size||'').split(',') || [0, 0]; + const width = model.width? model.width: size[0]; + const height = model.height? model.height: size[1]; + + return Object.assign(model, resource, { + width: parseFloat(width), + height: parseFloat(height), + resource + }); + } +} + +export default class Resource extends graphic.Group { + constructor(painter, shape, state) { + super(); + this._code = shape.model.code; + this._type = shape.model._type; + this._shape = shape; + this._painter = painter; + this._state = state; + + this._count = 0; + this._timer = null; + this._adaptor = new Adaptor({model: shape.model, state}); + this._elMap = { + image: null, + warning: null + }; + + this.create(); + + this.on('mouseover', this.mouseover, this); + this.on('mouseout', this.mouseout, this); + } + + mouseover(e) { + const model = this._shape.model; + const control = model.control||{}; + + if (this._shape.draw) { + this._elMap.image.attr({cursor: 'pointer'}); + this.doFocus(); + } else if (this._elMap.image) { + this._elMap.image.attr({cursor: control.disabled? 'default': 'pointer'}); + if (model.description) { + this._painter.$tipsHandle.trigger('show', { + x: e.offsetX, + y: e.offsetY, + text: model.description, + target: e.target + }); + } + } + } + + mouseout(e) { + const map = this._painter.$map; + + if (this._shape.draw && !map.isHover(this._code)) { + this.doBlur(); + } else { + this._elMap.image.attr({cursor: 'default'}); + this._painter.$tipsHandle.trigger('hide'); + } + } + + create() { + const model = this._adaptor.get(); + const style = this._shape.style; + + const rotation = -Math.PI / 180 * Number(model.rotate||0); + const origin = [model.point.x+model.width/2, model.point.y+model.height/2]; + const scale = new Array(2).fill(model.scale || 1); + const cache = this.register(model); + + const isVisible = this._state.isDraw + ? true + : !['PipeFitting'].includes(model.entity.type)&&model.visible; + + if (cache&&isVisible) { + if (utils.urlIsSvg(cache.none)) { + this._elMap.image = new graphic.Svg({ + zlevel: model.zlevel, + z: model.z, + z2: model.layer+5, + origin: [0, 0], + rotation, + scale, + shape: { + x: model.point.x, + y: model.point.y, + path: cache.none + }, + style: { + lineWidth: style[panelType.LinePipe].arrow.lineWidth, + stroke: '#fff', + fill: '#fff' + } + }); + } else { + this._elMap.image = new graphic.Image({ + zlevel: model.zlevel, + z: model.z, + z2: model.layer+5, + origin, + rotation, + scale, + style: { + image: cache.none, + x: model.point.x, + y: model.point.y, + width: model.width*scale[0], + height: model.height*scale[1] + } + }); + } + } + + Object.values(this._elMap).forEach(elem => { elem && elem instanceof Array? elem.forEach(el => this.add(el)): this.add(elem); }); + + this.setState(model); + } + + traversed(map, cb) { + Object.values(map).forEach(el => { + if (el) { + if (el instanceof Array) { + this.traversed(el, cb); + } else { + cb(el); + } + } + }); + } + + setShape(model, e) { + if (this._elMap.image) { + if (utils.shapeIsSvg(this._elMap.image)) { + this._elMap.image.setShape({ + x: model.point.x, + y: model.point.y + }); + } else { + const origin = [model.point.x+model.width/2, model.point.y+model.height/2]; + const scale = new Array(2).fill(model.scale || 1); + this._elMap.image.attr('origin', origin); + this._elMap.image.setStyle({ + x: model.point.x, + y: model.point.y, + width: model.width*scale[0], + height: model.height*scale[1] + }); + } + } + } + + setState(model) { + StateHandle.reload(this); + StateHandle.update(); + StateHandle.unload(); + } + + dragging(e) { + const model = this._adaptor.get(); + + model.point.x += e.dx; + model.point.y += e.dy; + + this.setShape(model, e); + } + + doActive(zr) { + const style = this._shape.style; + const level = zr||this.__zr; + + if (level && this._elMap.STL_Background) { + this._elMap.STL_Background.doActive(level); + } else if (level && this._elMap.image) { + level.addHover(this._elMap.image, { + opacity: style.maskOpacity, + image: style.maskHover2Image, + fill: style.measureHover2Color, + stroke: style.measureHover2Color + }); + } + } + + doInactive(zr) { + const level = zr||this.__zr; + if (this._elMap.STL_Background) { + this._elMap.STL_Background.doInactive(level); + } else if (level && this._elMap.image) { + level.removeHover(this._elMap.image); + } + this.doBlur(); + } + + doFocus() { + Object.values(this._elMap).forEach(elem => { + if (elem) { + elem.setStyle({opacity: 0.5}); + } + }); + } + + doBlur() { + Object.values(this._elMap).forEach(elem => { + if (elem) { + elem.setStyle({opacity: 1}); + } + }); + } + + register(model) { + if (model.resource) { + const resource = model.resource; + const statuses = resource.statusList||[]; + statuses.push({status: 'none', urls: [resource.url]}); + return Caches.register(model, statuses); + } else { + console.info(`设备绘图不支${model.entity.type}绘图(${model.code})!`); + } + } + + getViewTipsPoint() { + const model = this._adaptor.get(); + const image = this._elMap.image; + + if (image) { + const rect = image.getBoundingRect(); + return { + x: model.point.x + rect.width/10, + y: model.point.y + rect.height/20 + }; + } + } +} diff --git a/src/iscs_new/package/panel/Resource/stateHandle.js b/src/iscs_new/package/panel/Resource/stateHandle.js new file mode 100644 index 000000000..8eb41daff --- /dev/null +++ b/src/iscs_new/package/panel/Resource/stateHandle.js @@ -0,0 +1,52 @@ +class StateHandle { + constructor() { + this.unload(); + this.animateMap = null; + } + + reload(graph) { + this.graph = graph; + this.model = graph._shape.model; + this.style = graph._shape.style; + this.state = graph._state; + } + + unload() { + this.graph = null; + this.model = null; + this.style = null; + } + + update() { + if (this.graph) { + const data = this.model.entity.data; + const graph = this.graph; + const cache = this.graph.register(this.model); + + if (data && cache && graph._elMap.image) { + const status = cache[data.status]; + graph._elMap.image.stopAnimation(); + if (status instanceof Array) { + graph._elMap.image.animate('style', true) + .when(37, {image: cache.none }) + .when(74, {image: null }) + .during(() => { + if (+new Date() - graph._delta > 74) { + graph._elMap.image.setStyle({image: status[graph._count%2]}); + graph._delta = +new Date(); + graph._count = graph._count%2+1; + } + }) + .start(); + } else { + graph._elMap.image.stopAnimation(); + graph._elMap.image.setStyle({ image: status }); + graph._delta = 0; + graph._count = 0; + } + } + } + } +} + +export default new StateHandle(); diff --git a/src/iscs_new/package/panel/Switching/index.js b/src/iscs_new/package/panel/Switching/index.js new file mode 100644 index 000000000..8a0e47d05 --- /dev/null +++ b/src/iscs_new/package/panel/Switching/index.js @@ -0,0 +1,195 @@ +import * as color from 'zrender/src/tool/color'; +import * as graphic from '../../../graph/graphic'; +import panelType from '../../../constant/panelType'; + +export default class Switching extends graphic.Group { + constructor(painter, shape) { + super(); + this._code = shape.model.code; + this._type = shape.model._type; + this._shape = shape; + this._painter = painter; + this._elMap = { + text: null, + button: null + }; + + this.create(); + + this.on('mouseover', this.mouseover, this); + this.on('mouseout', this.mouseout, this); + this.on('mousedown', this.mousedown, this); + this.on('mouseup', this.mouseup, this); + } + + mousedown(e) { + const model = this._shape.model; + if (model.isReset && + !this._shape.draw && + this._elMap.button) { + this._elMap.button.setStyle({ + fill: '#FF0000' + }); + } + } + + mouseup(e) { + const model = this._shape.model; + const style = this._shape.style; + if (model.isReset && + !this._shape.draw && + this._elMap.button) { + setTimeout(() => { + this._elMap.button.setStyle({ + fill: style[panelType.Switching].button.fill + }); + }, 200); + + } + } + + mouseover(e) { + if (this._shape.draw) { + this._elMap.button.attr({cursor: 'pointer'}); + this.doActive(this.__zr); + } + } + + mouseout(e) { + const map = this._painter.$map; + if (this._shape.draw && !map.isHover(this._code)) { + this._elMap.button.attr({cursor: 'default'}); + this.doInactive(this.__zr); + } + } + + create() { + const model = this._shape.model; + const style = this._shape.style; + + this._elMap.button = new graphic.Rect({ + zlevel: model.zlevel, + z: model.z, + shape: { + x: model.point.x-model.width/2, + y: model.point.y-model.height/2, + width: model.width, + height: model.height, + r: [1] + }, + style: { + fill: style[panelType.Switching].button.fill, + stroke: style[panelType.Switching].button.stroke, + lineWidth: style[panelType.Switching].button.lineWidth, + shadowColor: '#dfdfdf', + shadowOffsetX: 1, + shadowOffsetY: 1 + } + }); + + this._elMap.text = new graphic.Text({ + zlevel: model.zlevel, + z: model.z, + z2: 2, + style: { + x: model.point.x, + y: model.point.y, + fontWeight: style[panelType.Switching].text.fontWeight, + fontFamily: style.fontFamily, + fontSize: model.fontSize, + text: model.putInText, + textFill: '#000', + textPadding: [4, 4], + textAlign: 'center', + textVerticalAlign: 'middle' + } + }); + + this.setState(model); + + Object.values(this._elMap).forEach(elem => { elem && elem instanceof Array? elem.forEach(el => this.add(el)): this.add(elem); }); + } + + setShape(model) { + if (this._elMap.button) { + this._elMap.button.setShape({ + x: model.point.x-model.width/2, + y: model.point.y-model.height/2 + }); + } + + if (this._elMap.text) { + this._elMap.text.setStyle({ + x: model.point.x, + y: model.point.y + }); + } + } + + setState(model) { + const entity = model.entity||{}; + const data = entity.data ||{}; + if (!model.isReset && + !this._shape.draw && + entity.data) { + if (this._elMap.button) { + this._elMap.button.setStyle({ + fill: data.status? '#FF0000' : '#3CB371' + }); + } + + if (this._elMap.text) { + this._elMap.text.setStyle({ + text: data.status? model.putInText: model.cutOffText + }); + } + } + } + + dragging(e) { + const model = this._shape.model; + + model.point.x += e.dx; + model.point.y += e.dy; + this.setShape(model); + } + + doActive(zr) { + const style = this._shape.style; + const level = zr||this.__zr; + if (this._elMap.button && level) { + level.addHover(this._elMap.button, { + opacity: style.maskOpacity, + fill: color.lift(style.graphHover2Color, style.liftLevel) + }); + } + + if (this._elMap.text && level) { + level.addHover(this._elMap.text, { + opacity: style.maskOpacity, + textFill: color.lift(style.textHover2Color, style.liftLevel) + }); + } + } + + doInactive(zr) { + const level = zr||this.__zr; + if ( this._elMap.button && level) { + level.removeHover(this._elMap.button); + } + + if ( this._elMap.text && level) { + level.removeHover(this._elMap.text); + } + } + + getViewTipsPoint() { + if (this._elMap.button) { + const button = this._elMap.button.getBoundingRect(); + return { + x: button.x + button.width/2, + y: button.y + }; + } + } +} diff --git a/src/iscs_new/package/panel/Table/index.js b/src/iscs_new/package/panel/Table/index.js new file mode 100644 index 000000000..b6aaf5f44 --- /dev/null +++ b/src/iscs_new/package/panel/Table/index.js @@ -0,0 +1,144 @@ +import * as graphic from '../../../graph/graphic'; +import panelType from '../../../constant/panelType'; + +export default class Table extends graphic.Group { + constructor(painter, shape) { + super(); + this._code = shape.model.code; + this._type = shape.model._type; + this._shape = shape; + this._painter = painter; + this._elMap = { + table: null + }; + + this.create(); + + this.on('mouseover', this.mouseover, this); + this.on('mouseout', this.mouseout, this); + } + + mouseover(e) { + if (this._shape.draw) { + this.doActive(this.__zr); + } + } + + mouseout(e) { + const map = this._painter.$map; + if (this._shape.draw && !map.isHover(this._code)) { + this.doInactive(this.__zr); + } + } + + create() { + const draw = this._shape.draw; + const model = this._shape.model; + const style = this._shape.style; + + this._elMap.header = new graphic.Rect({ + zlevel: model.zlevel, + z: model.z, + z2: -1, + cursor: draw? 'pointer': 'default', + shape: { + x: model.point.x, + y: model.point.y, + width: model.width, + height: style[panelType.Table].header.height + }, + style: { + stroke: model.lineColor, + lineWidth: model.lineWidth, + fill: model.headerBg + } + }); + + this._elMap.body = new graphic.Rect({ + zlevel: model.zlevel, + z: model.z, + z2: -1, + silent: true, + shape: { + x: model.point.x, + y: model.point.y+style[panelType.Table].header.height, + width: model.width, + height: model.height + }, + style: { + stroke: model.lineColor, + lineWidth: model.lineWidth, + fill: model.bodyBg + } + }); + + this._elMap.title = new graphic.Text({ + zlevel: model.zlevel, + z: model.z, + z2: 0, + cursor: draw? 'pointer': 'default', + style: { + x: model.point.x+model.width/2, + y: model.point.y+style[panelType.Table].header.height/2, + fontWeight: style[panelType.Table].header.fontWeight, + fontSize: style[panelType.Table].header.fontSize, + fontFamily: style.fontFamily, + text: model.title||'标题', + textAlign: 'center', + textVerticalAlign: 'middle' + } + }); + + Object.values(this._elMap).forEach(elem => { elem && elem instanceof Array? elem.forEach(el => this.add(el)): this.add(elem); }); + + } + + setShape(model) { + const style = this._shape.style; + + if (this._elMap.header) { + this._elMap.header.setShape({ + x: model.point.x, + y: model.point.y + }); + } + + if (this._elMap.body) { + this._elMap.body.setShape({ + x: model.point.x, + y: model.point.y+style[panelType.Table].header.height + }); + } + + if (this._elMap.title) { + this._elMap.title.setStyle({ + x: model.point.x+model.width/2, + y: model.point.y+style[panelType.Table].header.height/2 + }); + } + } + + setState(model, e) { + + } + + dragging(e) { + const model = this._shape.model; + + model.point.x += e.dx; + model.point.y += e.dy; + + this.setShape(model); + } + + doActive(zr) { + + } + + doInactive(zr) { + + } + + getViewTipsPoint() {} + +} diff --git a/src/iscs_new/package/panel/Text/index.js b/src/iscs_new/package/panel/Text/index.js new file mode 100644 index 000000000..dcd2e8b71 --- /dev/null +++ b/src/iscs_new/package/panel/Text/index.js @@ -0,0 +1,132 @@ +import * as color from 'zrender/src/tool/color'; +import * as graphic from '../../../graph/graphic'; + +export default class Text2 extends graphic.Group { + constructor(painter, shape) { + super(); + this._code = shape.model.code; + this._type = shape.model._type; + this._shape = shape; + this._painter = painter; + + this._rotation = null; + this._origin = null; + + this._elMap = { + text: null + }; + + this.create(); + + this.on('mouseover', this.mouseover, this); + this.on('mouseout', this.mouseout, this); + } + + mouseover(e) { + if (this._shape.draw) { + this.doActive(this.__zr); + } + } + + mouseout(e) { + const map = this._painter.$map; + if (this._shape.draw && !map.isHover(this._code)) { + this.doInactive(this.__zr); + } + } + + create() { + const draw = this._shape.draw; + const model = this._shape.model; + const backGroundColor = this.getTextBgColor(model); + const textStyle = this.getTextStyle(model); + + this._rotation = -Math.PI / 180 * Number(model.rotate||0); + this._origin = [model.point.x, model.point.y]; + + this._elMap.text = new graphic.Text({ + zlevel: model.zlevel, + z: model.z, + origin: this._origin, + rotation: this._rotation, + silent: !draw, + style: { + x: model.point.x, + y: model.point.y, + fontWeight: 'normal', + textBackgroundColor: backGroundColor, + fontSize: model.fontSize, + fontFamily: model.font, + text: textStyle.textValue || textStyle.value || '', + textLineHeight: model.fontSize+4, + textFill: model.fontColor, + textPadding: [4, 4], + textAlign: textStyle.textAlign, + textVerticalAlign: 'middle' + } + }); + + this.setState(model); + + Object.values(this._elMap).forEach(elem => { elem && elem instanceof Array? elem.forEach(el => this.add(el)): this.add(elem); }); + } + + getTextStyle(model) { + const pattern = /\{<(?\w+)>\}\{<(?\w+)>\}(?(.|\n)*)|(?(.|\n)*)/; + const groups = (pattern.exec(model.name)||{}).groups||{}; + return groups; + } + + getTextBgColor(model) { + const pattern = /\{<(?\w+)>\}(?(.|\n)*)/; + const groups = (pattern.exec(model.backGroundColor)||{}).groups||{}; + + return groups.active == 'image' + ? { image: `${process.env.VUE_APP_BASE_RESOURCE_URL}${groups.string}` } + : groups.active == 'color' + ? groups.string + : model.backGroundColor; + } + + setShape(model) { + if (this._elMap.text) { + this._origin = [model.point.x, model.point.y]; + this._elMap.text.attr('origin', this._origin); + this._elMap.text.setStyle({ + x: model.point.x, + y: model.point.y + }); + } + } + + setState(model) { + } + + dragging(e) { + const model = this._shape.model; + + model.point.x += e.dx; + model.point.y += e.dy; + this.setShape(model); + } + + doActive(zr) { + const style = this._shape.style; + const level = zr||this.__zr; + if (this._elMap.text && level) { + level.addHover(this._elMap.text, { + opacity: style.maskOpacity, + textBackgroundColor: color.lift(style.textHover2Color, style.liftLevel) + }); + } + } + + doInactive(zr) { + const level = zr||this.__zr; + if (this._elMap.text && level) { + level.removeHover(this._elMap.text); + } + } + + getViewTipsPoint() {} +} diff --git a/src/iscs_new/package/panel/Warning/index.js b/src/iscs_new/package/panel/Warning/index.js new file mode 100644 index 000000000..2831c67f1 --- /dev/null +++ b/src/iscs_new/package/panel/Warning/index.js @@ -0,0 +1,172 @@ +import RadialGradient from 'zrender/src/graphic/RadialGradient'; +import * as graphic from '../../../graph/graphic'; +import * as color from 'zrender/src/tool/color'; +import panelType from '../../../constant/panelType'; +import ConstConfig from '@/scripts/ConstConfig'; + +export default class Warning extends graphic.Group { + constructor(painter, shape, state) { + super(); + this._code = shape.model.code; + this._type = shape.model._type; + this._shape = shape; + this._state = state; + this._painter = painter; + this._state = state; + this._elMap = { + circle: null + }; + + this.create(); + + this.on('mouseover', this.mouseover, this); + this.on('mouseout', this.mouseout, this); + } + + mouseover(e) { + const model = this._shape.model; + if (this._shape.draw) { + this.doActive(this.__zr); + } else if (model.description) { + this._painter.$tipsHandle.trigger('show', { + x: e.offsetX, + y: e.offsetY, + text: model.description, + target: e.target + }); + } + } + + mouseout(e) { + const map = this._painter.$map; + if (this._shape.draw && !map.isHover(this._code)) { + this.doInactive(this.__zr); + } else { + this._painter.$tipsHandle.trigger('hide'); + } + } + + create() { + const model = this._shape.model; + const style = this._shape.style; + const distance = 8; + + this._elMap.circle = new graphic.Circle({ + zlevel: model.zlevel, + z: model.z, + shape: { + cx: model.point.x, + cy: model.point.y, + r: model.radius||10 + }, + style: { + lineWidth: style[panelType.Warning].circle.lineWidth, + stroke: style[panelType.Warning].circle.stroke, + fill: new RadialGradient(0.5, 0.5, 0.5, [ + {offset: 0, color: '#eeeeee'}, + {offset: 1, color: '#666666'} + ]) + } + }); + + const signX = ConstConfig.ConstMap.LocationMode.Left.value == model.showPosition + ? -1 + : ConstConfig.ConstMap.LocationMode.Right.value == model.showPosition + ? 1 + : 0; + const signY = ConstConfig.ConstMap.LocationMode.Top.value == model.showPosition + ? -1 + : ConstConfig.ConstMap.LocationMode.Bottom.value == model.showPosition + ? 1 + : 0; + this._elMap.text = new graphic.Text({ + zlevel: model.zlevel, + z: model.z, + style: { + x: model.point.x + signX*(model.radius+distance), + y: model.point.y + signY*(model.radius+distance*2), + fontFamily: style.fontFamily, + fontWeight: style[panelType.Warning].text.fontWeight, + fontSize: style[panelType.Warning].text.fontSize, + textFill: style[panelType.Warning].text.textFill, + textVerticalAlign: 'middle', + text: model.description, + textAlign: ConstConfig.ConstMap.LocationMode.Left.value == model.showPosition + ? 'right' + : ConstConfig.ConstMap.LocationMode.Right.value == model.showPosition + ? 'left' + : 'center' + } + }); + + model.textShow? this._elMap.text.show(): this._elMap.text.hide(); + + this.setState(model); + + Object.values(this._elMap).forEach(elem => { elem && elem instanceof Array? elem.forEach(el => this.add(el)): this.add(elem); }); + } + + setShape(model) { + if (this._elMap.circle) { + this._elMap.circle.setShape({ + cx: model.point.x, + cy: model.point.y + }); + } + + if (this._elMap.text) { + const distance = 8; + const signX = ConstConfig.ConstMap.LocationMode.Left.value == model.showPosition + ? -1 + : ConstConfig.ConstMap.LocationMode.Right.value == model.showPosition + ? 1 + : 0; + const signY = ConstConfig.ConstMap.LocationMode.Top.value == model.showPosition + ? -1 + : ConstConfig.ConstMap.LocationMode.Bottom.value == model.showPosition + ? 1 + : 0; + this._elMap.text.setStyle({ + x: model.point.x + signX*(model.radius+distance), + y: model.point.y + signY*(model.radius+distance*2) + }); + } + } + + setState(model) { + } + + dragging(e) { + const model = this._shape.model; + + model.point.x += e.dx; + model.point.y += e.dy; + this.setShape(model); + } + + doActive(zr) { + const style = this._shape.style; + const level = zr||this.__zr; + if (this._elMap.circle && level) { + level.addHover(this._elMap.circle, { + opacity: style.maskOpacity, + fill: color.lift(style.graphHover2Color, style.liftLevel) + }); + } + } + + doInactive(zr) { + const level = zr||this.__zr; + if (this._elMap.circle &&level) { + level.removeHover(this._elMap.circle); + } + } + + getViewTipsPoint() { + const model = this._shape.model; + return { + x: model.point.x, + y: model.point.y + }; + } +} diff --git a/src/iscs_new/package/panel/index.js b/src/iscs_new/package/panel/index.js new file mode 100644 index 000000000..d984efc07 --- /dev/null +++ b/src/iscs_new/package/panel/index.js @@ -0,0 +1,29 @@ +import panelType from '../../constant/panelType'; + +import Text2 from './Text/index'; +import Table from './Table/index'; +import LinePipe from './LinePipe/index'; +import Resource from './Resource/index'; +import Measure from './Measure/index'; +import Warning from './Warning/index'; +import Switching from './Switching/index'; +import Popup from './Popup/index'; +import ProgramControl from './ProgramControl/index'; +import Pid from './Pid/index'; + +/** 图库*/ +const mapShape = {}; + +mapShape[panelType.Text] = Text2; +mapShape[panelType.Table] = Table; +mapShape[panelType.LinePipe] = LinePipe; +mapShape[panelType.Resource] = Resource; +mapShape[panelType.Measure] = Measure; +mapShape[panelType.Warning] = Warning; +mapShape[panelType.Switching] = Switching; +mapShape[panelType.Popup] = Popup; +mapShape[panelType.ProgramControl] = ProgramControl; +mapShape[panelType.Pid] = Pid; + +export default mapShape; + diff --git a/src/iscs_new/painter.js b/src/iscs_new/painter.js new file mode 100644 index 000000000..25608c622 --- /dev/null +++ b/src/iscs_new/painter.js @@ -0,0 +1,229 @@ +import * as zrUtil from 'zrender/src/core/util'; +import * as vector from 'zrender/src/core/vector'; +import Graphic from './package'; +import Group from 'zrender/src/container/Group'; +import graphType from './constant/graphType'; +import panelType from './constant/panelType'; +import resourceType from './constant/resourceType'; +import TransformHandle from './transformHandle'; +import StateHandle from './stateHandle'; +import TipsHandle from './tipsHandle'; +import { ParserType } from './parser/index.js'; + +function traverseLayers(layers) { + return (inject) => { + inject(layers, type => { return layers.includes(type); }); + }; +} + +class Painter { + constructor(map) { + this.$map = map; + this.$zr = map.getZr(); + + // 图层数据 + this.mapInstanceLevel = {}; + + // 初始图层 + this.initLevels(); + + // 视图控制器 + this.$transformHandle = new TransformHandle(this); + + // 状态处理器 + this.$stateHandle = new StateHandle(map); + + // 提示处理器 + this.$tipsHandle = new TipsHandle(map); + } + + initLevels() { + // 图层分级策略 + // 预留图层级功能 默认全部显示 + this.parserBranch = {}; + this.parserBranch[ParserType.Graph.value] = traverseLayers(Object.values(graphType)); + this.parserBranch[ParserType.Panel.value] = traverseLayers(Object.values(panelType)); + this.parserBranch[ParserType.Resource.value] = traverseLayers(Object.values(resourceType)); + + // 添加父级图层 + this.parentLevel = new Group({ name: '__parent__' }); + this.$zr.add(this.parentLevel); + + // 添加hover子级图层 + this.hoverLevel = new Group({ name: `___hover__` }); + this.parentLevel.add(this.hoverLevel); + + // 添加提示子级图层 + this.tipsLevel = new Group({name: `__tips__`}); + this.parentLevel.add(this.tipsLevel); + + // 添加设备子级图层 + // 添加设备模板子级图层 + zrUtil.each([ + ...Object.values(graphType), + ...Object.values(panelType), + ...Object.values(resourceType)], type => { + const level = new Group({ name: `__${type}__` }); + this.mapInstanceLevel[type] = level; + this.parentLevel.add(level); + }); + } + + newGraph(shape) { + const type = shape.model._type; + const state = this.$map.getState(); // 获取 默认状态 + const builder = Graphic.getBuilder(type); // 根据 type 绘制 面板,资源,画面对应的 instance + return builder(this, shape, state); + } + + doHover(view, visible=true) { + visible + ? this.$map.isHover(view._code) + ? view.doActive + ? view.doActive(this.$zr) + : null + : view.doInactive + ? view.doInactive(this.$zr) + : null + : view.doInactive + ? view.doInactive() + : null; + } + + add(shape) { + try { + this.delete(shape); + shape.instance = this.newGraph(shape); + if (shape.instance) { + this.$transformHandle.transformView(shape.instance); + this.mapInstanceLevel[shape.model._type].add(shape.instance); // 添加type + this.doHover(shape.instance); + } + } catch (err) { + console.error(err); + } + } + + delete(shape) { + if (shape.hover) { + this.hoverLevel.remove(shape.hover); + shape.hover = null; + } + + if (shape.instance) { + shape.instance.doInactive(this.$zr); + this.mapInstanceLevel[shape.model._type].remove(shape.instance); + } + } + // 更新设备状态 + update(shape) { + try { + if (shape) { + this.$stateHandle.update(shape); + } + } catch (err) { + console.error(err); + } + } + + updateTransform(opt) { + this.$transformHandle.updateTransform(opt); + } + + updateZrSize(opt) { + this.$transformHandle.updateZrSize(opt); + } + + addHoverElem(view) { + this.$transformHandle.transformView(view); + this.hoverLevel.add(view); + } + + delHoverElem(view) { + this.hoverLevel.remove(view); + } + + setLayerVisible(typeList, parserType = ParserType.Graph.value) { + this.parserBranch[parserType]((layers, check) => { + zrUtil.each(layers, type => { + const instance = this.mapInstanceLevel[type]; + if (check(type) && typeList.includes(type)) { + this.parentLevel.add(instance); + } else { + this.parentLevel.remove(instance); + } + }, this); + }); + } + + setResourceVisible(view, visible) { + const instance = this.mapInstanceLevel[graphType.Resource]; + if (instance) { + if (visible) { + this.$transformHandle.transformView(view); + instance.add(view); + } else { + instance.remove(view); + } + } + } + + refresh() { + this.$zr.refresh(); + } + + clear() { + if (this.hoverLevel) { + this.hoverLevel.removeAll(); + } + + zrUtil.each(Object.values(this.mapInstanceLevel), (level) => { + level && level.removeAll(); + }, this); + + this.refresh(); + } + + dispose() { + this.clear(); + this.mapInstanceLevel = {}; + this.parentLevel = null; + this.$tipsHandle.dispose(); + } + + getMapShape() { + return this.$map.getMapShape(); + } + + getShapeByCode(code) { + return this.$map.getShapeByCode(code); + } + + getViewTipsPoint(step) { + const shape = this.getShapeByCode(step.code)||{}; + const instance = shape.instance; + + if (instance) { + const point = instance.getViewTipsPoint(); + + if (point) { + const transform = this.$transformHandle.getTransform(); + const transPoint = vector.applyTransform([], [point.x, point.y], transform); + return { + x: transPoint[0], + y: transPoint[1] + }; + } + } + } + + getParentLevel() { + return this.parentLevel; + } + + getTipsLevel() { + return this.tipsLevel; + } +} + +export default Painter; diff --git a/src/iscs_new/parser/index.js b/src/iscs_new/parser/index.js new file mode 100644 index 000000000..970df5d6b --- /dev/null +++ b/src/iscs_new/parser/index.js @@ -0,0 +1,21 @@ +import * as parserGraph from './parser-graph.js'; +import * as parserResource from './parser-resource.js'; +import * as parserPanel from './parser-panel.js'; + +export const ParserType = { + Graph: { name: '绘图', value: 'Graph' }, + Data: { name: '数据', value: 'Data' }, + Panel: { name: '面板', value: 'Panel'}, + Resource: { name: '资源', value: 'Resource'} +}; + +export function parserFactory(type) { + switch (type) { + case ParserType.Data.value: + case ParserType.Graph.value : return parserGraph; + case ParserType.Resource.value: return parserResource; + case ParserType.Panel.value: return parserPanel; + } + + return parserGraph; +} diff --git a/src/iscs_new/parser/parser-graph.js b/src/iscs_new/parser/parser-graph.js new file mode 100644 index 000000000..2c7bb5b6b --- /dev/null +++ b/src/iscs_new/parser/parser-graph.js @@ -0,0 +1,199 @@ +import * as zrUtil from 'zrender/src/core/util'; +import * as utils from '../utils/utils'; +import graphType from '../constant/graphType'; +import graphRender from '../constant/graphRender'; +import graphStyle from '../config/graphStyle'; + +// 创建一个Shape结构 +export function newShape(entity, type, model) { + return { model: Object.assign(model, graphRender[type], {entity}), style: graphStyle, instance: null, hover: null, dragging: false, draw: false }; +} + +// 解析绘图原始数据 +export function parse(state, data, isDraw) { + const mapLink = state.mapLink; + const mapEntity = state.mapEntity; + const mapShape = {}; + + try { + if (data) { + // 文字 + zrUtil.each(data.textList||[], el => { + const entity = { type: 'Text', data: {}}; + mapShape[el.code] = newShape(entity, graphType.Text, el); + }, this); + + // 按钮 + zrUtil.each(data.buttonList||[], el => { + const entity = { type: 'Button', data: {}}; + mapShape[el.code] = newShape(entity, graphType.Button, el); + }, this); + + // 表 + zrUtil.each(data.tableList||[], el => { + const entity = { type: 'Table', data: {}}; + mapShape[el.code] = newShape(entity, graphType.Table, el); + }, this); + + // 表1 + zrUtil.each(data.tableList||[], el => { + const entity = { type: 'Table1', data: {}}; + mapShape[el.code] = newShape(entity, graphType.Table1, el); + }, this); + + // 资源 + zrUtil.each(data.resourceList||[], el => { + const link = utils.getLinkByModel(mapLink, {...el, _type: graphType.Resource})||{}; + const entity = isDraw + ? mapEntity[link.code]||{} + : mapEntity[link.code] = { code: link.code, type: link.type, data: {}}; + mapShape[el.code] = newShape(entity, graphType.Resource, el); + }, this); + + // 管线 + zrUtil.each(data.linePipeList||[], el => { + const link = utils.getLinkByModel(mapLink, {...el, _type: graphType.LinePipe})||{}; + const entity = isDraw + ? mapEntity[link.code]||{} + : mapEntity[link.code] = { code: link.code, type: 'Pipe', data: {}}; + + mapShape[el.code] = newShape(entity, graphType.LinePipe, el); + }, this); + + // 计量 + zrUtil.each(data.measureList||[], el => { + const entity = { type: graphType.Measure, data: {}}; + mapShape[el.code] = newShape(entity, graphType.Measure, el); + }, this); + + // 报警 + zrUtil.each(data.warningList||[], el => { + const entity = { type: graphType.Warning, data: {}}; + mapShape[el.code] = newShape(entity, graphType.Warning, el); + }, this); + + // 投切按钮 + zrUtil.each(data.switchingList||[], el => { + const entity = { type: graphType.Switching, data: {}}; + mapShape[el.code] = newShape(entity, graphType.Switching, el); + }, this); + + // 弹窗按钮 + zrUtil.each(data.popupList||[], el => { + const entity = { type: graphType.Popup, data: {}}; + mapShape[el.code] = newShape(entity, graphType.Popup, el); + }, this); + + // 程制按钮 + zrUtil.each(data.programControlList||[], el => { + const entity = { type: graphType.ProgramControl, data: {}}; + mapShape[el.code] = newShape(entity, graphType.ProgramControl, el); + }, this); + + // Pid按钮 + zrUtil.each(data.pidList||[], el => { + const entity = { type: graphType.Pid, data: {}}; + mapShape[el.code] = newShape(entity, graphType.Pid, el); + }, this); + } + } catch (error) { + console.error('[ERROR] ', error); + } + + return mapShape; +} + +// 处理依赖关系 +export function analysis (state) { + const mapLink = state.mapLink || {}; // 关联关系 + const mapEntity = state.mapEntity || {}; // 实体数据 + const mapShape = state.mapShape || {}; // 绘图code数据 + const mapDependency = {}; + + function push(set, model) { + set.add(model.code); + } + + function complateSelf(model, entity) { + if (entity && entity.code) { + let dependency = mapDependency[entity.code]; + if (!dependency) dependency = mapDependency[entity.code] = {}; + if (!dependency['Self']) dependency['Self'] = new Set(); + push(dependency['Self'], model); + } + } + + function complateDependency(model, entity) { + if (entity && entity.code) { + let dependency = mapDependency[entity.code]; + if (!dependency) dependency = mapDependency[entity.code] = {}; + if (!dependency[model._type]) dependency[model._type] = new Set(); + push(dependency[model._type], model); + } + } + + try { + Object.values(mapShape).forEach(({model}) => { + const link = utils.getLinkByModel(mapLink, model) || {}; // link关系 + const entity = utils.getEntityByModel(mapEntity, mapLink, model) || {}; // 实体数据 + + if (mapEntity[link.code] && !link.hasOwnProperty('prop')) { // 排查计量 设置为 self + complateSelf(model, entity); + } + + if ([graphType.Resource].includes(model._type)) { + const attrList = entity.attrList; + const attrObj = utils.getObjInListBySign(attrList, 'deviceCode'); + + if (attrObj && attrObj.value) { + const entity = mapEntity[attrObj.value] || {}; + complateDependency(model, entity); + } + } else if (link.code && link.hasOwnProperty('prop')) { + const entity = mapEntity[link.code]||{}; + complateDependency(model, entity); + } + }); + } catch (error) { + console.error(`[ERROR] `, error); + } + return mapDependency; +} + +// 更新绘图原始组列表数据 +export function update2List(model, map, name) { + const list = map[name]; + if (list && list instanceof Array) { + const i = list.findIndex(elem => { return elem.code == model.code; }); + if (model._dispose) { + i >= 0 && list.splice(i, 1); + } else if (!list[i]) { + list.push(model); + } else { + Object.assign(list[i], model); + } + } else { + map[name] = [model]; + } +} + +// 更新绘图的数据 +export function updateData(state, model) { + const map = state.map; + if (map && model) { + switch (model._type) { + case graphType.Text: update2List(model, map, 'textList'); break; + case graphType.Button: update2List(model, map, 'buttonList'); break; + case graphType.Table: update2List(model, map, 'tableList'); break; + case graphType.Table1: update2List(model, map, 'table1List'); break; + case graphType.Resource: update2List(model, map, 'resourceList'); break; + case graphType.LinePipe: update2List(model, map, 'linePipeList'); break; + case graphType.Measure: update2List(model, map, 'measureList'); break; + case graphType.Warning: update2List(model, map, 'warningList'); break; + case graphType.Switching: update2List(model, map, 'switchingList'); break; + case graphType.Popup: update2List(model, map, 'popupList'); break; + case graphType.ProgramControl: update2List(model, map, 'programControlList'); break; + case graphType.Pid: update2List(model, map, 'pidList'); break; + } + } +} diff --git a/src/iscs_new/parser/parser-panel.js b/src/iscs_new/parser/parser-panel.js new file mode 100644 index 000000000..e573e5d89 --- /dev/null +++ b/src/iscs_new/parser/parser-panel.js @@ -0,0 +1,195 @@ +import * as zrUtil from 'zrender/src/core/util'; +import * as utils from '../utils/utils'; +import panelType from '../constant/panelType'; +import panelRender from '../constant/panelRender'; +import panelStyle from '../config/panelStyle'; + +// 创建一个Shape结构 +export function newShape(entity, type, model) { + return { model: Object.assign(model, panelRender[type], {entity}), style: panelStyle, instance: null, hover: null, dragging: false, draw: false }; +} + +// 解析绘图原始数据 +export function parse(state, data, isDraw) { + const mapLink = state.mapLink; + const mapEntity = state.mapEntity; + const mapShape = {}; + + try { + if (data) { + // 文字 + zrUtil.each(data.textList||[], el => { + const entity = { type: 'Text', data: {}}; + mapShape[el.code] = newShape(entity, panelType.Text, el); + }, this); + + // 按钮 + zrUtil.each(data.buttonList||[], el => { + const entity = { type: 'Button', data: {}}; + mapShape[el.code] = newShape(entity, panelType.Button, el); + }, this); + + // 表 + zrUtil.each(data.tableList||[], el => { + const entity = { type: 'Table', data: {}}; + mapShape[el.code] = newShape(entity, panelType.Table, el); + }, this); + + // 资源 + zrUtil.each(data.resourceList||[], el => { + const link = utils.getLinkByModel(mapLink, {...el, _type: panelType.Resource})||{}; + const entity = isDraw + ? mapEntity[link.code]||{} + : mapEntity[link.code] = { code: link.code, type: link.type, data: {}}; + mapShape[el.code] = newShape(entity, panelType.Resource, el); + }, this); + + // 管线 + zrUtil.each(data.linePipeList||[], el => { + const link = utils.getLinkByModel(mapLink, {...el, _type: panelType.LinePipe})||{}; + const entity = isDraw + ? mapEntity[link.code]||{} + : mapEntity[link.code] = { code: link.code, type: 'Pipe', data: {}}; + + mapShape[el.code] = newShape(entity, panelType.LinePipe, el); + }, this); + + // 计量 + zrUtil.each(data.measureList||[], el => { + const entity = { type: panelType.Measure, data: {}}; + mapShape[el.code] = newShape(entity, panelType.Measure, el); + }, this); + + // 报警 + zrUtil.each(data.warningList||[], el => { + const entity = { type: panelType.Warning, data: {}}; + mapShape[el.code] = newShape(entity, panelType.Warning, el); + }, this); + + // 投切按钮 + zrUtil.each(data.switchingList||[], el => { + const entity = { type: panelType.Switching, data: {}}; + mapShape[el.code] = newShape(entity, panelType.Switching, el); + }, this); + + // 弹窗按钮 + zrUtil.each(data.popupList||[], el => { + const entity = { type: panelType.Popup, data: {}}; + mapShape[el.code] = newShape(entity, panelType.Popup, el); + }, this); + + // 程制按钮 + zrUtil.each(data.programControlList||[], el => { + const entity = { type: panelType.ProgramControl, data: {}}; + mapShape[el.code] = newShape(entity, panelType.ProgramControl, el); + }, this); + + // Pid按钮 + zrUtil.each(data.pidList||[], el => { + const entity = { type: panelType.Pid, data: {}}; + mapShape[el.code] = newShape(entity, panelType.Pid, el); + }, this); + } + } catch (error) { + console.error('[ERROR] ', error); + } + + return mapShape; +} + +// 分析依赖关系 +export function analysis (state) { + const mapLink = state.mapLink||{}; + const mapEntity = state.mapEntity||{}; + const mapShape = state.mapShape||{}; + const mapDependency = {}; + + function push(set, model) { + set.add(model.code); + } + + function complateSelf(model, entity) { + if (entity && + entity.code) { + let dependency = mapDependency[entity.code]; + if (!dependency) dependency = mapDependency[entity.code] = {}; + if (!dependency['Self']) dependency['Self'] = new Set(); + push(dependency['Self'], model); + } + } + + function complateDependency(model, entity) { + if (entity && + entity.code) { + let dependency = mapDependency[entity.code]; + if (!dependency) dependency = mapDependency[entity.code] = {}; + if (!dependency[model._type]) dependency[model._type] = new Set(); + push(dependency[model._type], model); + } + } + + try { + Object.values(mapShape).forEach(({model}) => { + const link = utils.getLinkByModel(mapLink, model)||{}; + const entity = utils.getEntityByModel(mapEntity, mapLink, model)||{}; + + if (mapEntity[link.code] && !link.hasOwnProperty('prop')) { + complateSelf(model, entity); + } + + if ([panelType.Resource].includes(model._type)) { + const attrList = entity.attrList; + const attrObj = utils.getObjInListBySign(attrList, 'deviceCode'); + + if (attrObj && attrObj.value) { + const entity = mapEntity[attrObj.value]||{}; + complateDependency(model, entity); + } + } else if (link.code && link.hasOwnProperty('prop') ) { + const entity = mapEntity[link.code]||{}; + complateDependency(model, entity); + } + }); + } catch (error) { + console.error(`[ERROR] `, error); + } + + return mapDependency; +} + +// 更新绘图原始组列表数据 +export function update2List(model, map, name) { + const list = map[name]; + if (list && list instanceof Array) { + const i = list.findIndex(elem => { return elem.code == model.code; }); + if (model._dispose) { + i >= 0 && list.splice(i, 1); + } else if (!list[i]) { + list.push(model); + } else { + Object.assign(list[i], model); + } + } else { + map[name] = [model]; + } +} + +// 更新绘图的数据 +export function updateData(state, model) { + const map = state.map; + if (map && model) { + switch (model._type) { + case panelType.Text: update2List(model, map, 'textList'); break; + case panelType.Button: update2List(model, map, 'buttonList'); break; + case panelType.Table: update2List(model, map, 'tableList'); break; + case panelType.Resource: update2List(model, map, 'resourceList'); break; + case panelType.LinePipe: update2List(model, map, 'linePipeList'); break; + case panelType.Measure: update2List(model, map, 'measureList'); break; + case panelType.Warning: update2List(model, map, 'warningList'); break; + case panelType.Switching: update2List(model, map, 'switchingList'); break; + case panelType.Popup: update2List(model, map, 'popupList'); break; + case panelType.ProgramControl: update2List(model, map, 'programControlList'); break; + case panelType.Pid: update2List(model, map, 'pidList'); break; + } + } +} diff --git a/src/iscs_new/parser/parser-resource.js b/src/iscs_new/parser/parser-resource.js new file mode 100644 index 000000000..796fb7474 --- /dev/null +++ b/src/iscs_new/parser/parser-resource.js @@ -0,0 +1,123 @@ +import * as zrUtil from 'zrender/src/core/util'; +import Graphic from '../package'; +import * as utils from '../utils/utils'; +import panelType from '../constant/panelType'; +import resourceStyle from '../config/resourceStyle'; +import resourceType from '../constant/resourceType'; +import resourceRender from '../constant/resourceRender'; +import Vue from 'vue'; + +// 创建一个Shape结构 +export function newShape(entity, type, model) { + return { model: Object.assign(model, resourceRender[type], {entity}), style: resourceStyle, instance: null, hover: null, dragging: false, draw: false }; +} + +// 创建一个图形 +export function newGraph(type, model, base) { + const clonedModel = utils.deepClone(model); + clonedModel.point.x += base.point.x; + clonedModel.point.y += base.point.y; + clonedModel.origin = base.origin; + clonedModel.rotation = base.rotation; + clonedModel.scale = base.scale; + clonedModel.parentTag = base.parentTag; + clonedModel.layer = base.layer+10; + clonedModel.attrList = base.attrList; + clonedModel.dialog = base.dialog; + const builder = Graphic.getBuilder(type); // 根据 type 绘制 面板,资源,画面对应的 instance + + return builder(Vue.prototype.$map.getPainter(), newShape({}, type, clonedModel), {is: true}); +} + +export function parse(state, data, isDraw) { + const mapDevice = {}; + + try { + if (data) { + if (!data.background) { + data.background = { code: utils.getUID('Resource'), url: '', width: 200, height: 200, point: { x: 0, y: 0 } }; + } + + mapDevice[data.background.code] = newShape({}, resourceType.Background, Object.assign(data.background, {scale: [1, 1]}) ); + + zrUtil.each(data.buttonList||[], elem => { + mapDevice[elem.code] = newShape({}, resourceType.Button, Object.assign(elem, {scale: [1, 1]})); + }, this); + + zrUtil.each(data.displayList||[], elem => { + mapDevice[elem.code] = newShape({}, resourceType.Display, Object.assign(elem, {scale: [1, 1]})); + }, this); + + zrUtil.each(data.pilotLampList||[], elem => { + mapDevice[elem.code] = newShape({}, resourceType.PilotLamp, Object.assign(elem, {scale: [1, 1]})); + }, this); + + zrUtil.each(data.textList||[], elem => { + mapDevice[elem.code] = newShape({}, resourceType.Text, Object.assign(elem, {scale: [1, 1]})); + }, this); + } + } catch (error) { + console.log(error); + } + + return mapDevice; +} + +export function generator(data, base, draw) { + const elMap = {}; + + try { + if (data) { + if (data.background) { + data.background._silent = true; + elMap[resourceType.Background] = newGraph(resourceType.Background, data.background, base, draw); + } + + elMap[resourceType.Button] = []; + zrUtil.each(data.buttonList||[], elem => { + elMap[resourceType.Button].push(newGraph(resourceType.Button, elem, base, draw)); + }, this); + + elMap[resourceType.Display] = []; + zrUtil.each(data.displayList||[], elem => { + elMap[resourceType.Display].push(newGraph(resourceType.Display, elem, base, draw)); + }, this); + + elMap[resourceType.PilotLamp] = []; + zrUtil.each(data.pilotLampList||[], elem => { + elMap[resourceType.PilotLamp].push(newGraph(resourceType.PilotLamp, elem, base, draw)); + }, this); + } + } catch (error) { + console.log(error); + } + + return elMap; +} + +export function update2List(model, map, name) { + const list = map[name]; + if (list && list instanceof Array) { + const i = list.findIndex(elem => { return elem.code == model.code; }); + if (model._dispose) { + i >= 0 && list.splice(i, 1); + } else if (!list[i]) { + list.push(model); + } else { + Object.assign(list[i], model); + } + } else { + map[name] = [model]; + } +} + +export function updateData(state, model) { + const map = state.map; + if (map && model) { + switch (model._type) { + case resourceType[panelType.Resource].Button: update2List(model, map, 'buttonList'); break; + case resourceType[panelType.Resource].PilotLamp: update2List(model, map, 'pilotLampList'); break; + case resourceType[panelType.Resource].Display: update2List(model, map, 'displayList'); break; + } + } +} diff --git a/src/iscs_new/selectHandle.js b/src/iscs_new/selectHandle.js new file mode 100644 index 000000000..6003c8a4d --- /dev/null +++ b/src/iscs_new/selectHandle.js @@ -0,0 +1,94 @@ + +import graphType from './constant/graphType'; +import LineDraggable from './draggable/Line'; +import ImageDraggable from './draggable/Image'; + +export default class SelectHandle { + constructor(map, controller) { + this.$map = map; + this.$zr = map.getZr(); + this.$controller = controller; + this.$painter = map.getPainter(); + + this.e = {}; + } + + onSelected(e) { + if (e.target && e.target.instance) { + this.e = {...e }; + if (['Control'].includes(this.$controller.getKeyStr())) { + if (this.$map.isHover(e.target.model.code)) { + this.delSelected(e.target); + } else { + this.addSelected(e.target); + } + } else if (this.$controller.storage.isSelectSelf(e.target.model.code)) { + this.addSelected(e.target); + } else { + this.clear(); + this.addSelected(e.target); + } + } + } + + addSelected(target) { + this.$controller.storage.set(target.model.code, target); + + if (target.instance.doActive) { + target.instance.doActive(this.$zr); + } + + if (!target.hover) { + target.hover = this.newHover(target); + this.$painter.addHoverElem(target.hover); + } + } + + delSelected(target) { + if (target.instance.doInactive) { + target.instance.doInactive(this.$zr); + } + + if (target.hover) { + this.$painter.delHoverElem(target.hover); + target.hover = null; + } + + this.$controller.storage.delete(target.model.code); + } + + clear() { + this.$controller.storage.values().forEach(target => { + this.delSelected(target); + }); + } + + setDraggable(draggable) { + const target = this.e.target; + if (target && target.hover) { + target.hover.setDraggable(draggable); + } + } + + newHover(target) { + if (this.$map.draggle) { + switch (target.model._type) { + case graphType.LinePipe: + return new LineDraggable(this); + case graphType.Resource: + return new ImageDraggable(this); + } + } + } + + render(list) { + this.$map.render(list); + } + + normalizedDiff(x, y) { + const options = this.$map.getOptions(); + const dx = x / options.scaleRate; + const dy = y / options.scaleRate; + return [dx, dy]; + } +} diff --git a/src/iscs_new/selectingHandle.js b/src/iscs_new/selectingHandle.js new file mode 100644 index 000000000..3f28c0ad0 --- /dev/null +++ b/src/iscs_new/selectingHandle.js @@ -0,0 +1,82 @@ +import * as graphic from './graph/graphic.js'; + +export default class SelectingHandle { + constructor(map, controller) { + this.$map = map; + this.$zr = map.getZr(); + this.$controller = controller; + this.$painter = map.getPainter(); + + this.begPoint = null; + this.endPoint = null; + this.hover = new graphic.Rect({ + _subType: 'selectingEl', + zlevel: 999, + shape: { + x: 0, + y: 0, + width: 0, + height: 0 + }, + style: { + lineWidth: 0, + stroke: '#000', + fill: 'rgba(200,200,200,0.3)' + } + }); + } + + isSelecting() { + return this.begPoint; + } + + onSelectStart(e) { + // console.log(e, '左键点击'); + this.hover.setShape({ x: e.x, y: e.y, width: 0, height: 0 }); + this.$painter.addHoverElem(this.hover); + this.begPoint = { x: e.x, y: e.y }; + this.endPoint = null; + } + + onSelecting(e) { + // console.log(e, '移动'); + this.endPoint = { x: e.x, y: e.y }; + this.hover.setShape(this.normalizedArea(this.begPoint, this.endPoint)); + this.$painter.addHoverElem(this.hover); + } + + onSelectEnd(e) { + // console.log(e, '鼠标抬起'); + this.endPoint = { x: e.x, y: e.y }; + this.hover.setShape(this.normalizedArea(this.begPoint, this.endPoint)); + this.$painter.addHoverElem(this.hover); + + const hoverRect = this.hover.getBoundingRect(); + Object.values(this.$map.getMapShape()).forEach(elem => { + if (!elem.model._silent && elem.instance && hoverRect.intersect(elem.instance.getBoundingRect())) { + this.setSelected(elem); + } + }); + + this.clear(); + this.begPoint = this.endPoint = null; + } + + setSelected(target) { + target.instance.doActive(this.$zr); + this.$controller.storage.set(target.model.code, target); + } + + clear() { + this.$painter.delHoverElem(this.hover); + } + + normalizedArea(begin, end) { + const options = this.$map.getOptions(); + const x = (begin.x + options.offsetX) / options.scaleRate; + const y = (begin.y + options.offsetY) / options.scaleRate; + const width = (end.x - begin.x) / options.scaleRate; + const height = (end.y - begin.y) / options.scaleRate; + return {x, y, width, height}; + } +} diff --git a/src/iscs_new/stateHandle.js b/src/iscs_new/stateHandle.js new file mode 100644 index 000000000..53782eabc --- /dev/null +++ b/src/iscs_new/stateHandle.js @@ -0,0 +1,52 @@ +import graphType from './constant/graphType'; +import panelType from './constant/panelType'; +// 状态处理器 +export default class StateHandle { + constructor(map) { + this.$map = map; + } + + update(state) { + const rootState = this.$map.getState(); // 获取 store.state + this.updateState(rootState, state); // 处理实体关联绘图数据 + this.updateDepState(rootState, state); // 处理关联数据 + } + + updateState({mapShape}, state) { + const mapDependency = this.$map.getMapDependency(); // 依赖关系集合 + const dependency = mapDependency[state.code]||{}; + (dependency.Self||[]).forEach(code => { + this.__update2Self(mapShape[code], state); + }); + } + + updateDepState({mapShape}, state) { + const mapDependency = this.$map.getMapDependency(); + const dependency = mapDependency[state.code]||{}; + const mapper = { + [graphType.Measure]: this.__update2Measure, + [panelType.Measure]: this.__update2Measure + }; + + [...Object.values(graphType), ...Object.values(panelType)].forEach(type => { + const depList = dependency[type]||[]; + depList.forEach(code => { + const funcCb = mapper[type]; + if (funcCb) { + funcCb.call(this, mapShape[code], state); + } + }); + }); + } + + __update2Self({instance, model}, state) { + Object.assign(model.entity, state); + instance.setState(model); + } + + __update2Measure({instance, model}, state) { + const link = this.$map.getLinkByModel(model)||{}; + Object.assign(model.entity, {data: {value: state.data[link.prop]}}); + instance.setState(model); + } +} diff --git a/src/iscs_new/subMap/subMap.js b/src/iscs_new/subMap/subMap.js new file mode 100644 index 000000000..3bb86ebb8 --- /dev/null +++ b/src/iscs_new/subMap/subMap.js @@ -0,0 +1,180 @@ +import store from '@/store'; +import zrender from 'zrender'; +import * as utils from '../utils/utils'; +import Eventful from 'zrender/src/mixin/Eventful'; +import resourceType from '../constant/resourceType'; +import ConstConfig from '@/scripts/ConstConfig'; +import { generator } from '../parser/parser-resource'; + +const renderer = 'canvas'; +const devicePixelRatio = 1; + +export default class SubMap extends Eventful { + constructor(map) { + super(); + this.$map = map; + this.storageMap = {}; + this.cacheMap = {}; + } + + __updateDevice(list) { + list.forEach(el => { + const storage = this.storageMap[el.code]; + const cache = (storage || {}).cache; + if (storage && cache) { + cache.update(utils.initModelState(storage.model, {})); + } + }); + } + + register(opts) { + if (opts.dom) { + const width = opts.dom.clientWidth; + const height = opts.dom.clientHeight; + const canvasId = utils.getUID('canvas_'); + const zr = zrender.init(opts.dom, { renderer, devicePixelRatio, width, height, ...utils.deepClone(opts.config || {}) }); + const cache = { zr, update: null, layer: null }; + + opts.dom.setAttribute('canvasId', canvasId); + zr.dom.setAttribute('tabIndex', -1); + + this.cacheMap[canvasId] = cache; + + return cache; + } + } + + appendDevice(cache, model, data) { + const x = 80; + const y = 20; + + const layer = new zrender.Group({ name: '__shapes__' }); + + const elMap = generator(data.graphData||{}, { ...model, point: { x, y }, scale: 1, dialog: true }, false); + + cache.zr.clear(); + + cache.zr.add(layer); + + cache.layer = layer; + + cache.update = function (state) { + if (model && elMap && state) { + const els = Object.values(elMap); + utils.setModelState(model, state); + (function setState(el) { + if (el instanceof Array) { + el.forEach(it => { setState(it); }); + } else { + el.setState(model); + el.dirty(); + } + })(els); + } + }; + + Object.values(elMap).forEach(el => { + if (el instanceof Array) { + el.forEach(it => { layer.add(it); }); + } else if (el instanceof Object) { + layer.add(el); + } + }); + + layer.dirty(); + + this.on(`update-${model.code}`, cache.update); + + this.bindEvent(elMap, model); + + this.storageMap[model.code] = { model, elMap, cache }; + + cache.update(utils.initModelState(model, {})); + } + + bindEvent(elMap, model) { + const buttonList = elMap[resourceType.Button] || []; + const displayList = elMap[resourceType.Display] || []; + const attrObj = utils.getObjFormListBySign(model.attrList, 'deviceCode') || {}; + if (attrObj.val) { + const related = store.getters['map/getDeviceByCode'](attrObj.val); + displayList.forEach(display => { + buttonList.forEach(button => { + button.on('click', e => { + const control = model.control || {}; + if (!control.disabled) { + const operation = { + type: ConstConfig.ConstMap.TipsTrigger.SubMap.value, + code: `${button._val}`, + params: `${model.code}` + }; + + store.dispatch('training/next', operation).then(({ valid }) => { + if (valid) { + store.dispatch('menuOperation/handleBreakFlag', { break: true }); + display.execute(button._device.model.event, { ...e, target: button }); + display.dirty(); + } + }); + } + }); + }); + + display.on('updaterelated', state => { + if (related) { + utils.setModelState(related.model, state); + store.dispatch('training/updateState', [related.model]); + } + }); + + display.on('updateself', state => { + const device = store.getters['map/getDeviceByCode'](model.code); + if (device.instance) { + utils.setModelState(model, state); + device.instance.setState(model); + } + }); + }); + } + } + + traversed(map, cb) { + Object.values(map).forEach(el => { + if (el) { + if (el instanceof Array) { + this.traversed(el, cb); + } else { + cb(el); + } + } + }); + } + + dispose(cache) { + if (cache && cache.zr) { + const canvasId = cache.zr.dom.canvasId; + delete this.cacheMap[canvasId]; + + this.off('update', cache.update); + + cache.update = null; + cache.zr.dispose(); + cache.zr = null; + } + } + + getViewTipsPoint(step) { + const storage = this.storageMap[step.params]; + + if (storage) { + let point = null; + const dom = storage.cache.zr.dom; + this.traversed(storage.elMap, el => { + if (el._val == step.code) { + point = el.getViewTipsPoint(utils.getDomOffset(dom)); + } + }); + return point; + } + } +} diff --git a/src/iscs_new/tipsHandle.js b/src/iscs_new/tipsHandle.js new file mode 100644 index 000000000..259ce842e --- /dev/null +++ b/src/iscs_new/tipsHandle.js @@ -0,0 +1,72 @@ +import * as graphic from './graph/graphic'; +import Eventful from 'zrender/src/mixin/Eventful'; + +export default class TipsHandle extends Eventful { + constructor(map) { + super(); + this.map = map; + this.message = new graphic.Text({ + zlevel: 1, + z: 99, + silent: true, + style: { + x: 0, + y: 0, + fontSize: 16, + fontWeight: 'normal', + textBackgroundColor: '#feffc8', + text: 'aaa', + textFill: '#000', + textPadding: [7, 14], + textAlign: 'left', + textVerticalAlign: 'bottom', + textBorderColor: '#666666', + textBorderWidth: 0, + textBorderRadius: 4, + textLineHeight: 22, + textBoxShadowColor: 'rgba(0,0,0,.3)', + textBoxShadowOffsetX: 0, + textBoxShadowOffsetY: 1, + textBoxShadowBlur: 3, + opacity: 0.8 + } + }); + this.on('show', this.onShow, this); + this.on('hide', this.onHide, this); + } + + onShow(e) { + const {x, y, text} = e; + const painter = this.map.getPainter(); + const options = this.map.getOptions(); + const level = painter.getTipsLevel(); + const scaleRate = options.scaleRate || 1; + const offsetX = options.offsetX || 0; + const offsetY = options.offsetY || 0; + + const newX = parseInt((x + offsetX) / scaleRate); + const newY = parseInt((y + offsetY) / scaleRate); + + this.message.setStyle({x: newX, y: newY, text}); + + if (level) { + level.add(this.message); + painter.$transformHandle.transformView(this.message); + } + } + + onHide(e) { + const painter = this.map.getPainter(); + const level = painter.getTipsLevel(); + + if (level) { + level.remove(this.message); + } + this.message.setStyle('text', ''); + } + + dispose() { + this.off('show', this.onShow); + this.off('hide', this.onHide); + } +} diff --git a/src/iscs_new/transformHandle.js b/src/iscs_new/transformHandle.js new file mode 100644 index 000000000..2fd8596c1 --- /dev/null +++ b/src/iscs_new/transformHandle.js @@ -0,0 +1,80 @@ +import * as utils from './utils/utils'; + +class TransformHandle { + constructor(painter) { + this.$painter = painter; + + this.parentLevel = painter.getParentLevel(); + + this.rect = { x: 0, y: 0, width: 0, height: 0 }; + + this.transform = utils.createTransform({ scaleRate: 1, offsetX: 0, offsetY: 0 }); + } + + getTransform() { + return this.transform; + } + + checkVisible(view) { + return utils.createBoundingRect(view).intersect(this.rect); + } + + revisibleView(view) { + let visible = false; + if (this.checkVisible(view)) { + view.show(); + visible = true; + } else { + view.hide(); + visible = false; + } + + if (view._code) { + this.$painter.doHover(view, visible); + } + + view.dirty(); + } + + // 视图进行缩放/平移 + transformView(view) { + if (view) { + view.transform = this.transform; + view.decomposeTransform(); + this.revisibleView(view); + } + } + + // 处理所有视图缩放/平移 + transformAll() { + this.traverse(this.transformView, this); + } + + // 重新计算显示图形 + revisibleAll() { + this.traverse(this.revisibleView, this); + } + + // 更新偏移量 + updateTransform(opts) { + this.transform = utils.createTransform(opts); + this.transformAll(); + } + + // 更新画布尺寸 + updateZrSize(opts) { + this.rect = { x: 0, y: 0, width: opts.width, height: opts.height }; + this.revisibleAll(); + } + + // 遍历group执行回调 + traverse(cb, context) { + this.parentLevel.eachChild(level => { + level.eachChild((view) => { + cb.call(context, view); + }, context); + }, context); + } +} + +export default TransformHandle; diff --git a/src/iscs_new/utils/container/Caches.js b/src/iscs_new/utils/container/Caches.js new file mode 100644 index 000000000..cf3739487 --- /dev/null +++ b/src/iscs_new/utils/container/Caches.js @@ -0,0 +1,5 @@ +export default class Caches extends Map { + constructor(opts) { + super(); + } +} diff --git a/src/iscs_new/utils/container/Storage.js b/src/iscs_new/utils/container/Storage.js new file mode 100644 index 000000000..d8f395ac8 --- /dev/null +++ b/src/iscs_new/utils/container/Storage.js @@ -0,0 +1,64 @@ + +export default class Storage { + constructor() { + this.map = new Map(); + this.lst = new Set(); + this.clipboard = []; + } + + has(code) { + return code ? this.map.has(code) : false; + } + + set(code, target) { + if (!this.has(code)) { + this.lst.add(code); + this.map.set(code, target); + } + } + + get(code) { + return this.map.get(code); + } + + delete(code) { + // debugger; + if (this.has(code)) { + this.map.delete(code); + this.lst.delete(code); + } + } + + values() { + return Array.from(this.lst).map(code => { return this.get(code); }); + } + + clear() { + this.lst.clear(); + this.map.clear(); + } + + isSelectSelf(code) { + return this.has(code); + } + + setClipboard(lst) { + this.clipboard = Array.from(lst); + } + + clearClipboard() { + this.clipboard = []; + } + + getClipboard() { + return this.clipboard; + } + + getClipboardSize() { + return this.clipboard.length; + } + + forEach() { + return this.map.forEach; + } +} diff --git a/src/iscs_new/utils/dom.js b/src/iscs_new/utils/dom.js new file mode 100644 index 000000000..436b4bdd2 --- /dev/null +++ b/src/iscs_new/utils/dom.js @@ -0,0 +1,17 @@ +export function isDom(dom) { + return typeof dom === 'object' && + typeof dom.nodeType === 'number' && + typeof dom.ownerDocument === 'object'; +} + +export function setAttribute(dom, key, value) { + dom.setAttribute + ? dom.setAttribute(key, value) + : (dom[key] = value); +} + +export function getAttribute(dom, key) { + return dom.getAttribute + ? dom.getAttribute(key) + : dom[key]; +} diff --git a/src/iscs_new/utils/transform.js b/src/iscs_new/utils/transform.js new file mode 100644 index 000000000..2ca87e5f1 --- /dev/null +++ b/src/iscs_new/utils/transform.js @@ -0,0 +1,29 @@ +import * as matrix from 'zrender/src/core/matrix'; + +// 对图形进行scale/rotation/position变化 +export function transformed(shape, {scale, rotation, position}) { + let transform = matrix.create(); + + if (scale) { + transform = matrix.scale(matrix.create(), transform, scale); + } + + if (rotation) { + transform = matrix.rotate(matrix.create(), transform, rotation); + } + + if (position) { + transform = matrix.translate(matrix.create(), transform, position); + } + + if (shape) { + if (origin) { + shape.attr(origin, origin); + } + + shape.transform = transform; + shape.decomposeTransform(); + } + + return shape; +} diff --git a/src/iscs_new/utils/utils.js b/src/iscs_new/utils/utils.js new file mode 100644 index 000000000..3d483f08b --- /dev/null +++ b/src/iscs_new/utils/utils.js @@ -0,0 +1,342 @@ +import * as matrix from 'zrender/src/core/matrix'; +import * as color from 'zrender/src/tool/color'; +import BoundingRect from 'zrender/src/core/BoundingRect'; + +var base = 0; + +// 获取一个UID +export function getUID(type) { + return [(type || ''), base++, Math.random().toFixed(5)].join('_'); +} + +// 判断一个图形是否是svg +export function shapeIsSvg(shape) { + return shape.type == 'Svg'; +} + +// 判断一个url是否svg路径 +export function urlIsSvg(url) { + return !/.png$/i.test(url); +} + +export function isExistFile(url, draw) { + if (draw) { + try { + let xmlHttp; + if (window.ActiveXObject) { + xmlHttp = new window.ActiveXObject('Microsoft.XMLHTTP'); + } else if (window.XMLHttpRequest) { + xmlHttp = new window.XMLHttpRequest(); + } + + xmlHttp.open('get', url, false); + xmlHttp.send(); + + if (xmlHttp.readyState == 4) { + if (xmlHttp.status == 200) return true; + else if (xmlHttp.status == 404) return false; + else return false; + } + return false; + } catch (e) { + return false; + } + } + + return true; +} + +// 根据url重新获取url路径或者Svg内容 +export function getResourceUrl(relatedUrl) { + const url = `${process.env.VUE_APP_BASE_RESOURCE_URL}${relatedUrl}`; + const isSvg = /.svg$/i.test(url); + + if (isSvg) { + let xmlHttp; + if (window.ActiveXObject) { + xmlHttp = new window.ActiveXObject('Microsoft.XMLHTTP'); + } else if (window.XMLHttpRequest) { + xmlHttp = new window.XMLHttpRequest(); + } + + xmlHttp.open('get', url, false); + xmlHttp.send(); + + if (xmlHttp.readyState==4) { + if (xmlHttp.status==200) return xmlHttp.response.replace(/.*.*/, '$1'); + } + } + + return url; +} + +export function getObjFormListBySign(list, sign) { + if (list && list.length) { + return list[list.findIndex(el => { return el.sign == sign; })]; + } +} + +export function initModelState(model, state, blocks=['data', 'contorl']) { + blocks.forEach(block => { + state[block] = {...model[block]||{}}; + }); + return state; +} + +export function exBoundingRect(rt, padding) { + const rect = new BoundingRect(rt.x, rt.y, rt.width, rt.height); + rect.x -= padding; + rect.y -= padding; + rect.width += padding*2; + rect.height += padding*2; + return rect; +} + +// 判断Url路径是否存在 +export function isExistUrl(relatedUrl, draw) { + if (draw) { + try { + let xmlHttp; + const url = `${process.env.VUE_APP_BASE_RESOURCE_URL}${relatedUrl}`; + if (window.ActiveXObject) { + xmlHttp = new window.ActiveXObject('Microsoft.XMLHTTP'); + } else if (window.XMLHttpRequest) { + xmlHttp = new window.XMLHttpRequest(); + } + + xmlHttp.open('get', url, false); + xmlHttp.send(); + + if (xmlHttp.readyState==4) { + if (xmlHttp.status==200) return true; + else if (xmlHttp.status==404) return false; + else return false; + } + return false; + } catch (e) { + return false; + } + } + + return true; +} + +// clone一个对象 +export function deepClone(obj) { + var tag = Array.isArray(obj) ? [] : {}; + for (var key in obj) { + if (obj.hasOwnProperty(key)) { + if (Array.isArray(obj[key])) { + tag[key] = JSON.parse(JSON.stringify({data: obj[key]})).data; + } else if (typeof obj[key] === 'object' && obj[key] !== null) { + tag[key] = deepClone(obj[key]); + } else { + tag[key] = obj[key]; + } + } + } + + return tag; +} + +// 以clone的方式copy一个对象到另一个对象 +export function deepAssign(tag, obj) { + return Object.assign(tag, deepClone(obj)); +} + +// 拷贝对象指定层次的引用 +export function assignByDeep(source, target, deep) { + Object.keys(target).forEach(key => { + if (deep) { + Object.keys(target).forEach(key => { + source[key] = assignByDeep(source[key]||{}, target[key]||{}, deep-1); + }); + } else { + source[key] = target[key]; + } + }); + return source; +} + +// 代理一个线条重新计算偏移中心 +export function lineProxy(shape, origin, point) { + const dx = point.x - origin.x; + const dy = point.y - origin.y; + const dz = Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2)); + shape.attr('origin', [origin.x, origin.y]); + shape.attr('rotation', -Math.atan2(dy, dx),); + shape.setShape({ + points: [ + [origin.x, origin.y], + [origin.x+dz, origin.y] + ] + }); + return shape; +} + +// 创建一个transform +export function createTransform(opts) { + let transform = matrix.create(); + transform = matrix.scale(matrix.create(), transform, [opts.scaleRate, opts.scaleRate]); + transform = matrix.translate(matrix.create(), transform, [-opts.offsetX, -opts.offsetY]); + return transform; +} + +// 计算缩放和偏移后的包围框 +export function createBoundingRect(view) { + const rect = view.getBoundingRect().clone(); + const scale = view.scale[0]; + const offsetX = view.position[0]; + const offsetY = view.position[1]; + rect.x = rect.x * scale + offsetX; + rect.y = rect.y * scale + offsetY; + rect.width = rect.width * scale; + rect.height = rect.height * scale; + return rect; +} + +// 计算视图中心 +export function calculateDCenter(viewRect, bound) { + var dx = (bound.width - viewRect.width) / 2 - viewRect.x; + var dy = (bound.height - viewRect.height) / 2 - viewRect.y; + return { dx, dy }; +} + +export function setModelState(model, state) { + Object.keys(state).forEach(block => { + model[block] = {...model[block]||{}, ...state[block]}; + }); + return model; +} + +// 更新point指定x/y的偏移值 +export function updatePointDi(point, prop, di) { + let list = point; + if (!(point instanceof Array)) { + list = [point]; + } + + if (list && list.length) { + list.forEach(el => { + if (el.point) { + el.point[prop] += di; + } + if (el.points) { + el.points.forEach(point => { + point[prop] += di; + }); + } + }); + } +} + +// 通过sceneType获取资源画面 +export function getSceneBySceneType(resource, sceneType) { + return (resource.sceneMap||{})[sceneType]||{}; +} + +// 通过sceneType获取绘图数据块 +export function getBlockBySceneType(model, sceneType) { + const index = model.sceneTypes.findIndex(el => { return el == sceneType; }); + return index >= 0? model.graphList[index]||null: null; +} + +// 在list中通过指定sign获取节点obj +export function getObjInListBySign(list, sign) { + if (list && list.length) { + return list[list.findIndex(el => { return el.sign == sign; })]; + } +} + +// 通过Model获取link关系 +export function getLinkByModel(mapLink, model) { + const type = model._type == 'measure' ? 'measure' : 'device'; // 转换key + return mapLink ? (mapLink[type]||{})[model.code] : {}; +} + +// 通过Model获取实体 +export function getEntityByModel(mapEntity, mapLink, model) { + const link = getLinkByModel(mapLink, model)||{}; + return mapEntity[link.code]; +} + +export function getDomOffset(dom) { + let pol = 0; + let pot = 0; + let offsetLeft = 0; + let offsetTop = 0; + + while (dom) { + if (pol != dom.offsetLeft) { + offsetLeft += dom.offsetLeft; + pol = dom.offsetLeft; + } + if (pot != dom.offsetTop) { + offsetTop += dom.offsetTop; + pot = dom.offsetTop; + } + dom = dom.offsetParent; + } + + const offset = { + x: offsetLeft, + y: offsetTop + }; + return offset; +} + +// 矩形碰撞检测 +export function checkRectCollision(rect1, rect2) { + const center1 = { x: rect1.point.x + rect1.width / 2, y: rect1.point.y + rect1.height / 2 }; + const center2 = { x: rect2.point.x + rect2.width / 2, y: rect2.point.y + rect2.height / 2 }; + if ( + // 横向判断 和 纵向判断 + Math.abs(center1.x - center2.x) < rect1.width / 2 + rect2.width / 2 && + Math.abs(center1.y - center2.y) < rect1.height / 2 + rect2.height / 2 + ) { + return true; + } + return false; +} + +// 通过两点计算弧度 +export function getRadian(point1, point2) { + return Math.atan2(point2.y-point1.y, point2.x-point1.x); +} + +// 类型检测 +const cehckJsType = (type) => { return (obj) => { return Object.prototype.toString.call(obj) === `[object ${type.name}]`; }; }; + +export function isFunction() { return cehckJsType(Function); } + +export function isArray() { return cehckJsType(Array); } + +export function isString() { return cehckJsType(String); } + +export function isInstanceOf(obj, targt) { + return obj instanceof targt; +} + +export function isMobile() { + var sUserAgent= navigator.userAgent.toLowerCase(); + var bIsIpad= sUserAgent.match(/ipad/i) == 'ipad'; + var bIsIphoneOs= sUserAgent.match(/iphone os/i) == 'iphone os'; + var bIsMidp= sUserAgent.match(/midp/i) == 'midp'; + var bIsUc7= sUserAgent.match(/rv:1.2.3.4/i) == 'rv:1.2.3.4'; + var bIsUc= sUserAgent.match(/ucweb/i) == 'ucweb'; + var bIsAndroid= sUserAgent.match(/android/i) == 'android'; + var bIsCE= sUserAgent.match(/windows ce/i) == 'windows ce'; + var bIsWM= sUserAgent.match(/windows mobile/i) == 'windows mobile'; + // var bIsWebview = sUserAgent.match(/webview/i) == 'webview'; + return (bIsIpad || bIsIphoneOs || bIsMidp || bIsUc7 || bIsUc || bIsAndroid || bIsCE || bIsWM); +} + +export function handleColor(source, target, distance = 200) { + const rgbSource = []; + const rgbTarget = []; + color.parse(source, rgbSource); + color.parse(target, rgbTarget); + const diffArr = rgbTarget.map((el, i) => { return el- rgbSource[i]; }); + const sum = diffArr.slice(0, 3).reduce((s, el) => s + (el*el), 0); + return Math.sqrt(sum)