You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kev/Drawer/HtmlRoot/加了进度条-WebDrawer.html

1312 lines
44 KiB
HTML

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<!DOCTYPE html>
<html>
<head>
<meta charset="utf8">
<title>Kep Web图形组件</title>
<link rel="shortcut icon" href="#" />
<link rel="stylesheet" href="zTree/css/zTreeStyle/zTreeStyle.css" type="text/css" />
<link rel="stylesheet" href="css/menu.css" type="text/css" />
<style type="text/css">
<!--
html,
body {
color: #000000;
/* background-color: #0072C6; */
width: 100%;
height: 100%;
margin: 0;
}
#app {
width: 100%;
height: 100%;
}
img {
border: none;
}
.button {
padding: 3px 5px 3px 5px;
margin: 2px;
font-size: 15px;
cursor: pointer;
background-color: #4CAF50;
color: white;
border: none;
border-radius: 3px;
margin-top: 5px;
/* transition: all 0.3s ease; */
/* 添加过渡效果 */
}
.button:hover {
box-shadow: 0 3px 4px 0 rgba(0, 0, 0, 0.24), 0 4px 10px 0 rgba(0, 0, 0, 0.19);
background-color: #3e8e41;
}
.button--pressed {
background-color: #3e8e41;
/* 更深的绿色 */
}
.button-group {
display: flex;
justify-content: center;
/* 水平居中对齐 */
gap: 10px;
}
.overlay-image {
z-index: 9999;
/* 设置较高的z-index值 */
}
ul.ztree {
margin-top: 0px;
border: 0px solid #abcecb;
background: #f0f6e4;
overflow-y: auto;
overflow-x: hidden;
}
.ztree li span.button.switch.level0 {
visibility: hidden;
width: 0px;
}
.ztree li ul.level0 {
padding: 0;
background: none;
}
.layerButton {
margin-top: 1px;
margin-right: 0px;
margin-bottom: 1px;
margin-left: 0px;
background-size: auto;
background-repeat: no-repeat;
background-position: center;
width: 24px;
height: 24px;
border: none;
padding: 0px;
display: inline-flex;
color: black;
background-color: transparent;
border: 0px solid black;
border-radius: 3px;
transition: all 0.3s ease;
cursor: pointer;
flex: 0 0 auto;
}
.layerButton:hover {
color: blue;
border-color: black;
background-color: #c8d7c8;
}
.layerButton:after {
background: #90EE90;
opacity: 0;
transition: all 0.8s
}
.layerButton:active:after {
opacity: 1;
transition: 0s
}
.barSeparator {
width: 1px;
flex: 0 0 auto;
box-sizing: border-box;
border: solid #dee2e6;
border-width: 0 1px 0 0;
margin: 5px 2px;
min-height: 16px;
min-width: 1px;
height: 16px;
}
.loader-content {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
gap: 10px;
}
.loader-text {
color: #4CAF50;
font-weight: bold;
font-size: 14px;
animation: pulse 1.5s infinite;
}
.loader-dots {
display: flex;
gap: 4px;
}
.dot {
width: 6px;
height: 6px;
background: #76c779;
border-radius: 50%;
animation: bounce 1.4s infinite;
}
.dot:nth-child(2) { animation-delay: 0.2s; }
.dot:nth-child(3) { animation-delay: 0.4s; }
@keyframes bounce {
0%, 80%, 100% {
transform: translateY(0);
}
40% {
transform: translateY(-6px);
}
}
.loader-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
z-index: 9999;
display: flex;
align-items: center;
justify-content: center;
}
.loader-modal {
background: white; /* 设置背景颜色为白色 */
padding: 30px 400px; /* 设置内边距上下30像素左右400像素 */
border-radius: 10px; /* 设置圆角为10像素使边角显得圆滑 */
box-shadow: 0 0 20px rgba(0, 0, 0, 0.2); /* 添加阴影效果水平偏移0垂直偏移0模糊20像素黑色透明度0.2 */
text-align: center; /* 文本居中对齐 */
}
.loader-spinner {
width: 30px; /* 控制旋转图标的宽度为30像素 */
height: 40px; /* 控制旋转图标的高度为40像素注意宽高不同会形成椭圆形 */
border: 4px solid #f3f3f3; /* 设置4像素宽的浅灰色边框作为spinner的基础圆环 */
border-top: 4px solid #4CAF50; /* 将顶部边框设为绿色,形成旋转时的视觉效果 */
border-radius: 50%; /* 将元素变成圆形(或椭圆形,因为宽高不同) */
margin: 0 auto 15px; /* 上边距0左右自动居中下边距15像素 */
animation: spin 1s linear infinite; /* 应用名为spin的动画持续1秒线性变化无限循环 */
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
-->
</style>
<script src="dist/vue.global.js"></script>
<script src="zTree/js/jquery.min.js"></script>
<script src="zTree/js/jquery.ztree.core-3.5.js"></script>
<script src="zTree/js/jquery.ztree.excheck-3.5.js"></script>
<script src="zTree/js/jquery.ztree.exedit-3.5.js"></script>
</head>
<body>
<div id="app" style="position:relative; overflow:hidden;width: 100%; height: 100%;">
<!-- 新增进度条 -->
<div v-if="isLoading" class="loader-overlay">
<div class="loader-modal">
<div class="loader-content">
<div class="loader-spinner"></div>
<span class="loader-text">加载中</span>
<div class="loader-dots">
<div class="dot"></div>
<div class="dot"></div>
<div class="dot"></div>
</div>
</div>
</div>
</div>
<!-- 进度条 结束-->
<!-- 工具栏 -->
<div v-if="toolbarStyle===0" class="Meta2dMenu flex menu"><a target="_self" class="logo"
href="javascript:;"><img src="img/KEP001.svg" alt="KEP" /> KE Platform</a>
<div class="menus flex">
<div class="flex">
<div class="mr30" v-for="(item, index) in toolMainItems" :key="index">
<div class="ant-dropdown-trigger MenuItem" :style="{cursor: 'pointer', color: item.color }"
@click="toolMainClick(index)" @mouseover="setToolHoverColor(index)"
@mouseout="resetToolColor(index)">
<div class="iconItem">
<div class="icon"><img :src="item.imgSrc" :alt="item.title" class="t-icon"></img></div>
<span>{{item.title}}</span>
</div>
</div>
</div>
</div>
</div>
</div>
<div v-if="toolbarStyle===1" id="header"
style="position:relative; left: 0px; top:0px;height: 32px; background-color:#90908a;">
<button class="button" :class="{ 'button--pressed': isBtnPressed }" @click="toolDefault">浏览</button><button
class="button" @click="drawZoomIn">放大{{count}}</button><button class="button"
@click="drawZoomOut">缩小</button><button class="button" @click="toolViewWindow">局部</button><button
class="button" @click="viewAll">全部</button><button class="button" @click="toolViewMove"
:class="{ 'button--pressed': isBtnPressed }">移动</button><button class="button" @click="toolSelect"
:class="{ 'button--pressed': isBtnPressed }">选择</button><button class="button"
@click="drawSave">保存</button><button class="button" @click="switchLayerPanel">图层</button>
</div>
<div
style="overflow:visible;position: relative; height: 100%; width: 100%; margin: 0; display: flex; flex-direction: row;">
<div v-if="layerVisible" id="drawerTree"
:style="{width: layerSize.width+'px', height: layerSize.height+'px'}"
style="float:left; border: #b2b3b2; border-style:solid; border-width:2px; box-sizing: border-box;">
<!-- 图层树工具条 -->
<div
style="border: 1px solid #f8f9fa; border-top: 0; border-left: 0; border-right:0; box-sizing: border-box;vertical-align:middle; display: flex; flex-direction: row;">
<button class="layerButton" style="background-image: url('img/ViewEdit.png');" title="可编辑"
@click="setLayerStatus(1)"></button><button class="layerButton"
style="background-image: url('img/ViewNotEdit.png');" title="只读"
@click="setLayerStatus(2)"></button><button class="layerButton"
style="background-image: url('img/NotViewNotEdit.png');" title="隐藏"
@click="setLayerStatus(3)"></button>
<div class="barSeparator"></div><button class="layerButton"
style="background-image: url('img/Action_Delete.svg');" title="删除"
@click="deleteLayer"></button>
</div>
<!-- 图层树 -->
<ul id="treeDemo" class="ztree"
:style="{width: layerSize.width-6+'px', height: layerSize.height-32+'px' }" style="padding: 0;"></ul>
</div>
<!-- 绘图区域 -->
<div id="content" @wheel.prevent=""
style="overflow: hidden; position:relative; left: 0px; top:0px;height:100%;width:100%; float:left; padding: 0px; margin: 0px;">
<!-- 水平刻度尺 -->
<canvas id="ruler-horizontal" :width="viewSize.width*2+'px'" :height="rulerHeight*2+'px'"
:style="{width:viewSize.width+'px', height:rulerHeight+'px', left:rulerHeight+'px'}"
style="position:absolute; top:0px; background-color: rgb(245, 245, 245);">
</canvas>
<!-- 水平刻度指示 -->
<div ref="rulerHorizontalIndicator" width="1px"
:style="{height:rulerHeight+'px', left:mouseHorizontal+'px'}"
style="position:absolute; top:0px; width: 1px; background-color: #3e8e41; z-index: 99;box-sizing: border-box;">
</div>
<!-- 垂直刻度尺 -->
<canvas id="ruler-vertical" :width="rulerHeight*2+'px'" :height="viewSize.height*2+'px'"
:style="{height:viewSize.height+'px', width:rulerHeight+'px', top:rulerHeight+'px'}"
style="position:absolute; left: 0px; background-color: rgb(245, 245, 245);">
</canvas>
<!-- 垂直刻度指示 -->
<div width="1px" :style="{width:rulerHeight+'px', top:mouseVertical+'px'}"
style="position:absolute; left:0px; height: 1px; background-color: #3e8e41; z-index: 99;box-sizing: border-box;">
</div>
<div @wheel.prevent=""
style="overflow: hidden; position:relative; padding: 0px; margin: 0px; background-color: #4CAF50;"
:style="{ cursor: GetCursor(), left:rulerHeight+'px', top:rulerHeight+'px', width:viewSize.width+'px', height:viewSize.height+'px' }">
<!--橡皮筋选取框div-->
<div v-if="rubberVisible" ref="rubberbandDiv"
:style="{ position:'absolute', left: rubberbandRectangle.left + 'px', top: rubberbandRectangle.top + 'px', width: rubberbandRectangle.width + 'px', height: rubberbandRectangle.height + 'px' }"
style="pointer-events: none; border: 2px dashed rgb(81, 153, 212); cursor: crosshair;opacity: 0.5; display: inline; z-index: 999">
</div>
<canvas ref="canvas" @mousedown="canvasMouseDown" @mouseup="canvasMouseUp"
@mousemove="canvasMouseMove" @wheel="canvasMouseWheel" :width="viewSize.width +'px'"
:height="viewSize.height +'px'"
:style="{ cursor: GetCursor(), width:viewSize.width+'px', height:viewSize.height+'px' }"
style="position:absolute; margin: 0px;left: 0px; top:0px; padding: 0px; background-color: rgb(255, 255, 255);"></canvas>
<img v-if="imgVisible" ref="image"
:style="{ position:'absolute', left: imgPosition.x + 'px', top: imgPosition.y + 'px' }"
style="pointer-events: none;" />
</div>
</div>
</div>
</div>
<script>
const layerStatusIcons = {
1: "img/ViewEdit.png",
2: "img/ViewNotEdit.png",
3: "img/NotViewNotEdit.png"
}
/** 光标svg资源 */
const MouseIcons = {
auto: 'auto',
default: 'default',
crosshair: 'crosshair',
resizee: 'e-resize',
resizen: 'n-resize',
resizene: 'ne-resize',
resizenw: 'nw-resize',
resizes: 's-resize',
resizese: 'resizese',
resizesw: 'sw-resize',
resizew: 'w-resize',
text: 'text',
url: 'url',
wait: 'wait',
pointer: 'pointer',
help: 'help',
move: 'move',
pointerSelect: `url('data:image/svg+xml;utf8,<svg width="24px" height="24px" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024"><path d="m300.62812,496.77405l149.37188,347.20313l-112.5,56.25l-130.66875,-356.56875l-206.83125,187.81875l0,-731.25l562.5,450l-261.87188,46.54687z" /></svg>') 0 0, auto`,
viewPan: `url('data:image/svg+xml;utf8,<svg width="24px" height="24px" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024"><path fill="currentColor" d="M802.5 262.3c-11.9 0-23.4 2.1-34 5.9v-57.6c0-56-45.5-101.5-101.5-101.5-16.1 0-31.4 3.8-44.9 10.5-16.8-33-51.1-55.7-90.6-55.7-43.5 0-80.7 27.5-95 66.1-12.4-5.4-26-8.4-40.4-8.4-55.9 0-101.4 45.5-101.4 101.4v199.2c-10-10.9-22.5-19.6-36.6-25.4-25.4-10.3-53.2-10-78.3 0.9-50.6 21.9-74.6 81.1-53.4 132.1L178 653.3c5.9 14.2 12.6 28.3 19.9 41.9l94.3 175.2c29.8 55.4 87.4 89.8 150.3 89.8h231.9c68.4 0 130-40.7 156.9-103.6l42.6-99.6c19.9-46.6 30-96 30-146.7V363.7c0-55.9-45.5-101.4-101.4-101.4z m33.9 348c0 41.5-8.3 82-24.6 120.2l-42.6 99.6c-16.2 38-53.5 62.6-94.8 62.6H442.5c-38 0-72.8-20.8-90.8-54.3l-94.3-175.2c-6.3-11.6-12-23.7-17.1-35.9l-51.6-123.5c-7.1-17 0.9-36.8 17.8-44.1 8.4-3.6 17.7-3.7 26.1-0.3 8.5 3.4 15.1 10 18.5 18.4l46 111.5c6.1 14.9 22 23.4 37.8 20.2 15.8-3.1 27.2-17 27.2-33.1V223c0-18.7 15.2-33.8 34-33.8 18.7 0 33.8 15.2 33.8 33.8v286.7c0 1.2 0.1 2.3 0.2 3.5 1.7 17 16.1 30.3 33.6 30.3s31.9-13.3 33.6-30.3c0.1-1.1 0.2-2.3 0.2-3.5V165.3c0-18.7 15.2-33.9 33.9-33.9s34 15.2 34 34V509.6c0 18.7 15.1 33.8 33.8 33.8 18.7 0 33.8-15.1 33.8-33.8V210.5c0-18.7 15.2-33.9 33.9-33.9s33.9 15.2 33.9 33.9v342.9c0 18.7 15.1 33.8 33.8 33.8 18.7 0 33.8-15.1 33.8-33.8V363.8c0-18.7 15.2-34 34-34 18.7 0 33.9 15.2 33.9 33.8v246.7z"></path></svg>') 0 0, auto`,
test: `url('data:image/svg+xml;utf8,<svg width="24px" height="24px" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024"><path fill="currentColor" d="m186.496 544 41.408 41.344a32 32 0 1 1-45.248 45.312l-96-96a32 32 0 0 1 0-45.312l96-96a32 32 0 1 1 45.248 45.312L186.496 480h290.816V186.432l-41.472 41.472a32 32 0 1 1-45.248-45.184l96-96.128a32 32 0 0 1 45.312 0l96 96.064a32 32 0 0 1-45.248 45.184l-41.344-41.28V480H832l-41.344-41.344a32 32 0 0 1 45.248-45.312l96 96a32 32 0 0 1 0 45.312l-96 96a32 32 0 0 1-45.248-45.312L832 544H541.312v293.44l41.344-41.28a32 32 0 1 1 45.248 45.248l-96 96a32 32 0 0 1-45.312 0l-96-96a32 32 0 1 1 45.312-45.248l41.408 41.408V544H186.496z"></path></svg>') 0 0, auto`,
}
const canvasToolType = {
ITEM_DEFAULT: -1,
ITEM_VIEW_PAN: 1000,
ITEM_VIEW_WINDOW: 1001,
ITEM_STATE: 1003,
ITEM_ERASER: 1004,
ITEM_HYPERLINK: 1005,
ITEM_SELECT: 1006,
}
const VueApp = {
data() {
return {
// 加载状态,滚动条显示状态
isLoading: false, // 新增加载状态
firstConnect:true,
drawerToken: '',
isBtnPressed: false,
websocket: null, // WebSocket对象
reconnectInterval: 3000, // 重连间隔时间(毫秒)
heartbeatInterval: null, // 心跳定时器
count: 0,
canvas: null,
layerVisible: false,
isDragging: false,
isDragFirst: true,
queryDrawRuler: false,
imageSrc: '',
imgVisible: false,
imgPosition: { x: 0, y: 0 },
mouseStartX: 0,
mouseStartY: 0,
lastX: 0,
lastY: 0,
mouseHorizontal: 0,
mouseVertical: 0,
viewSize: { width: 0, height: 0 },
rulerHeight: 0,
rulerWidth: 0,
mouseX: 0,
mouseY: 0,
mouseDownX: 0,
mouseDownY: 0,
mouseDown: false,
pressedKeyCode: null,
drawerToolType: canvasToolType.ITEM_DEFAULT, // 当前操作模式
handleIndex: -1,
/** 画布对象 */
canvas: null,
ctx: null,
/** 橡皮筋选框 */
rubberbandDiv: null,
rubberbandRectangle: { left: 10, top: 10, width: 100, height: 100 },
rubberDragging: false,
rubberVisible: false,
toolbarStyle: 0,
toolMainItems: [
{
colorOld: '#000000d9',
color: 'rgb(24, 144, 255)',
imgSrc: 'img/mornejiantou.svg',
title: '默认',
checked: false,
}, {
colorOld: '#000000d9',
color: '#000000d9',
imgSrc: 'img/fangda.svg',
title: '放大',
checked: false,
}, {
colorOld: '#000000d9',
color: '#000000d9',
imgSrc: 'img/suoxiao.svg',
title: '缩小',
checked: false,
}, {
colorOld: '#000000d9',
color: '#000000d9',
imgSrc: 'img/fangdaWindow.svg',
title: '局部',
checked: false,
}, {
colorOld: '#000000d9',
color: '#000000d9',
imgSrc: 'img/quantu.svg',
title: '全部',
checked: false,
}, {
colorOld: '#000000d9',
color: '#000000d9',
imgSrc: 'img/yidong.svg',
title: '移动',
checked: false,
}, {
colorOld: '#000000d9',
color: '#000000d9',
imgSrc: 'img/xuanzejiantou.svg',
title: '选择',
checked: false,
}, {
colorOld: '#000000d9',
color: '#000000d9',
imgSrc: 'img/baocun.svg',
title: '保存',
checked: false,
}, {
colorOld: '#000000d9',
color: '#000000d9',
imgSrc: 'img/tucengshuxingtu.svg',
title: '图层',
checked: false,
}
],
rulerHeight: 20,
layerSize: { width: 180, height: 600 },
viewSize: { width: 1024, height: 768 },
windowMouseDown: false,
}
},
methods: {
toolMainClick(index) {
this.toolMainItems[index].color = 'rgb(255, 0, 0)'; // 修改对应索引的颜色
var strTitle = this.toolMainItems[index].title;
switch (strTitle) {
case '默认':
this.toolDefault();
this.togglePressed(index);
break;
case '放大':
this.drawZoomIn();
break;
case '缩小':
this.drawZoomOut();
break;
case '局部':
this.toolViewWindow();
this.togglePressed(index);
break;
case '全部':
this.viewAll();
break;
case '移动':
this.toolViewMove();
this.togglePressed(index);
break;
case '选择':
this.toolSelect();
this.togglePressed(index);
break;
case '保存':
this.drawSave();
break;
case '图层':
this.switchLayerPanel();
break;
default:
break;
}
},
setToolHoverColor(index) {
this.toolMainItems[index].colorOld = this.toolMainItems[index].color;
this.toolMainItems[index].color = 'rgb(24, 144, 255)'; // 修改对应索引的颜色
},
resetToolColor(index) {
if (this.toolMainItems[index].checked === false) {
this.toolMainItems[index].color = this.toolMainItems[index].colorOld;
}
},
togglePressed(index) {
this.isBtnPressed = !this.isBtnPressed;
this.toolMainItems[index].checked = true;
for (var i = 0; i < this.toolMainItems.length; i++) {
if (i !== index) {
this.toolMainItems[i].checked = false;
this.toolMainItems[i].color = '#000000d9';
}
}
},
setupWebSocket() {
//this.websocket = new WebSocket("ws://kep.kepoil.com:7677/event", "json"); // 创建WebSocket连接
this.websocket = new WebSocket("ws://192.168.31.45:8000/event", "json"); // 创建WebSocket连接
//this.websocket = new WebSocket("ws://192.168.31.113:8080/event", "json"); // 创建WebSocket连接
this.websocket.onopen = this.onWebSocketOpen; // WebSocket连接打开时的处理函数
this.websocket.onmessage = this.onWebSocketMessage; // 收到WebSocket消息时的处理函数
this.websocket.onclose = this.onWebSocketClose; // WebSocket连接关闭时的处理函数
},
closeWebSocket() {
if (this.websocket) {
this.websocket.close(); // 关闭WebSocket连接
}
},
onWebSocketOpen() {
console.log("链接成功");
// this.openFile();
// this.sendMessage('ping', null);
//this.startHeartbeat(100);
// 测试
// this.openFile("测试1-.dfd");
/* // 通知父页面 WebSocket 已经打开
const message = { action: 'webSocketOpened' };
if (window.parent && window.parent.postMessage) {
window.parent.postMessage(message, '*');
} */
},
onWebSocketMessage(event) {
try
{
const json = JSON.parse(event.data);
console.info(json);
const evtType = json.type;
// 根据消息的内容执行不同的操作
if (evtType === 'Pong') {
if (this.firstConnect == true) {
//this.stopHeartbeat();
//this.startHeartbeat(10000);
// 通知父页面 WebSocket 已经打开
const message = { action: 'webSocketOpened' };
if (window.parent && window.parent.postMessage) {
window.parent.postMessage(message, '*');
}
this.firstConnect = false;
}
}
else if (evtType === 'NewToken') {
this.isLoading=true;// 开始加载
this.drawerToken = json.drawerToken;
// 通知父页面 图件 已经打开
const message = {action: 'fileOpend', token: this.drawerToken, file:json.userID };
console.info(message);
if (window.parent && window.parent.postMessage) {
window.parent.postMessage(message, '*');
}
console.log("NewToken: " + this.drawerToken);
}
else if(evtType === 'OpenError'){
this.drawerToken = "";
this.ctx.fillStyle = '#FFFFFF'; // 设置背景色
this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
alert("打开文件失败:"+json.userID);
// 通知父页面 图件 已经打开
const message = {action: 'OpenError', token: '', file:json.userID };
if (window.parent && window.parent.postMessage) {
window.parent.postMessage(message, '*');
}
}
else if (evtType === 'Redraw') {
this.imageSrc = json.data + '?_=' + Math.random();
this.drawerToken = json.drawerToken;
this.redrawCanvas(this.imageSrc);
}
else if (evtType === "SelectHandle") {
if (json.data !== -2) {
this.handleIndex = json.data;
}
}
else if (evtType === "DragElement") { // 显示拖拽轮廓图片
let imgContent = json.data;
if (!(imgContent && imgContent.Data)) {
return;
}
this.imgVisible = true;
this.$nextTick(() => {
let imgTmp = this.$refs.image;
imgTmp.src = imgContent.Data;
let canvasRect = this.canvas.getBoundingClientRect();
this.imgPosition = {
x: imgContent.ImgLeft
, y: imgContent.ImgTop
};
});
}
else if (evtType === "ReloadLayer") { // 隐藏拖拽轮廓图片
this.showLayers(json.data);
}
else if (evtType === "MapRangeReal") { // 绘制刻度尺
if (this.queryDrawRuler === true) {
this.drawRuler(json.data);
queryDrawRuler = false;
}
this.isLoading=true;
}
}
finally
{
this.isLoading = false; // 结束加载
}
},
onWebSocketClose() {
console.log("WebSocket connection is closed");
this.stopHeartbeat(); // WebSocket连接关闭时停止心跳检测
setTimeout(this.setupWebSocket, this.reconnectInterval); // 在一定时间后重连WebSocket
},
startHeartbeat(stepTime = 3000) {
this.heartbeatInterval = setInterval(() => {
/* if (this.websocket && this.websocket.readyState === WebSocket.OPEN) {
this.websocket.send("ping"); // 发送心跳消息
} */
this.sendMessage('ping', null);
}, stepTime); // 每10秒发送一次心跳
},
stopHeartbeat() {
if (this.heartbeatInterval) {
clearInterval(this.heartbeatInterval); // 停止心跳检测定时器
}
},
getContaierOverflow() {
if (this.imgVisible) {
return 'hidden';
}
else {
return 'visible';
}
},
initCanvas() {
this.rubberbandDiv = this.$refs.rubberbandDiv;
this.canvas = this.$refs.canvas;
this.ctx = this.canvas.getContext('2d');
this.ctx.fillStyle = '#FFFFFF'; // 设置背景色
this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
const rect = this.canvas.getBoundingClientRect();
this.imgPosition = { x: rect.left, y: rect.top };
},
sendMessage(name, json) { // 发送消息到WebSocket服务器
if (this.websocket && this.websocket.readyState === WebSocket.OPEN) {
const message = {
type: name,
drawerToken: this.drawerToken,
data: json,
};
// console.log('sendMessage Open:' + name);
this.websocket.send(JSON.stringify(message));
}
else {
console.log('sendMessage Error:' + name);
}
},
openFile(fileUrl, token) {
if (!fileUrl) {
return;
}
if (this.drawerToken !== null && this.drawerToken.length > 0) {
// alert("OpenFile" + this.drawerToken);
this.closeDrawer(this.drawerToken);
}
// alert("OpenFile" + fileUrl);
console.log('OpenFile:' + fileUrl);
const rect = this.canvas.getBoundingClientRect();
// console.log('rect:' + rect);
// this.sendMessage("OpenFile", { file: fileUrl, width: rect.width*2, height: rect.height*2 });
this.sendMessage("OpenFile", { file: fileUrl,token:token, width: rect.width, height: rect.height });
},
closeDrawer(token) {
if (this.drawerToken !== null && this.drawerToken.length > 0) {
this.sendMessage("CloseDrawer", {token:token});
}
},
redraw() {
const rect = this.canvas.getBoundingClientRect();
//this.sendMessage("Redraw", { width: rect.width*2, height: rect.height*2 });
this.sendMessage("Redraw", { width: rect.width, height: rect.height });
},
drawRuler(range) {
const ctx = this.ctx;
const widthS = this.viewSize.width;
const heightS = this.viewSize.height;
const leftR = range.left;
const rightR = range.right;
const bottomR = range.bottom;
const topR = range.top;
redrawRuler(widthS, heightS, leftR, rightR, bottomR, topR);
},
drawSave() {
this.sendMessage("SaveFile", "");
},
switchLayerPanel() {
this.layerVisible = !this.layerVisible;
if (this.layerVisible) {
this.sendMessage("GetLayers", "");
}
},
showLayers(layerData) {
// console.log(layerData);
// 使用 '\r\n' 作为分隔符拆分字符串
const splitLines = layerData.split('\r\n');
let layerNodes = [];
layerNodes[0] = { id: "Layer:", pId: "-1", name: "图层", open: true, halfCheck: false }
splitLines.forEach((line, index) => {
if (line.length == 0) {
return;
}
let layerStatus = line.substring(0, line.indexOf("|"));
let layerData = line.substring(line.indexOf("|") + 1);
let layerArray = layerData.split("\\");
if (layerArray.length == 0) {
return;
}
let currLayer = "Layer:";
for (let i = 0; i < layerArray.length; i++) {
let currName = layerArray[i];
if (currName == "Layer:") {
continue;
}
let layerItem = { id: "", pId: "0", name: "", open: false };
layerItem.pId = currLayer;
currLayer += ("\\" + currName);
layerItem.id = "" + currLayer;
layerItem.name = currName;
layerItem.open = i < layerArray.length - 1;
if (i == layerArray.length - 1) {
layerItem.icon = layerStatusIcons[1];
layerNodes.push(layerItem);
}
else {
const findIndex = layerNodes.findIndex(item => item.id == layerItem.id);
if (findIndex == -1) {
layerItem.icon = layerStatusIcons[1];
layerNodes.push(layerItem);
}
}
}
});
zNodes = [...layerNodes].reverse();
this.$nextTick(() => {
//console.log("zNodes: " + zNodes);
reset(zNodes);
});
},
setLayerStatus(status) { /* 设置选中节点的图层状态 */
var treeObj = $.fn.zTree.getZTreeObj("treeDemo");
var nodes = treeObj.getCheckedNodes(true);
var nCount = nodes.length;
if (nCount === 0) {
return;
}
var strStatus = "10";
if (status === 2) {
strStatus = "11";
}
else if (status === 3) {
strStatus = "12";
}
var statusData = "";
for (var i = 0; i < nCount; i++) {
var imgUrl = layerStatusIcons[status];
nodes[i].icon = imgUrl;
treeObj.updateNode(nodes[i]);
statusData += (strStatus + "|" + nodes[i].id + "\r\n");
}
this.sendMessage("SetLayersStatus", { layerData: statusData });
},
deleteLayer() {
var treeObj = $.fn.zTree.getZTreeObj("treeDemo");
var nodes = treeObj.getCheckedNodes(true);
var nCount = nodes.length;
if (nCount === 0) {
return;
}
var statusData = "";
for (var i = 0; i < nCount; i++) {
statusData += (nodes[i].id + ",");
treeObj.removeNode(nodes[i]);
}
this.sendMessage("DeleteLayers", { layers: statusData, widthChild: 1 });
},
canvasMouseDown(event) {
this.mouseDown = true;
this.lastX = event.offsetX;
this.lastY = event.offsetY;
if (this.drawerToolType == canvasToolType.ITEM_VIEW_PAN) {
this.isDragFirst = true;
this.imgVisible = true;
this.imgPosition = { x: 0, y: 0 };
const rect = this.$refs.canvas.getBoundingClientRect();
this.mouseStartX = event.clientX - rect.left;
this.mouseStartY = event.clientY - rect.top;
// console.log("start: X:" + this.mouseStartX + " Y:" + this.mouseStartY);
}
else if (this.drawerToolType == canvasToolType.ITEM_VIEW_WINDOW) {
event.preventDefault();
this.rubberVisible = true;
const rect = this.$refs.canvas.getBoundingClientRect();
this.mouseStartX = event.clientX - rect.left;
this.mouseStartY = event.clientY - rect.top;
this.rubberbandRectangle.left = this.mouseStartX;
this.rubberbandRectangle.top = this.mouseStartY;
this.rubberbandRectangle.width = 1;
this.rubberbandRectangle.height = 1;
}
else if (this.drawerToolType == canvasToolType.ITEM_SELECT) {
const rect = this.$refs.canvas.getBoundingClientRect();
this.mouseStartX = event.clientX - rect.left;
this.mouseStartY = event.clientY - rect.top;
this.sendMessage("SelectMouseDown", { x: this.mouseStartX, y: this.mouseStartY });
}
},
canvasMouseUp(event) {
if (this.drawerToolType == canvasToolType.ITEM_VIEW_PAN) {
const rect = this.$refs.canvas.getBoundingClientRect();
let endX = event.clientX - rect.left;
let endY = event.clientY - rect.top;
this.sendMessage("ViewPan", {
startX: this.mouseStartX, startY: this.mouseStartY,
endX: endX, endY: endY,
width: this.viewSize.width, height: this.viewSize.height
});
}
else if (this.drawerToolType == canvasToolType.ITEM_VIEW_WINDOW) {
this.rubberVisible = false;
const rect = this.$refs.canvas.getBoundingClientRect();
let endX = event.clientX - rect.left;
let endY = event.clientY - rect.top;
this.sendMessage("ViewWindow", {
startX: this.mouseStartX, startY: this.mouseStartY,
endX: endX, endY: endY,
width: this.viewSize.width, height: this.viewSize.height
});
}
else if (this.drawerToolType == canvasToolType.ITEM_SELECT) {
if (this.handleIndex == 5) {
// 拖动结束
let endX = event.offsetX;
let endY = event.offsetY;
this.dragImageVisible = false;
this.sendMessage("DragElement", { x: endX, y: endY });
}
else {
// 图元选择
const rect = this.$refs.canvas.getBoundingClientRect();
let endX = event.offsetX;// - rect.left;
let endY = event.offsetY;// - rect.top;
this.sendMessage("SelectMouseUp", { x: endX, y: endY, keyCode: this.pressedKeyCode});
}
// mouseThought.value = false;
}
this.mouseDown = false;
// handleIndex = this.handleIndex===5 ? this.handleIndex : -1;
},
canvasMouseMove(event) {
this.mouseHorizontal = event.offsetX + 20;//-rect.left;
this.mouseVertical = event.offsetY + 20;// - rect.top;
if (this.mouseDown != true) {
if (this.drawerToolType == canvasToolType.ITEM_SELECT) {
this.sendMessage("MouseMove", { x: event.offsetX, y: event.offsetY, handleIndex: this.handleIndex });
}
}
else {
if (this.drawerToolType == canvasToolType.ITEM_VIEW_PAN) {// 执行视图拖动
let offsetX = event.offsetX - this.lastX;
let offsetY = event.offsetY - this.lastY;
const rect = this.canvas.getBoundingClientRect();
if (this.isDragFirst) {
const dataURL = this.canvas.toDataURL('image/png');
this.$refs.image.src = dataURL;
// console.log("first before: X" + this.imgPosition.x + " Y" + this.imgPosition.y);
this.imgPosition = { x: this.imgPosition.x + offsetX, y: this.imgPosition.y + offsetY };
// console.log("first after: X" + this.imgPosition.x + " Y" + this.imgPosition.y);
requestAnimationFrame(() => {
this.ctx.clearRect(0, 0, rect.width, rect.height);
});
this.isDragFirst = false;
}
else {
this.imgPosition = { x: this.imgPosition.x + offsetX, y: this.imgPosition.y + offsetY };
// console.log("moveing: X" + this.imgPosition.x + " Y" + this.imgPosition.y);
}
this.lastX = event.offsetX;
this.lastY = event.offsetY;
}
else if (this.drawerToolType == canvasToolType.ITEM_VIEW_WINDOW) {
const rect = this.canvas.getBoundingClientRect();
var endX = event.clientX - rect.left;
var endY = event.clientY - rect.top;
var dragStartX = this.mouseStartX;
var dragStartY = this.mouseStartY;
if (endX < dragStartX) {
dragStartX = endX;
endX = this.mouseStartX;
}
if (endY < dragStartY) {
dragStartY = endY;
endY = this.mouseStartY;
}
this.rubberbandRectangle = {
left: dragStartX,
top: dragStartY,
width: endX - dragStartX,
height: endY - dragStartY
};
event.preventDefault();
}
else if (this.drawerToolType == canvasToolType.ITEM_SELECT) {
let offsetX = event.offsetX - this.lastX;
let offsetY = event.offsetY - this.lastY;
this.imgPosition = { x: this.imgPosition.x + offsetX, y: this.imgPosition.y + offsetY };
this.lastX = event.offsetX;
this.lastY = event.offsetY;
}
}
},
canvasMouseWheel(event) {
this.count++;
},
/** 放大 */
drawZoomIn() {
this.sendMessage("ZoomIn", { width: this.viewSize.width, height: this.viewSize.height });
//emit('tool-changed', canvasAction.ZoomIn);
console.log("drawZoomIn: " + this.drawerToken);
},
/** 缩小 */
drawZoomOut() {
this.sendMessage("ZoomOut", { width: this.viewSize.width, height: this.viewSize.height });
},
viewAll() {
this.sendMessage("ViewAll", { width: this.viewSize.width, height: this.viewSize.height });
},
async redrawCanvas(data) {
if (data.length === 0) {
return;
}
try {
const response = await fetch(data, { cache: 'no-store' });
if (!response.ok) {
throw new Error('Network response was not ok');
}
const blob = await response.blob();
const bitmap = await createImageBitmap(blob);
this.ctx.drawImage(bitmap, 0, 0);
this.imgVisible = false;
// 重绘刻度尺
this.queryDrawRuler = true;
// const rect = this.canvas.getBoundingClientRect();
this.sendMessage("QueryRangeScreen2Real", { startX: 0, endX: this.viewSize.width, startY: 0, endY: this.viewSize.height });
} catch (error) {
console.error('Failed to load the image:', error);
}
},
toolDefault() {
this.drawerToolType = canvasToolType.ITEM_DEFAULT;
},
toolViewMove() {
this.drawerToolType = canvasToolType.ITEM_VIEW_PAN;
},
toolViewWindow() {
this.drawerToolType = canvasToolType.ITEM_VIEW_WINDOW;
},
toolSelect() {
this.drawerToolType = canvasToolType.ITEM_SELECT;
},
GetCursor() {
if (this.drawerToolType == canvasToolType.ITEM_SELECT) {
if (this.handleIndex == 5) {
return MouseIcons.move;
}
else {
return MouseIcons.pointerSelect;
}
} else if (this.drawerToolType == canvasToolType.ITEM_VIEW_PAN) {
return MouseIcons.viewPan;
}
else if (this.drawerToolType == canvasToolType.ITEM_VIEW_WINDOW) {
return MouseIcons.crosshair;
}
return MouseIcons.default;
},
handleResize() {
if (this.windowMouseDown === true) {
return;
}
this.$nextTick(() => {
const comWindow = this.$el.parentNode;
var viewWidth = comWindow.offsetWidth - this.rulerHeight;
if (this.layerVisible === true) {
// 总宽度-图层树宽度
viewWidth = comWindow.offsetWidth - this.layerSize.width - this.rulerHeight;
}
// 总高度-菜单高度
var viewHeight = comWindow.offsetHeight - 50 - this.rulerHeight;
this.layerSize.height = viewHeight + this.rulerHeight;
this.viewSize = { width: viewWidth, height: viewHeight };
this.redrawCanvas(this.imageSrc);
});
},
/* onWindowMouseDown() {
this.windowMouseDown = true;
},
onWindowMouseUp() {
this.windowMouseDown = false;
},*/
handleKeyDown(event) {
this.pressedKeyCode = event.keyCode;
},
handleKeyUp(event){
this.pressedKeyCode = null;
},
},
mounted() {
this.handleResize();
window.addEventListener('resize', this.handleResize);
this.initCanvas();
this.image = new Image();
this.setupWebSocket(); // 创建WebSocket连接
// 全局监听 mousedown 和 mouseup 事件
/* window.addEventListener('mousedown', this.onWindowMouseDown);
window.addEventListener('mouseup', this.onWindowMouseUp); */
// 使用 document.body.onmousedown 和 onmouseup 进行全局监听
/* document.body.onmousedown = this.onWindowMouseDown;
document.body.onmouseup = this.onWindowMouseUp; */
this.openFile = this.openFile.bind(this); // 绑定 this
window.addEventListener('message', function (event) {
// console.log('Message got:' + event.data.action);
if (event.data.action === 'openFile') {
this.isLoading=true;// 显示加载动画
this.openFile(event.data.fileUrl, event.data.token);
}
if(event.data.action === "redraw"){
this.redraw();
}
if(event.data.action === "viewAll"){
this.viewAll();
}
if(event.data.action === "showWait"){
}
}.bind(this));
// 全局监听键盘事件
window.addEventListener('keydown', this.handleKeyDown);
window.addEventListener('keyup', this.handleKeyUp);
},
beforeUnmount() {
this.closeDrawer();
this.closeWebSocket(); // 在组件销毁前关闭WebSocket连接
},
unmounted() {
window.removeEventListener('resize', this.handleResize);
window.removeEventListener('openFile', this.openFile);
// 移除全局事件监听
/* window.removeEventListener('mousedown', this.onWindowMouseDown);
window.removeEventListener('mouseup', this.onWindowMouseUp); */
// 移除全局事件监听器
/* document.body.onmousedown = null;
document.body.onmouseup = null; */
window.removeEventListener('keydown', this.handleKeyDown);
window.removeEventListener('keyup', this.handleKeyUp);
console.log('unmounted');
},
/* beforeDestroy() {
this.closeWebSocket(); // 在组件销毁前关闭WebSocket连接
}, */
}
const app = Vue.createApp(VueApp);
app.mount('#app');
</script>
<SCRIPT type="text/javascript">
var setting = {
view: {
dblClickExpand: dblClickExpand
},
check: {
enable: true,
chkStyle: "checkbox", // 使用复选框模式
chkboxType: { "Y": "", "N": "" }, // 关键设置
//nocheckInherit: true // 防止子节点影响父节点
},
edit: {
enable: true,
showRemoveBtn: false,
showRenameBtn: false
},
data: {
simpleData: {
enable: true
}
},
callback: {
beforeDrag: beforeDrag,
beforeDrop: beforeDrop,
/* beforeCheck: zTreeBeforeCheck,
onCheck: onCheck, */
}
};
var zNodes = [
{ id: 'aa', pId: 0, name: "随意拖拽 1", open: true },
{ id: 11, pId: 'aa', name: "随意拖拽 1-1" },
{ id: 12, pId: 'aa', name: "随意拖拽 1-2", open: true },
{ id: 121, pId: 12, name: "随意拖拽 1-2-1" },
{ id: 122, pId: 12, name: "随意拖拽 1-2-2" },
{ id: 123, pId: 12, name: "随意拖拽 1-2-3" },
{ id: 13, pId: 'aa', name: "禁止拖拽 1-3", open: true, drag: false },
{ id: 131, pId: 13, name: "禁止拖拽 1-3-1", drag: false },
{ id: 132, pId: 13, name: "禁止拖拽 1-3-2", drag: false },
{ id: 133, pId: 13, name: "随意拖拽 1-3-3" },
{ id: 2, pId: 0, name: "随意拖拽 2", open: true },
{ id: 21, pId: 2, name: "随意拖拽 2-1" },
{ id: 22, pId: 2, name: "禁止拖拽到我身上 2-2", open: true, drop: false },
{ id: 221, pId: 22, name: "随意拖拽 2-2-1" },
{ id: 222, pId: 22, name: "随意拖拽 2-2-2" },
{ id: 223, pId: 22, name: "随意拖拽 2-2-3" },
{ id: 23, pId: 2, name: "随意拖拽 2-3" }
];
function dblClickExpand(treeId, treeNode) {
return treeNode.level > 0;
}
function beforeDrag(treeId, treeNodes) {
for (var i = 0, l = treeNodes.length; i < l; i++) {
if (treeNodes[i].drag === false) {
return false;
}
}
return true;
}
function beforeDrop(treeId, treeNodes, targetNode, moveType) {
return targetNode ? targetNode.drop !== false : true;
}
/* 设置选中状态 */
function setCheck() {
var zTree = $.fn.zTree.getZTreeObj("treeDemo"),
isCopy = true, //$("#copy").attr("checked"),
isMove = true, // $("#move").attr("checked"),
prev = true, // $("#prev").attr("checked"),
inner = true, // $("#inner").attr("checked"),
next = true; //$("#next").attr("checked");
if (zTree == null) {
return;
}
zTree.setting.edit.drag.isCopy = isCopy;
zTree.setting.edit.drag.isMove = isMove;
//showCode(1, ['setting.edit.drag.isCopy = ' + isCopy, 'setting.edit.drag.isMove = ' + isMove]);
zTree.setting.edit.drag.prev = prev;
zTree.setting.edit.drag.inner = inner;
zTree.setting.edit.drag.next = next;
//showCode(2, ['setting.edit.drag.prev = ' + prev, 'setting.edit.drag.inner = ' + inner, 'setting.edit.drag.next = ' + next]);
}
/* function zTreeBeforeCheck(treeId, treeNode) {
if (treeNode.children && treeNode.children.length > 0) {
return true; // 阻止勾选子节点
}
return false;
}; */
function onCheck(event, treeId, treeNode) {
/* var zTree = $.fn.zTree.getZTreeObj(treeId);
var nodes = zTree.getNodesByFilter(function (node) {
return node.parentTId === treeNode.tId;
});
// 对于每个子节点,如果它被勾选,则保持勾选状态;否则取消勾选
for (var i = 0, l = nodes.length; i < l; i++) {
var node = nodes[i];
if (!node.checked) {
zTree.checkNode(node, false, true);
}
} */
}
function cancelHalf(treeNode) {
/* if (treeNode.checkedEx) return;
var zTree = $.fn.zTree.getZTreeObj("treeDemo");
treeNode.halfCheck = false;
zTree.updateNode(treeNode); */
}
function showCode(id, str) {
var code = $("#code" + id);
code.empty();
for (var i = 0, l = str.length; i < l; i++) {
code.append("<li>" + str[i] + "</li>");
}
}
/* function SetLayerStatus(status){
var treeObj = $.fn.zTree.getZTreeObj("treeDemo");
var nodes = treeObj.getCheckedNodes(true);
if(nodes){
<scritp src="drawerRuler.js" type="text/javascript"></scritp>
}
} */
function reset(nodesData) {
$.fn.zTree.init($("#treeDemo"), setting, nodesData);
setCheck();
}
$(document).ready(function () {
$.fn.zTree.init($("#treeDemo"), setting, zNodes);
setCheck();
//$("#copy").bind("change", setCheck);
//$("#move").bind("change", setCheck);
//$("#prev").bind("change", setCheck);
//$("#inner").bind("change", setCheck);
//$("#next").bind("change", setCheck);
});
//-->
</SCRIPT>
<script src="drawerRuler.js" type="text/javascript"></script>
<script type="text/javascript">
var ruler_horizontal = new drawerRuler({ container: "ruler-horizontal", orientation: 1 });
var ruler_vertial = new drawerRuler({ container: "ruler-vertical", orientation: 2 });
function redrawRuler(widthS, heightS, leftR, rightR, bottomR, topR) {
ruler_horizontal.api.redraw(widthS, leftR, rightR);
ruler_vertial.api.redraw(heightS, bottomR, topR);
};
</script>
</body>
</html>