Browse Source

新增地图管理界面,实现仙工地图加载功能

HRH-DEV
edgarhrh 4 months ago
parent
commit
ed6a42a428
  1. 2
      package.json
  2. 462
      src/views/system/mapManagement/index.vue
  3. 1
      src/views/system/mapManagement/map/lab0522xiezuo(1).json
  4. 2
      tsconfig.json
  5. 9439
      yarn.lock

2
package.json

@ -7,7 +7,6 @@
"scripts": {
"dev": "vite",
"build": "vite build",
"lint-fix": "eslint --fix --ext .js --ext .jsx --ext .vue src/",
"build-api": "cd api_build/ && build.bat"
},
"dependencies": {
@ -45,6 +44,7 @@
"vcrontab-3": "^3.3.22",
"vform3-builds": "^3.0.10",
"vue": "^3.4.21",
"konva": "^9.2.0",
"vue-clipboard3": "^2.0.0",
"vue-demi": "^0.14.7",
"vue-grid-layout": "3.0.0-beta1",

462
src/views/system/mapManagement/index.vue

@ -0,0 +1,462 @@
<template>
<div class="sys-role-container">
<el-card shadow="hover" :body-style="{ paddingBottom: '0' }">
<el-form :model="state.queryParams" ref="queryForm" :inline="true">
<el-form-item>
<el-button-group>
<el-button icon="ele-Refresh" @click="resetMap"> 重置地图 </el-button>
</el-button-group>
</el-form-item>
</el-form>
</el-card>
<el-card class="full-table" shadow="hover" style="margin-top: 5px" v-loading="state.loading" element-loading-text="Loading...">
<div id="container" class="container" />
</el-card>
</div>
</template>
<script lang="ts" setup name="sysRole">
import { onMounted, reactive, ref } from 'vue';
import Konva from 'konva';
import { ElMessageBox, ElMessage } from 'element-plus';
import mapData from './map/lab0522xiezuo(1).json';
const state = reactive({
loading: false,
queryParams: {
name: undefined,
code: undefined,
},
});
const mapCanvas = reactive<Record<string, any>>({
// JSON
mapData: {},
// agvImg: require('@/assets/agv.png'),
//
circle: null,
allGroup: [],
rect: null,
arrow: null,
text: null,
// canvas
stage: null,
//
widthScale: 0,
heightScale: 0,
// canvas
layer: null,
//线
bezier: [],
//线线线
dottedLinesArr: [],
//线
anchorArr: [],
//线
bezierLength: 0,
//线
anchorPoints: [],
//
showEditMap: false,
//
advancedPoint: {},
//
advancedCurve: {},
});
//
const draw = () => {
const { normalPosList, advancedPointList, advancedCurveList } = mapCanvas.mapData;
//
if (normalPosList?.length) {
for (let i = 0; i < normalPosList.length; i += 3) {
const x = normalPosList[i].x * mapCanvas.widthScale;
const y = normalPosList[i].y * mapCanvas.heightScale;
const circle = drawCircle(x, y, 2, '#c7d4ca');
mapCanvas.layer.add(circle);
}
}
//
for (let i = 0; i < advancedPointList.length; i++) {
const list = advancedPointList[i];
// mapCanvas.tableData[0].Interference.push({ name: list.instanceName, type: 'allGroup', i });
const x = list.pos.x * mapCanvas.widthScale;
const y = list.pos.y * mapCanvas.heightScale;
const number = list.instanceName.substring(2);
const name = list.instanceName.substring(0, 2);
if (list.dir) list.dir = parseFloat(list.dir).toFixed(3);
let rotation = (list.dir / Math.PI) * 180;
rotation = isNaN(rotation) ? 0 : rotation;
const color = list?.enable ? '#c5b8af' : '#1ABC9C';
const width = 50;
const height = 37;
mapCanvas.rect = new Konva.Rect({
opacity: 0.5,
x,
y,
width,
height,
color,
// perfectDrawEnabled: false,
offset: { x: width / 2, y: height / 2 },
rotation,
draggable: false,
// listening: false,
});
mapCanvas.rect.cache();
const group = new Konva.Group({ name: list.instanceName });
const rect = drawRect(x, y, rotation, color);
const circle = drawCircle(x, y, 3, 'red');
const arrow = drawArrow(x, y, width, rotation);
const text1 = drawText(x, y, width, height, name, 'top', rotation);
const text2 = drawText(x, y, width, height, number, 'bottom', rotation);
// group.on('click', (evt) => {
// evt.cancelBubble = true; // group
// setCurrentPoint(i);
// if (!mapCanvas.showInterference) setCurrentTarget(evt.currentTarget.attrs.name, 'fill', evt.currentTarget);
// else setInterference(mapCanvas.advancedPoint); //
// // if (mapCanvas.drawer && mapCanvas.drawerTabsName === 'second') showInterferenceForm(mapCanvas.advancedPoint); //
// });
group.on('mouseover', () => (document.body.style.cursor = 'pointer'));
group.on('mouseout', () => (document.body.style.cursor = 'default'));
group.add(rect, circle, arrow, text1, text2);
mapCanvas.allGroup.push(group);
mapCanvas.layer.add(group);
}
// 线 线
for (let i = 0; i < advancedCurveList.length; i += 2) {
const list = advancedCurveList[i];
const color = list?.enable ? '#c5b8af' : '#2C3E50';
// mapCanvas.tableData[1].Interference.push({ name: list.instanceName, type: 'bezier', i: i / 2 });
let arr = [];
arr[i] = {};
const startPos = { x: list.startPos.pos.x * mapCanvas.widthScale, y: list.startPos.pos.y * mapCanvas.heightScale };
const endPos = { x: list.endPos.pos.x * mapCanvas.widthScale, y: list.endPos.pos.y * mapCanvas.heightScale };
switch (list.className) {
case 'BezierPath':
let control1 = { x: list.controlPos1?.x * mapCanvas.widthScale, y: list.controlPos1.y * mapCanvas.heightScale };
let control2 = { x: list.controlPos2?.x * mapCanvas.widthScale, y: list.controlPos2.y * mapCanvas.heightScale };
arr[i].control1 = buildAnchor(control1.x, control1.y, 1, i);
arr[i].control2 = buildAnchor(control2.x, control2.y, 2, i);
mapCanvas.anchorPoints.push({ startPos, control1, control2, endPos, instanceName: list.instanceName });
/* 绘制贝塞尔控制点 */
const bezierLine = new Konva.Shape({
stroke: color,
strokeWidth: 2,
perfectDrawEnabled: false, //
name: list.instanceName,
draggable: false,
sceneFunc: (ctx, shape) => {
ctx.globalCompositeOperation = 'destination-over'; //
ctx.beginPath();
ctx.moveTo(startPos.x, startPos.y);
ctx.bezierCurveTo(arr[i].control1.x(), arr[i].control1.y(), arr[i].control2.x(), arr[i].control2.y(), endPos.x, endPos.y);
ctx.fillStrokeShape(shape);
},
}) as any;
bezierLine.startPos = startPos;
bezierLine.endPos = endPos;
/* 绘制贝塞尔辅助线 */
// const updateDottedLines = new Konva.Shape({
// perfectDrawEnabled: false,
// visible: false,
// // stroke: 'lightgray',
// listening: false,
// draggable: false,
// // dash: [10, 10],
// sceneFunc: (ctx, shape) => {
// ctx.beginPath();
// ctx.moveTo(startPos.x, startPos.y);
// ctx.lineTo(arr[i].control1.x(), arr[i].control1.y());
// ctx.moveTo(endPos.x, endPos.y);
// ctx.lineTo(arr[i].control2.x(), arr[i].control2.y());
// ctx.moveTo(arr[i].control1.x(), arr[i].control1.y());
// ctx.lineTo(arr[i].control2.x(), arr[i].control2.y());
// ctx.restore();
// ctx.fillStrokeShape(shape);
// },
// });
// mapCanvas.dottedLinesArr.push(updateDottedLines);
// mapCanvas.bezier.push(bezierLine);
// bezierLine.on('mouseover', () => {
// document.body.style.cursor = 'pointer';
// bezierLine.strokeWidth(3);
// });
// bezierLine.on('mouseout', () => {
// document.body.style.cursor = 'default';
// bezierLine.strokeWidth(2);
// });
// 线
// bezierLine.on('click', (evt) => {
// setCurrentCurve(i);
// if (!mapCanvas.showInterference) {
// setCurrentTarget(list.instanceName, 'stroke', evt.currentTarget);
// } else {
// setInterference(mapCanvas.advancedCurve); //
// }
// //线
// // ,
// control1 = { x: arr[i].control1.x(), y: arr[i].control1.y() };
// control2 = { x: arr[i].control2.x(), y: arr[i].control2.y() };
// // advancedCurve
// mapCanvas.advancedCurve.controlPos1 = unitFormat(control1);
// mapCanvas.advancedCurve.controlPos2 = unitFormat(control2);
// getBezierLength(startPos, control1, control2, endPos);
// //if (mapCanvas.drawer && mapCanvas.drawerTabsName === 'second') showInterferenceForm(mapCanvas.advancedCurve);
// });
mapCanvas.layer.add(bezierLine);
//mapCanvas.layer.add(bezierLine, updateDottedLines);//线线
break;
case 'StraightPath':
// 线
const line = new Konva.Line({
points: [startPos.x, startPos.y, endPos.x, endPos.y],
stroke: color,
strokeWidth: 2,
perfectDrawEnabled: false,
name: list.instanceName,
draggable: false,
listening: false,
});
mapCanvas.layer.add(line);
break;
}
}
};
const drawCircle = (x, y, radius, fill) => {
if (!mapCanvas.circle) {
mapCanvas.circle = new Konva.Circle({
x,
y,
radius,
// visible: true,
fill,
draggable: false,
listening: false,
});
mapCanvas.circle.cache();
} else mapCanvas.circle = mapCanvas.circle.clone({ x, y, fill });
//
// mapCanvas.circle.on('mouseover', (evt) => {
// evt.currentTarget.destroy();
// // mapCanvas.circle.radius(4);
// });
return mapCanvas.circle;
};
const drawRect = (x, y, rotation, fill) => {
mapCanvas.rect = mapCanvas.rect.clone({ x, y, rotation, fill, opacity: 0.5 });
return mapCanvas.rect;
};
const drawArrow = (x, y, width, rotation) => {
if (!mapCanvas.arrow) {
mapCanvas.arrow = new Konva.Arrow({
x,
y,
points: [0, 0, width, 0],
stroke: '#FFFFF0',
strokeWidth: 2,
perfectDrawEnabled: false,
pointerLength: 10,
pointerWidth: 15,
offset: {
x: width / 2,
y: 0,
},
rotation,
listening: false,
draggable: false,
});
mapCanvas.arrow.cache();
} else mapCanvas.arrow = mapCanvas.arrow.clone({ x, y, rotation });
return mapCanvas.arrow;
};
const drawText = (x, y, width, height, text, verticalAlign, rotation) => {
const offset = { x: width / 2, y: verticalAlign === 'bottom' ? height / 2 : height / 2 };
if (!mapCanvas.text) {
mapCanvas.text = new Konva.Text({
x,
y,
text,
fontSize: 12,
fill: '#fff',
align: 'center',
verticalAlign,
width,
height,
offset,
scaleY: -1,
rotation,
perfectDrawEnabled: false,
listening: false,
draggable: false,
});
mapCanvas.text.cache();
} else mapCanvas.text = mapCanvas.text.clone({ x, y, text, verticalAlign, rotation, offset });
return mapCanvas.text;
};
// 线
const buildAnchor = (x, y, type, index) => {
let anchor = null as any;
anchor = new Konva.Circle({
x,
y,
radius: 2.5,
fill: 'red',
draggable: true,
visible: false,
perfectDrawEnabled: false,
listening: false,
});
anchor.transformsEnabled('position'); //
mapCanvas.layer.add(anchor);
// anchor.cache();
// anchor = mapCanvas.anchorArr[0].clone({ x, y });
// mapCanvas.layer.add(anchor);
//
anchor.on('mouseover', () => {
document.body.style.cursor = 'pointer';
anchor.radius(4);
});
//
anchor.on('mouseout', () => {
document.body.style.cursor = 'default';
anchor.radius(2.5);
});
// anchor.on('dragmove', (e) => {
// if (!mapCanvas.drawer) return;
// const anchorPoint = mapCanvas.anchorPoints[index / 2];
// mapCanvas.mapType = 1;
// // 线
// if (anchorPoint.instanceName !== mapCanvas.advancedCurve.instanceName) {
// mapCanvas.advancedCurve = advancedCurveList[index];
// }
// if (mapCanvas.drawerTabsName === 'one') {
// const position = anchor.position();
// anchorPoint['control' + type] = position;
// getBezierLength(anchorPoint.startPos, anchorPoint.control1, anchorPoint.control2, anchorPoint.endPos);
// //
// mapCanvas.advancedCurve['controlPos' + type] = unitFormat(position);
// }
// });
mapCanvas.anchorArr.push(anchor); //,
return anchor;
};
const initMap = () => {
state.loading = true;
// this.mapData = await this.getMapInfos();
mapCanvas.mapData = mapData;
const { header } = mapCanvas.mapData;
//
const map = document.querySelector('#container') as any;
let xMin = parseFloat(Math.abs(header.minPos.x).toFixed(3));
let yMin = parseFloat(Math.abs(header.minPos.y).toFixed(3));
let xMax = parseFloat(Math.abs(header.maxPos.x).toFixed(3));
let yMax = parseFloat(Math.abs(header.maxPos.y).toFixed(3));
const Xlength = xMin + xMax;
const Ylength = yMin + yMax;
mapCanvas.widthScale = Number(map.offsetWidth / Xlength);
mapCanvas.heightScale = Number(map.offsetHeight / Ylength);
mapCanvas.stage = new Konva.Stage({
container: '#container',
width: map.offsetWidth,
height: map.offsetHeight - 70,
x: xMin * mapCanvas.widthScale,
y: yMax * mapCanvas.heightScale,
scaleY: -1,
draggable: true,
});
mapCanvas.layer = new Konva.Layer();
mapCanvas.stage.add(mapCanvas.layer);
const max = 4; //
const min = 0.1; //
const step = 0.02; //
//
mapCanvas.stage.on('wheel', (e) => {
const x = e.evt.offsetX;
const y = e.evt.offsetY;
const offsetX = ((x - mapCanvas.layer.offsetX()) * mapCanvas.layer.scaleX()) / (mapCanvas.layer.scaleX() - step) - (x - mapCanvas.layer.offsetX());
const offsetY = ((y - mapCanvas.layer.offsetY()) * mapCanvas.layer.scaleY()) / (mapCanvas.layer.scaleY() - step) - (y - mapCanvas.layer.offsetY());
if (e.evt.wheelDelta > 0) {
//
if (mapCanvas.layer.scaleX() < max && mapCanvas.layer.scaleY() < max) {
mapCanvas.layer.scaleX(mapCanvas.layer.scaleX() + step);
mapCanvas.layer.scaleY(mapCanvas.layer.scaleY() + step);
mapCanvas.layer.move({ x: -offsetX, y: -offsetY }); //
}
} else {
//
if (mapCanvas.layer.scaleX() > min && mapCanvas.layer.scaleY() > min) {
mapCanvas.layer.scaleX(mapCanvas.layer.scaleX() - step);
mapCanvas.layer.scaleY(mapCanvas.layer.scaleY() - step);
mapCanvas.layer.move({ x: offsetX, y: offsetY }); //
}
}
});
// mapCanvas.stage.on('click', (evt) => {
// // stage
// if (!evt.target.parent) {
// if (mapCanvas.currentTarget) {
// mapCanvas.currentTarget[mapCanvas.currentTarget.type](mapCanvas.currentTarget.prevfill);
// mapCanvas.currentTarget = null;
// mapCanvas.advancedPoint = { pos: { x: 0, y: 0 } };
// mapCanvas.advancedCurve = {};
// }
// }
// });
setTimeout(() => {
draw();
state.loading = false;
}, 1200);
};
onMounted(() => initMap());
const resetMap = () => {
mapCanvas.advancedCurve = {};
mapCanvas.advancedPoint = {};
mapCanvas.bezierLength = 0;
mapCanvas.allGroup = [];
mapCanvas.dottedLinesArr = [];
mapCanvas.anchorPoints = [];
mapCanvas.anchorArr = [];
mapCanvas.bezier = [];
mapCanvas.layer.clear();
mapCanvas.layer.destroy();
state.loading = true;
mapCanvas.layer = new Konva.Layer();
mapCanvas.stage.add(mapCanvas.layer);
setTimeout(() => {
draw();
state.loading = false;
}, 1200);
};
</script>
<style scoped lang="scss">
.full-table {
.container {
width: 100%;
height: 100%;
background-color: #faf9f6;
overflow: hidden;
z-index: 99;
border: 2px solid #ded9e1;
border-radius: 15px;
}
}
</style>

1
src/views/system/mapManagement/map/lab0522xiezuo(1).json

File diff suppressed because one or more lines are too long

2
tsconfig.json

@ -25,7 +25,7 @@
"isolatedModules": true /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */,
/* Strict Type-Checking Options */
"strict": true /* Enable all strict type-checking options. */,
"strict": false /* Enable all strict type-checking options. */,
// "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
// "strictNullChecks": true, /* Enable strict null checks. */
// "strictFunctionTypes": true, /* Enable strict checking of function types. */

9439
yarn.lock

File diff suppressed because it is too large
Loading…
Cancel
Save