import Load from "./Load"; import { stateService } from "./Service/StateService"; import { elementService } from "./Service/ElementService"; import { dataService } from "./Service/DataService"; import { measureService } from "./Service/MeasureService"; import { tagService } from "./Service/TagService"; import { historyService } from "./Service/HistoryService"; import UIControl from "./Controls/UIControl"; // import { moveRectangle } from "./Controls/MoveRectangle"; import { moveTag } from "./Controls/MoveTag"; import { addRoad } from "./Controls/AddRoad"; import { moveRoad } from "./Controls/MoveRoad"; import { coordinate } from "./Coordinate"; import Render from "./Renderer/Render"; import { draw } from "./Renderer/Draw"; import { listenLayer } from "./ListenLayer"; import LayerEvents from "./enum/LayerEvents.js"; import UIEvents from "./enum/UIEvents.js"; import SelectState from "./enum/SelectState.js"; import VectorType from "./enum/VectorType"; import { mathUtil } from "./Util/MathUtil"; import History from "./History/History"; import mitt from "mitt"; import { roadService } from "./Service/RoadService"; import { edgeService } from "./Service/EdgeService"; import { pointService } from "./Service/PointService"; import { curveRoadService } from "./Service/CurveRoadService"; const minDragDis = 10; export default class Layer { constructor(canvas) { this.canvas = canvas; this.load = new Load(this); this.uiControl = new UIControl(this); this.renderer = new Render(this); this.history = new History(this); this.dragging = false; // 当前是否正在拖拽 this.start(); Object.setPrototypeOf(Object.getPrototypeOf(this), mitt()); } start() { if (this.canvas) { this.canvas.width = this.canvas.clientWidth; this.canvas.height = this.canvas.clientHeight; coordinate.init(this.canvas); draw.initContext(this.canvas); dataService.initVectorData(); this.history.init(); this.bindEvents(); } window.vectorData = dataService.vectorData; } bindEvents() { this.canvas.addEventListener("contextmenu", function (e) { e.preventDefault(); }); this.canvas.addEventListener("mousedown", this.onMouseDown.bind(this)); this.canvas.addEventListener("mousemove", this.onMouseMove.bind(this)); this.canvas.addEventListener("mouseup", this.onMouseUp.bind(this)); this.canvas.addEventListener("mousewheel", this.onWheel.bind(this)); this.canvas.addEventListener("DOMMouseScroll", this.onWheel.bind(this)); this.canvas.addEventListener("resize", this.reSize.bind(this)); document.addEventListener("keydown", this.onKeydown.bind(this)); } reSize = function () { console.log("resize"); coordinate.updateForCanvas(); this.renderer.autoRedraw(); }; onMouseDown(e) { this.startX = e.offsetX || e.layerX; this.startY = e.offsetY || e.layerY; this.lastX = e.offsetX || e.layerX; this.lastY = e.offsetY || e.layerY; // 右键 if (e.button == 2) { this.stopAddVector(); this.uiControl.currentUI = null; this.renderer.autoRedraw(); return; } this.dragging = false; this.setEventName("mouseDown"); const selectItem = stateService.getSelectItem(); const eventName = stateService.getEventName(); stateService.setDraggingItem(selectItem); // 清除上一个状态 // 设置当前事件名称 e.preventDefault(); e.stopPropagation(); } onMouseMove(e) { const X = e.offsetX || e.layerX; const Y = e.offsetY || e.layerY; let dx = X - this.lastX; let dy = Y - this.lastY; let position = coordinate.getXYFromScreen({ x: X, y: Y, }); if ( Math.abs(X - this.startX) > minDragDis || Math.abs(Y - this.startY) > minDragDis ) { // 是否拖拽了 this.dragging = true; } const eventName = stateService.getEventName(); // 是否需要重绘 let needAutoRedraw = false; let point = null; const draggingItem = stateService.getDraggingItem(); switch (eventName) { case null: //监控 needAutoRedraw = listenLayer.start(position); break; case LayerEvents.PanBackGround: stateService.clearItems(); coordinate.center.x = coordinate.center.x - (dx * coordinate.defaultZoom) / coordinate.zoom; coordinate.center.y = coordinate.center.y + (dy * coordinate.defaultZoom) / coordinate.zoom; this.lastX = X; this.lastY = Y; needAutoRedraw = true; break; case LayerEvents.AddRoad: needAutoRedraw = true; listenLayer.start(position); if (listenLayer.modifyPoint) { position = { x: listenLayer.modifyPoint.x, y: listenLayer.modifyPoint.y, }; } elementService.hideAll(); elementService.setPoint(position); elementService.showPoint(); if (listenLayer.modifyPoint) { elementService.execute(listenLayer.modifyPoint, position); } break; case LayerEvents.AddingRoad: needAutoRedraw = true; listenLayer.start(position); if (listenLayer.modifyPoint) { position = { x: listenLayer.modifyPoint.x, y: listenLayer.modifyPoint.y, }; } elementService.execute(addRoad.startInfo.position, position); elementService.setPoint(position); elementService.setNewRoad(addRoad.startInfo.position, position); elementService.showNewRoad(); elementService.setNewRoadGeoType(VectorType.Road); addRoad.setNewRoadPoint("end", position); addRoad.canAdd = addRoad.canAddRoadForEnd(position); if (!addRoad.canAdd) { elementService.setNewRoadState("error"); } else { elementService.setNewRoadState("normal"); } break; case LayerEvents.MoveRoad: needAutoRedraw = true; //只允许拖拽一条公路 let road = dataService.getRoad(draggingItem.vectorId); let start = dataService.getPoint(road.startId); let end = dataService.getPoint(road.endId); if ( Object.keys(start.getParent()).length == 1 && Object.keys(end.getParent()).length == 1 ) { //拖拽的路只有一条 moveRoad.moveRoad( draggingItem.vectorId, (dx * coordinate.defaultZoom) / coordinate.zoom, (dy * coordinate.defaultZoom) / coordinate.zoom ); } this.lastX = X; this.lastY = Y; break; case LayerEvents.MoveRoadPoint: point = dataService.getPoint(draggingItem.vectorId); //listenLayer.start(position, draggingItem.vectorId, point.parent); listenLayer.start(position, draggingItem.vectorId, point.parent); if (listenLayer.modifyPoint) { position = { x: listenLayer.modifyPoint.x, y: listenLayer.modifyPoint.y, }; } let flag = moveRoad.moveingRoadPoint( draggingItem.vectorId, position, listenLayer.modifyPoint ); if (!flag) { elementService.hideAll(); } else { point = dataService.getPoint(draggingItem.vectorId); listenLayer.start(point, draggingItem.vectorId, point.parent); let otherPoint = null; if ( listenLayer.modifyPoint && listenLayer.modifyPoint.linkedPointId ) { otherPoint = dataService.getPoint( listenLayer.modifyPoint.linkedPointId ); } else if ( listenLayer.modifyPoint && listenLayer.modifyPoint.linkedPointIdX ) { otherPoint = dataService.getPoint( listenLayer.modifyPoint.linkedPointIdX ); } else if ( listenLayer.modifyPoint && listenLayer.modifyPoint.linkedPointIdY ) { otherPoint = dataService.getPoint( listenLayer.modifyPoint.linkedPointIdY ); } elementService.execute(otherPoint, point); } needAutoRedraw = true; break; case LayerEvents.AddCurveRoad: needAutoRedraw = true; listenLayer.start(position); if (listenLayer.modifyPoint) { position = { x: listenLayer.modifyPoint.x, y: listenLayer.modifyPoint.y, }; } elementService.hideAll(); elementService.setPoint(position); elementService.showPoint(); if (listenLayer.modifyPoint) { elementService.execute(listenLayer.modifyPoint, position); } break; case LayerEvents.AddingCurveRoad: needAutoRedraw = true; listenLayer.start(position); if (listenLayer.modifyPoint) { position = { x: listenLayer.modifyPoint.x, y: listenLayer.modifyPoint.y, }; } elementService.execute(addRoad.startInfo.position, position); elementService.setPoint(position); elementService.setNewRoad(addRoad.startInfo.position, position); elementService.showNewRoad(); elementService.setNewRoadGeoType(VectorType.Road); addRoad.setNewRoadPoint("end", position); addRoad.canAdd = addRoad.canAddRoadForEnd(position); if (!addRoad.canAdd) { elementService.setNewRoadState("error"); } else { elementService.setNewRoadState("normal"); } break; case LayerEvents.AddMeasureLine: needAutoRedraw = true; listenLayer.start(position); if (listenLayer.modifyPoint) { position = { x: listenLayer.modifyPoint.x, y: listenLayer.modifyPoint.y, }; } elementService.setPoint(position); elementService.showPoint(); addRoad.setNewRoadPoint("start", position); break; case LayerEvents.MoveCurveRoadPoint: point = dataService.getCurvePoint(draggingItem.vectorId); listenLayer.start(position, draggingItem.vectorId, null, point.parent); if (listenLayer.modifyPoint) { position = { x: listenLayer.modifyPoint.x, y: listenLayer.modifyPoint.y, }; } if (draggingItem) { moveRoad.moveCurveRoadPoint(draggingItem.vectorId, position); needAutoRedraw = true; } break; case LayerEvents.AddTag: needAutoRedraw = true; if (draggingItem == null) { const tag = tagService.createTag(position); if (tag.vectorId) { stateService.setSelectItem( tag.vectorId, VectorType.Tag, SelectState.All ); stateService.setDraggingItem(stateService.selectItem); } } else { moveTag.moveFullTag(position, draggingItem.vectorId); } break; case LayerEvents.MoveTag: needAutoRedraw = true; if (draggingItem != null) { moveTag.moveFullTag(position, draggingItem.vectorId); } break; } if (needAutoRedraw) { this.renderer.autoRedraw(); } } onMouseUp(e) { // 右键 if (e.button == 2) { return; } const X = e.offsetX || e.layerX; const Y = e.offsetY || e.layerY; let eventName = stateService.getEventName(); const draggingItem = stateService.getDraggingItem(); const selectItem = stateService.getSelectItem(); let focusItem = null; if (!this.dragging && selectItem) { focusItem = { vectorId: selectItem.vectorId, type: selectItem.type, cursor: { x: this.lastX, y: this.lastY }, }; stateService.setFocusItem(focusItem); stateService.clearDraggingItem(); } let position = coordinate.getXYFromScreen({ x: X, y: Y, }); let needAutoRedraw = false; switch (eventName) { case null: return; case LayerEvents.PanBackGround: needAutoRedraw = true; stateService.clearFocusItem(); this.uiControl.currentUI = null; break; case LayerEvents.MoveRoadPoint: needAutoRedraw = true; elementService.hideAll(); let point = dataService.getPoint(draggingItem.vectorId); if (point) { listenLayer.start(point, draggingItem.vectorId, point.parent); if ( listenLayer.modifyPoint && listenLayer.modifyPoint.hasOwnProperty("linkedPointId") ) { moveRoad.moveTo( draggingItem.vectorId, listenLayer.modifyPoint.linkedPointId ); } else if ( listenLayer.modifyPoint && (listenLayer.modifyPoint.linkedPointIdX || listenLayer.modifyPoint.linkedPointIdY) ) { mathUtil.clonePoint(point, listenLayer.modifyPoint); } else if ( listenLayer.modifyPoint && listenLayer.modifyPoint.hasOwnProperty("linkedRoadId") ) { point = pointService.create({ x: listenLayer.modifyPoint.x, y: listenLayer.modifyPoint.y, }); roadService.splitRoad( listenLayer.modifyPoint.linkedRoadId, point.vectorId, "start" ); moveRoad.moveTo(draggingItem.vectorId, point.vectorId); } else if (moveRoad.splitRoadId != null) { roadService.splitRoad( moveRoad.splitRoadId, draggingItem.vectorId, "start" ); } //draggingItem.vectorId所在的墙面与其他墙角相交 moveRoad.updateForAbsorbRoadPoints(); let parent = point.getParent(); for (let key in parent) { roadService.setLanes(key); } this.history.save(); } break; case LayerEvents.AddRoad: addRoad.setNewRoadPoint("start", position); break; case LayerEvents.AddingRoad: needAutoRedraw = true; if (addRoad.canAdd) { addRoad.buildRoad(); addRoad.clear(); this.history.save(); elementService.hideAll(); } break; case LayerEvents.AddCurveRoad: addRoad.setNewRoadPoint("start", position); break; case LayerEvents.AddingCurveRoad: needAutoRedraw = true; if (addRoad.canAdd) { addRoad.buildCurveRoad(); addRoad.clear(); this.history.save(); elementService.hideAll(); } break; case LayerEvents.MoveRoad: needAutoRedraw = true; if (focusItem != null && focusItem.type == VectorType.Road) { const road = dataService.getRoad(focusItem.vectorId); this.uiControl.currentUI = focusItem.type; } this.history.save(); moveRoad.setStartMoving(false); break; case LayerEvents.MoveTag: needAutoRedraw = true; if (focusItem != null && focusItem.type == VectorType.Tag) { this.uiControl.currentUI = focusItem.type; } this.history.save(); break; case LayerEvents.AddTag: needAutoRedraw = true; let tag = dataService.getTag(draggingItem.vectorId); tag.setAdding(false); focusItem = { vectorId: draggingItem.vectorId, type: draggingItem.type, cursor: { x: this.lastX, y: this.lastY }, }; stateService.setFocusItem(focusItem); this.history.save(); this.uiControl.currentUI = focusItem.type; break; } this.setEventName("mouseUp"); stateService.clearDraggingItem(); this.renderer.autoRedraw(); } onWheel(e) { e.preventDefault(); const type = e.type; if (type == "DOMMouseScroll" || type == "mousewheel") { // 当在canvas用滚轮滚动时 const delta = e.wheelDelta ? (e.wheelDelta / 120) * 20 : (-(e.detail || 0) / 3) * 20; const zoom = coordinate.zoom + delta; if (zoom < 14) { return; } coordinate.updateZoom(zoom); this.renderer.autoRedraw(); } } //测试用 onKeydown(e) { let focusItem = stateService.getFocusItem(); if (focusItem) { console.log("键盘(foucus有效):" + e.code); if (e.code == "Delete") { //删除 const road = dataService.getRoad(focusItem.vectorId); roadService.subtraRoadFromIntersect(road.startId, focusItem.vectorId); roadService.subtraRoadFromIntersect(road.endId, focusItem.vectorId); //dataService.deleteControlPoint() dataService.deleteRoad(focusItem.vectorId); this.renderer.autoRedraw(); this.history.save(); } //加宽 else if (e.code == "KeyA") { const road = dataService.getRoad(focusItem.vectorId); road.width += 100; edgeService.updateEdgeForMovePoint(road.startId); edgeService.updateEdgeForMovePoint(road.endId); roadService.setLanes(road.vectorId); this.renderer.autoRedraw(); this.history.save(); } //变窄 else if (e.code == "KeyB") { const road = dataService.getRoad(focusItem.vectorId); road.width -= 50; edgeService.updateEdgeForMovePoint(road.startId); edgeService.updateEdgeForMovePoint(road.endId); roadService.setLanes(road.vectorId); this.renderer.autoRedraw(); this.history.save(); } //添加左车道 else if (e.code == "KeyQ") { let road = dataService.getRoad(focusItem.vectorId); if (road) { roadService.updateForAddSubtractLanesCount( focusItem.vectorId, road.leftDrivewayCount + 1, "left" ); } else { road = dataService.getCurveRoad(focusItem.vectorId); curveRoadService.updateForAddSubtractLanesCount( road, road.leftDrivewayCount + 1, //rightDrivewayCount "left" ); } this.renderer.autoRedraw(); this.history.save(); } //减少左车道 else if (e.code == "KeyW") { let road = dataService.getRoad(focusItem.vectorId); if (road) { roadService.updateForAddSubtractLanesCount( focusItem.vectorId, road.leftDrivewayCount - 1, "left" ); } else { road = dataService.getCurveRoad(focusItem.vectorId); curveRoadService.updateForAddSubtractLanesCount( road, road.leftDrivewayCount - 1, //rightDrivewayCount "left" ); } this.renderer.autoRedraw(); this.history.save(); } //添加右车道 else if (e.code == "KeyE") { let road = dataService.getRoad(focusItem.vectorId); if (road) { roadService.updateForAddSubtractLanesCount( focusItem.vectorId, road.rightDrivewayCount + 1, "right" ); } else { road = dataService.getCurveRoad(focusItem.vectorId); curveRoadService.updateForAddSubtractLanesCount( road, road.rightDrivewayCount + 1, //rightDrivewayCount "right" ); } this.renderer.autoRedraw(); this.history.save(); } //减少右车道 else if (e.code == "KeyR") { let road = dataService.getRoad(focusItem.vectorId); if (road) { roadService.updateForAddSubtractLanesCount( focusItem.vectorId, road.rightDrivewayCount - 1, "right" ); } else { road = dataService.getCurveRoad(focusItem.vectorId); curveRoadService.updateForAddSubtractLanesCount( road, road.rightDrivewayCount - 1, //rightDrivewayCount "right" ); } this.renderer.autoRedraw(); this.history.save(); } } else { console.log("键盘(foucus无效):" + e.code); } } setEventName(eventType) { let eventName = stateService.getEventName(); if (eventType == "mouseDown") { if (eventName == null) { const selectItem = stateService.getSelectItem(); if (selectItem == null) { stateService.setEventName(LayerEvents.PanBackGround); } else if (selectItem.type == VectorType.Road) { stateService.setEventName(LayerEvents.MoveRoad); } else if (selectItem.type == VectorType.Point) { stateService.setEventName(LayerEvents.MoveRoadPoint); } else if (selectItem.type == VectorType.CurveRoad) { stateService.setEventName(LayerEvents.MoveCurveRoad); } else if (selectItem.type == VectorType.CurvePoint) { stateService.setEventName(LayerEvents.MoveCurveRoadPoint); } else if (selectItem.type == VectorType.Tag) { stateService.setEventName(LayerEvents.MoveTag); } else if (selectItem.type == VectorType.MeasureLine) { stateService.setEventName(LayerEvents.MoveMeasureLine); } else if (selectItem.type == VectorType.MeasureArrow) { stateService.setEventName(LayerEvents.MoveMeasureArrow); } } } else if (eventType == "mouseUp") { if (eventName == LayerEvents.AddTag) { //可连续添加 //stateService.clearEventName() } else if (eventName == LayerEvents.AddRoad) { stateService.setEventName(LayerEvents.AddingRoad); } else if (eventName == LayerEvents.AddingRoad) { stateService.setEventName(LayerEvents.AddRoad); } else if (eventName == LayerEvents.AddCurveRoad) { stateService.setEventName(LayerEvents.AddingCurveRoad); } else if (eventName == LayerEvents.AddingCurveRoad) { stateService.setEventName(LayerEvents.AddCurveRoad); } else if (eventName == LayerEvents.AddMeasureLine) { stateService.setEventName(LayerEvents.AddingMeasureLine); } else if (eventName == LayerEvents.AddingMeasureLine) { stateService.setEventName(LayerEvents.AddMeasureLine); } else { stateService.clearEventName(); } } } exit() { stateService.clear(); this.uiControl.clearUI(); } stopAddVector() { let eventName = stateService.getEventName(); if (eventName != LayerEvents.AddingRoad) { stateService.clearEventName(); const draggingItem = stateService.getDraggingItem(); if (eventName == LayerEvents.AddTag) { if (draggingItem && draggingItem.vectorId) { dataService.deleteTag(draggingItem.vectorId); this.uiControl.currentUI = null; } } } else { stateService.setEventName(LayerEvents.AddRoad); } this.uiControl.clearUI(); elementService.hideAll(); } update() {} revokeHistory() { this.history.goPreState(); this.renderer.autoRedraw(); } recoveryHistory() { this.history.goNextState(); this.renderer.autoRedraw(); } deleteItem() { let item = stateService.getFocusItem(); if (item) { if (item.type == VectorType.Road) { dataService.deleteRoad(item.vectorId); } else if (item.type == VectorType.Tag) { dataService.deleteTag(item.vectorId); } else if (item.type == VectorType.Point) { //这个比较复杂,参考deleteRoadCorner //dataService.deletePoint(item.vectorId); } this.history.save(); this.renderer.autoRedraw(); } } }