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.htm

1851 lines
62 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);
}
}
/*自定义右键菜单样式*/
.custom-context-menu {
position: absolute;
background: white;
border: 1px solid #ccc;
padding: 5px;
z-index: 1000;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
}
.custom-context-menu div {
cursor: pointer;
padding: 5px;
}
.custom-context-menu div:hover {
background-color: #f0f0f0;
}
/*分隔线样式*/
.divider {
border: none;
height: 1px;
background: #ccc;
margin: 3px 0;
}
-->
</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);image-rendering: crisp-edges;"
@contextmenu="handleWellContextMenu">
<div v-show="showContextMenu" class="custom-context-menu" :style="{
top: `${contextMenuY}px`,
left: `${contextMenuX}px`,
}">
<div @click="handleMenuAction('edit')">编辑</div>
<hr class="divider" />
<div @click="handleMenuAction('wellGroupClone')">应用井组参数到其它井组</div>
<div @click="handleMenuAction('wellGroupData')">井组数据</div>
</div>
</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 = {
Default: 0,
Select: 1,
Pointer: 2,
ViewPan: 3,
ViewWindow: 4,
Connection: 5,
Convexity: 6,
Model: 7,
Fault: 8,
FaultReverse: 9,
Rectangle: 10,
Ellipse: 11,
Curve: 12, // Line,
Arc: 13,
Chord: 14,
Pie: 15,
Polygon: 16,
Proportion: 17, // 比例尺
Point: 18,
FractionPoint: 19, // 分数点
CrossPoint: 20, // 十字点
Text: 21,
Equilateral: 22, // 等边多边形
RectangularCSGrid: 23, // 直角坐标网
BreakDirect: 24, // 直接打断
Break: 25, // 打断
Delete: 26, // 删除
DeleteIn: 27, // 删除区域内元素
DeleteCondition: 28, // 条件删除
DeleteOut: 29, // 删除区域外元素
ExtendCurve: 30, // 延伸曲线
TrimCurve: 31, // 剪切曲线
CloseCurve: 32, // 闭合曲线
MoveCurveName: 33, // 移动曲线内部名字
LinkCurve: 34, // 连接曲线
MergeCurve: 35, // 连接曲线
ReverseCurve: 36, // 反转曲线
NameToZ: 37, // 曲线名称变为Z值,
ZToName: 38, // Z值变为曲线名称,
FindCurveOfEmptyName: 39, // 发现空名称的曲线
RangeToImage: 40, // 复制选择区域为图像
WindowToImage: 41, // 复制窗口区域为图像
AllToImage: 42, // 复制全图为图像
RangeToImageEx: 43, // 定制复制选择区域为图像
LeftAlignment: 44, // 左对齐
RightAlignment: 45, // 右对齐
TopAlignment: 46, // 顶对齐
BottomAlignment: 47, // 底对齐
HCenterAlignment: 48, // 水平居中
VCenterAlignment: 49, // 垂直居中
DisplayOrderTop: 50, // 最上显示
DisplayOrderBottom: 51, // 最下显示
DisplayOrderFront: 52, // 上移一层
DisplayOrderBack: 53, // 下移一层
HorizontalMirror: 54, // 水平镜像
VerticalMirror: 55, // 垂直镜像
EditCurveNode: 56, // 编辑曲线节点
CurveDensityNode: 57, // 曲线节点加密
CurveRedundancy: 58, // 曲线冗余 去掉曲线上多余的节点
CurveSmooth: 59, // 光滑曲线
CutOutByRect: 60, // 矩形式外切
CutOutByPickup: 61, // 拾取式外切
CutInByRect: 62, // 矩形式内切
CutInByPickup: 63, // 拾取式内切
CalculateVolume: 64, // 计算体积
SetZValueOfSurface: 65, // 设置曲面Z值
EditGridPoint: 66,
PointPropertyClear: 67, // 点属性的批量清理
PointPropertySet: 68, // 点属性的批量设置
CurvePropertyClear: 69, // 线属性的批量清理
CurvePropertySet: 70, // 线属性的批量设置
HighLightTip: 71, // 高亮图元并获得提示信息
ArcToCurve: 72,
CurveZFromSurface: 73, // 由曲面设置曲线节点的Z值
Calibration2: 74, // 两点校正
Calibration4: 75, // 四点校正
ConnectCurveFilling: 76, // 连接曲线形成填充区域
SolidAuto: 77, // 自动填充区域
SolidLink: 78, // 连接填充区域
SaveAsSymbol: 79, // 保存为符号
PositiveNegativeSign: 80, // Z值正负号
CurveNameSetting: 81, // 曲线名称设置
SetContourName: 82, // 设置等值线名称
Finsih: 83, // 完成了一个命令 此值没有对应的类
PolygonToImage: 84, // 复制选择区域内选中多边形区域为图像
WellGroup: 85, // 井组绘制
WellGroupEdit: 86, // 井组编辑
EditWellGroupBranchCurveNode: 87, // 井分支的编辑
CurveBroaden: 88, // 曲线外扩
FaultSymply: 89, // 断层简化
Measure: 90, // 测量
Eraser: 91, // 橡皮擦
SelectWellPole: 92,
NumberOfDrawTools: 93,
}
const VueApp = {
data() {
return {
// 加载状态,滚动条显示状态
isLoading: false, // 新增加载状态
firstConnect: true,
drawerToken: '',
isBtnPressed: false,
websocket: null, // WebSocket对象
reconnectInterval: 3000, // 重连间隔时间(毫秒)
heartbeatInterval: null, // 心跳定时器
count: 0,
canvas: null,
// 选中的井组ID
selectedElementId: "",
selectedElement: {},
// 是否显示右键菜单
showContextMenu: false,
contextMenuX: 0,
contextMenuY: 0,
layerVisible: false,
isDragging: false,
isDragFirst: true,
queryDrawRuler: false,
imageSrc: '',
imgVisible: false,
imgPosition: { x: 0, y: 0 },
mouseStartX: 0,
mouseStartY: 0,
lastX: 0,
lastY: 0,
// isRegionSelecting: false,
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,
/* 选择轮廓图 */
initialRect: { left: 0, top: 0, width: 0, height: 0 },
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/refresh.svg',
title: '刷新',
checked: false,
}, {
colorOld: '#000000d9',
color: '#000000d9',
imgSrc: 'img/center.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,
// 选择框的句柄
SelectHandle: {
TopLeft: 0,
Top: 1,
TopRight: 2,
Right: 3,
BottomRight: 4,
Bottom: 5,
BottomLeft: 6,
Left: 7,
Center: 8,
Body: 9,
Nothing: -1
},
}
},
methods: {
/* 联动选中父子节点
initZTree() {
const setting = {
check: {
enable: true,
chkboxType: { "Y": "ps", "N": "ps" } // 父子联动选择
},
callback: {
onCheck: this.onZTreeCheck,
beforeCheck: function(treeId, treeNode) {
// 阻止图层根节点被选中
if(treeNode.id === "Layer:"){
return false;
}
return true;
}
},
data: {
key: {
// 设置图层根节点不可选
chkDisabled: function(node) {
return node.id === "Layer:";
}
}
}
};
$.fn.zTree.init($("#treeDemo"), setting, zNodes);
},
onZTreeCheck(event, treeId, treeNode) {
const zTree = $.fn.zTree.getZTreeObj("treeDemo");
// 选中父节点时自动选中所有子节点
if (treeNode.checked) {
const children = treeNode.children;
if (children && children.length > 0) {
zTree.checkNode(children[0], true, true);
}
}
// 选中子节点时自动选中父节点
else {
const parentNode = treeNode.getParentNode();
if (parentNode) {
zTree.checkNode(parentNode, false, true);
}
}
},*/
handleWellContextMenu(event) {
// 阻止默认的右键菜单
event.preventDefault();
if (this.selectedElementId === "") {
console.warn('没有选中任何井组');
return;
}
// 设置右键菜单的位置
this.contextMenuX = event.layerX;
this.contextMenuY = event.layerY;
this.showContextMenu = true;
// 阻止事件冒泡,避免触发 mouseup 事件
event.stopPropagation();
},
// 处理右键菜单的操作
handleMenuAction(action) {
this.showContextMenu = false; // 隐藏右键菜单
switch (action) {
// 应用井组参数
case 'wellGroupClone':
if (window.parent && window.parent.postMessage) {
window.parent.postMessage({ action: 'wellGroupClone', data: this.selectedElementId }, '*');
}
break;
case 'wellGroupData':
if (window.parent && window.parent.postMessage) {
window.parent.postMessage({ action: 'wellGroupData' }, '*');
}
break;
// 取消操作
case 'cancel':
showContextMenu = false;
break;
// 编辑操作
case 'edit':
if (window.parent && window.parent.postMessage) {
/* console.log('编辑井组:', this.selectedElementId, this.selectedElement); */
window.parent.postMessage({ action: 'editWellGroup', data: this.selectedElement, dataid: this.selectedElementId, parenttoken: this.drawerToken }, '*');
}
break;
default:
console.warn('未知操作:', action);
}
},
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.drawRefresh();
break;
case '刷新':
this.drawCenter();
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:8000/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 = new WebSocket("ws://localhost: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;
console.log(evtType)
// 根据消息的内容执行不同的操作
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;
// console.log(json.data);
}
}
else if (evtType === "DragElement") { // 显示拖拽轮廓图片
let imgContent = json.data;
if (!(imgContent && imgContent.Data)) {
return;
}
this.imgVisible = true;
this.imgPosition = { x: imgContent.ImgLeft, y: imgContent.ImgTop };
this.initialRect = { left: imgContent.ImgLeft, top: imgContent.ImgTop, width: imgContent.ImgWidth, height: imgContent.ImgHeight };
this.$nextTick(() => {
let imgTmp = this.$refs.image;
imgTmp.src = imgContent.Data;
});
// this.redrawCanvas(this.imageSrc);
}
else if (evtType === "ElementProperty") {
let imgContent = json.data;
this.selectedElementId = imgContent.ElementID;
this.selectedElement = imgContent.ElementData;
if (window.parent && window.parent.postMessage) {
window.parent.postMessage({ action: 'data-change', data: imgContent.ElementData, Id: imgContent.ElementID }, '*');
}
}
else if (evtType === "ReloadLayer") { // 隐藏拖拽轮廓图片
console.log("ReloadLayer:" + json.data);
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');
const devicePixelRatio = window.devicePixelRatio || 1;
const rect = this.canvas.getBoundingClientRect();
this.canvas.width = rect * devicePixelRatio;
this.canvas.height = rect * devicePixelRatio;
this.ctx.scale(devicePixelRatio, devicePixelRatio);
// 关闭图像平滑处理
this.ctx.imageSmoothingEnabled = false;
this.ctx.fillStyle = '#FFFFFF'; // 设置背景色
this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
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();
zNodes = layerNodes;*/
// 确保layerData是有效的JSON字符串
if (typeof layerData === 'string') {
layerData = JSON.parse(layerData);
}
// 确保转换后是数组
if (!Array.isArray(layerData)) {
console.error('Invalid layer data format - expected array');
return;
}
// 创建图层根节点
let layerNodes = [{
id: "Layer:",
pId: "-1",
name: "图层",
open: true,
halfCheck: false,
icon: layerStatusIcons[1],
children: []
}];
// 递归处理节点和子节点
const processNode = (node) => {
const treeNode = {
id: node.id,
pId: "Layer:",// node.ParentId.toString(),
name: node.name || "",
open: false,
icon: layerStatusIcons[1],
status: node.status || 0,
fullPath: node.fullPath || "",
children: [],
};
// 如果有子节点,递归处理
if (node.children && node.children.length > 0) {
treeNode.children = node.children.map(child => {
const childNode = processNode(child);
// 确保子节点的pId指向父节点id
childNode.pId = treeNode.id;
return childNode;
});
// 有子节点时默认展开
treeNode.open = true;
}
return treeNode;
};
// let layerNodes = layerData.map(node => processNode(node));
// 处理传入的图层数据并添加到根节点下
if (Array.isArray(layerData)) {
layerNodes[0].children = layerData.map(node => processNode(node));
}
zNodes = layerNodes;
this.$nextTick(() => {
console.log("zNodes: " + zNodes);
reset(zNodes);
// this.initZTree(); 联动选中父子节点
});
},
setLayerStatus(status) { /* 设置选中节点的图层状态 */
var treeObj = $.fn.zTree.getZTreeObj("treeDemo");
var nodes = treeObj.getCheckedNodes(true);
// 移除name为"图层"的根节点
nodes = nodes.filter(node => node.name !== "图层");
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 + "|Layer:\\" + nodes[i].fullPath + "\r\n");
}
this.sendMessage("SetLayersStatus", { layerData: statusData });
},
deleteLayer() {
var treeObj = $.fn.zTree.getZTreeObj("treeDemo");
var nodes = treeObj.getCheckedNodes(true);
nodes = nodes.filter(node => node.name !== "图层");
var nCount = nodes.length;
if (nCount === 0) {
return;
}
var statusData = "";
for (var i = 0; i < nCount; i++) {
// statusData += (nodes[i].id + ",");
statusData += ("Layer:\\" + nodes[i].fullPath + ",");
treeObj.removeNode(nodes[i]);
}
this.sendMessage("DeleteLayers", { layers: statusData, widthChild: 1 });
},
canvasMouseDown(event) {
this.mouseDown = true;
this.lastX = event.offsetX;
this.lastY = event.offsetY;
this.mouseStartX = event.offsetX;
this.mouseStartY = event.offsetY;
if (this.drawerToolType == canvasToolType.ViewPan) {
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.ViewWindow) {
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.Select) {
const rect = this.$refs.canvas.getBoundingClientRect();
if (this.handleIndex === this.SelectHandle.Nothing) {
// 框选
// this.rubberVisible = true;
}
if (this.handleIndex >= 0 && this.handleIndex <= 9) {
// 发送拖动开始消息
this.sendMessage("SelectDragStart", { x: event.offsetX, y: event.offsetY });
}
// this.sendMessage("SelectMouseDown", { x: this.mouseStartX, y: this.mouseStartY });
}
this.handleMenuAction('cancel');
},
canvasMouseUp(event) {
if (this.drawerToolType == canvasToolType.ViewPan) {
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.ViewWindow) {
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.Select) {
if (this.handleIndex === this.SelectHandle.Body) {
// 拖动结束
let endX = event.offsetX;
let endY = event.offsetY;
this.dragImageVisible = false;
// this.sendMessage("DragElement", { x: endX, y: endY });
this.sendMessage("SelectTransformElements", { handle: this.handleIndex, startX: this.mouseStartX, startY: this.mouseStartY, endX: endX, endY: endY });
}
else if (this.handleIndex >= 0 && this.handleIndex < 8) {
// 变形处理
let endX = event.offsetX;
let endY = event.offsetY;
this.dragImageVisible = false;
this.sendMessage("SelectTransformElements", { handle: this.handleIndex, startX: this.mouseStartX, startY: this.mouseStartY, endX: endX, endY: endY });
}
else if (this.handleIndex === this.SelectHandle.Nothing) {
this.rubberVisible = false;
const rect = this.$refs.canvas.getBoundingClientRect();
let endX = event.offsetX;// - rect.left;
let endY = event.offsetY;// - rect.top;
/* 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 });
} */
this.sendMessage("SelectRegion", {
startX: this.lastX,
startY: this.lastY,
endX: endX,
endY: endY,
isAdd: false
});
// mouseThought.value = false;
}
}
this.mouseDown = false;
},
canvasMouseMove(event) {
this.mouseHorizontal = event.offsetX + 20;//-rect.left;
this.mouseVertical = event.offsetY + 20;// - rect.top;
if (this.mouseDown != true) {
if (this.drawerToolType == canvasToolType.Select) {
this.sendMessage("SelectMouseMove", { x: event.offsetX, y: event.offsetY, handleIndex: this.handleIndex });
}
return;
}
// 鼠标按下状态事件处理
if (this.drawerToolType == canvasToolType.ViewPan) {// 执行视图拖动
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.ViewWindow) {
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.Select) {
var currentX = event.offsetX;
var currentY = event.offsetY;
event.preventDefault();
if (this.handleIndex === this.SelectHandle.Nothing) {
// 框选框绘制
// const rect = this.canvas.getBoundingClientRect();
// 使用 offsetX/offsetY 获取相对于 canvas 的坐标
var dragStartX = this.lastX;
var dragStartY = this.lastY;
// 确保坐标按左上->右下排列
var left = Math.min(dragStartX, currentX);
var top = Math.min(dragStartY, currentY);
var right = Math.max(dragStartX, currentX);
var bottom = Math.max(dragStartY, currentY);
var rbWidth = right - left;
var rbHeight = bottom - top;
if (rbWidth > 0 || rbHeight > 0) {
if (this.rubberVisible === false) {
this.rubberVisible = true;
}
this.rubberbandRectangle = {
left: left,
top: top,
width: rbWidth,
height: rbHeight
};
}
else {
this.rubberVisible = false;
}
}
else if (this.handleIndex === this.SelectHandle.Right) {
let imgTmp = this.$refs.image;
if (imgTmp && this.imgVisible) {
imgTmp.style.objectFit = 'fill'; // 允许拉伸填充
imgTmp.style.width = `${this.initialRect.width + (currentX - this.mouseStartX)}px`;
imgTmp.style.height = `${this.initialRect.height}px`;
}
}
else if (this.handleIndex === this.SelectHandle.Left) {
let imgTmp = this.$refs.image;
if (imgTmp && this.imgVisible) {
imgTmp.style.objectFit = 'fill'; // 允许拉伸填充
imgTmp.style.width = `${this.initialRect.width - (currentX - this.mouseStartX)}px`;
imgTmp.style.height = `${this.initialRect.height}px`;
this.imgPosition.x = this.initialRect.left + (currentX - this.mouseStartX);
}
}
else if (this.handleIndex === this.SelectHandle.Bottom) {
let imgTmp = this.$refs.image;
if (imgTmp && this.imgVisible) {
imgTmp.style.objectFit = 'fill'; // 允许拉伸填充
imgTmp.style.width = `${this.initialRect.width}px`;
imgTmp.style.height = `${this.initialRect.height + (currentY - this.mouseStartY)}px`;
}
}
else if (this.handleIndex === this.SelectHandle.Top) {
let imgTmp = this.$refs.image;
if (imgTmp && this.imgVisible) {
imgTmp.style.objectFit = 'fill'; // 允许拉伸填充
imgTmp.style.width = `${this.initialRect.width}px`;
imgTmp.style.height = `${this.initialRect.height - (currentY - this.mouseStartY)}px`;
this.imgPosition.y = this.initialRect.top + (currentY - this.mouseStartY);
}
}
else if (this.handleIndex === this.SelectHandle.BottomRight) {
let imgTmp = this.$refs.image;
if (imgTmp && this.imgVisible) {
imgTmp.style.objectFit = 'fill'; // 允许拉伸填充
imgTmp.style.width = `${this.initialRect.width + (currentX - this.mouseStartX)}px`;
imgTmp.style.height = `${this.initialRect.height + (currentY - this.mouseStartY)}px`;
}
}
else if (this.handleIndex === this.SelectHandle.BottomLeft) {
let imgTmp = this.$refs.image;
if (imgTmp && this.imgVisible) {
imgTmp.style.objectFit = 'fill'; // 允许拉伸填充
imgTmp.style.width = `${this.initialRect.width - (currentX - this.mouseStartX)}px`;
imgTmp.style.height = `${this.initialRect.height + (currentY - this.mouseStartY)}px`;
this.imgPosition.x = this.initialRect.left + (currentX - this.mouseStartX);
}
}
else if (this.handleIndex === this.SelectHandle.TopRight) {
let imgTmp = this.$refs.image;
if (imgTmp && this.imgVisible) {
imgTmp.style.objectFit = 'fill'; // 允许拉伸填充
imgTmp.style.width = `${this.initialRect.width + (currentX - this.mouseStartX)}px`;
imgTmp.style.height = `${this.initialRect.height - (currentY - this.mouseStartY)}px`;
this.imgPosition.y = this.initialRect.top + (currentY - this.mouseStartY);
}
}
else if (this.handleIndex === this.SelectHandle.TopLeft) {
let imgTmp = this.$refs.image;
if (imgTmp && this.imgVisible) {
imgTmp.style.objectFit = 'fill'; // 允许拉伸填充
imgTmp.style.width = `${this.initialRect.width - (currentX - this.mouseStartX)}px`;
imgTmp.style.height = `${this.initialRect.height - (currentY - this.mouseStartY)}px`;
this.imgPosition.x = this.initialRect.left + (currentX - this.mouseStartX);
this.imgPosition.y = this.initialRect.top + (currentY - this.mouseStartY);
}
}
else if (this.handleIndex === this.SelectHandle.Body) {
// 拖动
let offsetX = event.offsetX - this.lastX;
let offsetY = event.offsetY - this.lastY;
if (Math.abs(offsetX) > 0 || Math.abs(offsetY) > 0) {
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 });
},
/** 刷新 */
drawRefresh() {
this.sendMessage("Refresh", { width: this.viewSize.width, height: this.viewSize.height });
},
/** 居中 */
drawCenter() {
this.sendMessage("Center", { 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 {
console.log("重新绘制图片数据:", data);
const response = await fetch(data, { cache: 'no-store' });
//const response = await fetch(data, { cache: '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.Default;
},
toolViewMove() {
this.drawerToolType = canvasToolType.ViewPan;
},
toolViewWindow() {
this.drawerToolType = canvasToolType.ViewWindow;
},
toolSelect() {
this.drawerToolType = canvasToolType.Select;
this.toolSwitch(this.drawerToolType);
},
// 工具切换
toolSwitch(newToolType) {
this.sendMessage("SwitchToolType", { toolType: newToolType });
},
GetCursor() {
if (this.drawerToolType === canvasToolType.Select) {
if (this.handleIndex === this.SelectHandle.Body || this.handleIndex === this.SelectHandle.Center) {
return MouseIcons.move;
}
else if (this.handleIndex === this.SelectHandle.TopLeft || this.handleIndex === this.SelectHandle.BottomRight) {
return MouseIcons.resizenw;
}
else if (this.handleIndex === this.SelectHandle.TopRight || this.handleIndex === this.SelectHandle.BottomLeft) {
return MouseIcons.resizene;
}
else if (this.handleIndex === this.SelectHandle.Left || this.handleIndex === this.SelectHandle.Right) {
return MouseIcons.resizee;
}
else if (this.handleIndex === this.SelectHandle.Top || this.handleIndex === this.SelectHandle.Bottom) {
return MouseIcons.resizen;
}
else {
return MouseIcons.pointerSelect;
}
} else if (this.drawerToolType == canvasToolType.ViewPan) {
return MouseIcons.viewPan;
}
else if (this.drawerToolType == canvasToolType.ViewWindow) {
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.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 === "refresh") {
this.redraw();
}
if (event.data.action === "center") {
this.redraw();
}
}.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', ParentId: 0, Name: "随意拖拽 1", open: true, children: [] },
{ Id: 11, ParentId: 'aa', Name: "随意拖拽 1-1", children: [] },
{ Id: 12, ParentId: 'aa', Name: "随意拖拽 1-2", open: true, children: [] },
/* { 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, ParentId: 2, Name: "随意拖拽 2-3", children: [] }
];
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>