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.

497 lines
15 KiB
TypeScript

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.

/**
* @交互说明
* 1. 初始化选中目标的设备对象 【设备名称、使用图标】
*/
// https://t7.baidu.com/it/u=2757924858,1404466263&fm=193
import video_type_1 from "@/assets/modelSetting/video_type_1.png";
import video_type_2 from "@/assets/modelSetting/video_type_2.png";
import video_type_3 from "@/assets/modelSetting/video_type_3.png";
import device_video_bg from "@/assets/modelSetting/device_video_bg.png";
import device_video_bg_gray from "@/assets/modelSetting/device_video_bg_gray.png";
import notInVisableIcon from "@/assets/modelSetting/notInVisableIcon.png";
import { workspaceIDConf } from "@/config/attribute/viewType";
import { v4 as uuid } from "uuid";
const deviceInfoKey = "deviceInfo";
// TODO 设计实现点位绑定设备实体的位置偏移问题
/**
* @交互说明
* 1. 基于画布中心点建立坐标系。画布中心点坐标为(0,0)
*/
export const useDeviceObject = () => {
// 拖拽新增获取设备对象在画布上的坐标
function getDragDeviceObjectOrdinate(event, viewObj, deviceObj) {
// 移动到画布上的设备对象的相对坐标,使用相对图片的坐标系,而不是画布的坐标系
const currWorkSpaceData = document
.getElementById(workspaceIDConf)
.getBoundingClientRect();
const cvsObjects = viewObj.getObjects()[0]; // 获取画布对象
const imgObjects = viewObj.getObjects()[1]; // 获取图片对象
const { left, top, width, height } = currWorkSpaceData;
// .getSelectionElement()
// .getBoundingClientRect();
// 该设备基于当前画布的坐标信息
const currPointView = {
x: event.clientX - left,
y: event.clientY - top
};
// const pointerVpt = viewObj.restorePointerVpt(currPointView);
const x_ordinate =
currPointView.x - width / 2 - (deviceObj.width * deviceObj.scaleX) / 2;
const y_ordinate =
height / 2 - currPointView.y + (deviceObj.height * deviceObj.scaleY) / 2;
console.log(
"currWorkSpace:",
currWorkSpaceData,
"cvsObjects:",
cvsObjects,
"event:",
event,
"getDragDeviceObjectOrdinate",
"imgObjects:",
imgObjects.getCenterPoint(),
x_ordinate,
y_ordinate
);
return {
x_ordinate,
y_ordinate
};
}
// 在画布上移动后设备对象坐标
function fetchMoveDeviceObjectOrdinate(viewObj, activeObject) {
const cvsObjects = viewObj.getObjects()[0]; // 获取画布对象
const x_ordinate = activeObject.get("left") - cvsObjects.width / 2;
const y_ordinate = cvsObjects.height / 2 - activeObject.get("top");
return {
x_ordinate,
y_ordinate
};
}
// 使用相对坐标换实际位置的方法
function fetchOrdinateByView(viewObj, deviceItem) {
const cvsObjects = viewObj.getObjects()[0]; // 获取画布对象
const { x_ordinate, y_ordinate } = deviceItem;
const left = cvsObjects.width / 2 + parseFloat(x_ordinate);
const top = cvsObjects.height / 2 - parseFloat(y_ordinate);
console.log(cvsObjects, "fetchOrdinateByView", left, top);
return {
left,
top
};
}
// 可操作区域的各点位相对坐标【限定可操作区域边界】
function fetchViewsBoundaries(viewObj, activeObj) {
// 图片原点为中心图标
const cvsObjects = viewObj.getObjects()[0]; // 获取画布对象
const imgObjects = viewObj.getObjects()[1]; // 获取图片对象
const y_mistake = -8 * activeObj?.scaleY; // 上下边界误差
const currIconWidth = activeObj?.width * activeObj?.scaleX;
const currIconHeight = activeObj?.height * activeObj?.scaleY;
const startLeft =
(cvsObjects.width * cvsObjects.scaleX -
imgObjects.width * imgObjects.scaleX) /
2 -
currIconWidth / 2;
const startTop =
(cvsObjects.height * cvsObjects.scaleY -
imgObjects.height * imgObjects.scaleY) /
2 -
currIconHeight -
y_mistake;
const endLeft = startLeft + imgObjects.width * imgObjects.scaleX;
const endTop = startTop + imgObjects.height * imgObjects.scaleY;
const currImgWidth = imgObjects.width * imgObjects.scaleX;
const currImgHeight = imgObjects.height * imgObjects.scaleY;
return {
x_min: -currImgWidth / 2 - currIconWidth / 2,
y_min: -currImgHeight / 2 - currIconHeight,
x_max: currImgWidth / 2 + currIconWidth / 2,
y_max: currImgHeight / 2,
startLeft,
startTop,
endLeft,
endTop
};
}
// 操作区判断设备是否在可视区域内
function isInViewBoundaries(viewObj, deviceObj): boolean {
const { x_min, x_max, y_min, y_max } = fetchViewsBoundaries(
viewObj,
deviceObj
);
const { x_ordinate, y_ordinate } = deviceObj;
// 限制对象在画布内移动
if (x_ordinate < x_min) {
return false;
}
if (y_ordinate < y_min) {
return false;
}
if (x_ordinate > x_max) {
return false;
}
if (y_ordinate > y_max) {
return false;
}
return true;
}
// 预览判断当前的图片图层内
function isInCurrViewBoundaries(viewObj, deviceObj): boolean {
const objLeft = deviceObj.left;
const objTop = deviceObj.top;
const canvasObject = viewObj;
const { backgroundImage } = canvasObject; // backgroundImage 背景图片
const currIconWidth = deviceObj?.width * deviceObj?.scaleX;
const currIconHeight = deviceObj?.height * deviceObj?.scaleY;
const y_mistake = -8 * deviceObj?.scaleY; // 上下边界误差
const x_mistake = 1; // 左右边界误差
const startLeft =
(canvasObject.width - backgroundImage.width * backgroundImage.scaleX) /
2 -
currIconWidth / 2;
const startTop =
(canvasObject.height - backgroundImage.height * backgroundImage.scaleY) /
2 -
currIconHeight -
y_mistake;
const endLeft = startLeft + backgroundImage.width * backgroundImage.scaleX;
const endTop = startTop + backgroundImage.height * backgroundImage.scaleY;
console.log(
backgroundImage.getBoundingClientRect(),
canvasObject.width,
canvasObject.scaleX,
backgroundImage.width,
backgroundImage.scaleX,
currIconWidth,
"isInCurrViewBoundaries",
backgroundImage.scaleX,
deviceObj,
"startLeft",
startLeft,
"startTop",
startTop,
"endLeft",
endLeft,
"endTop",
endTop
);
if (
objLeft < startLeft - x_mistake ||
objTop < startTop ||
objLeft > endLeft + x_mistake ||
objTop > endTop
) {
return true;
}
return false;
}
// function isInView() {
// // TODO 用三角函数判断
// return;
// }
// 设备对象是否移动
function isMoveDevice(activeObject, viewObj) {
const x_ordinate_history = activeObject.get(deviceInfoKey)?.x_ordinate;
const y_ordinate_history = activeObject.get(deviceInfoKey)?.y_ordinate;
const { x_ordinate, y_ordinate } = fetchMoveDeviceObjectOrdinate(
viewObj,
activeObject
);
// 误差设置为 0.1
const errorValue = [1, 1];
let x_move = true;
let y_move = true;
const x_move_value = Math.abs(
Number(x_ordinate_history) - Number(x_ordinate)
);
const y_move_value = Math.abs(
Number(y_ordinate_history) - Number(y_ordinate)
);
// 重新绑定车间的设备没有坐标信息,暂时不判断设备是否移动【默认没有移动】
// if (Number.isNaN(x_move_value) || Number.isNaN(y_move_value)) {
// return false;
// }
if (x_move_value < errorValue[0]) {
x_move = false;
}
if (y_move_value < errorValue[1]) {
y_move = false;
}
console.log(
"isMoveDevice:" + (x_move || y_move),
"x_move_value" + x_move_value,
"y_move_value" + y_move_value
);
return x_move || y_move;
}
// 初始化设备对象
const initDeviceGroupObjects: Record<string, any> = (
record,
restDeviceItem = {}
) => {
console.log(record, "initDeviceGroupObjects");
// const { value } = record;
let iconObjectSrc = video_type_1;
switch (record?.icon) {
case "3":
iconObjectSrc = video_type_3;
break;
case "2":
iconObjectSrc = video_type_2;
break;
case "1":
default:
iconObjectSrc = video_type_1;
break;
}
let bgDeviceImage;
const fontStyle = { fill: "#333333" };
// 不在可视区域内的设备
if (record?.notInVisable) {
bgDeviceImage = device_video_bg_gray;
fontStyle.fill = "gray";
} else {
bgDeviceImage = device_video_bg;
}
return {
name: "device",
id: uuid(),
deviceInfo: record, // 设备信息
left: record?.left ? Number(record?.left) : 0,
top: record?.top ? Number(record?.top) : 0,
selectable: true,
hasControls: true,
lockUniScaling: true, // 当设置为trueObject将无法被锁定比例进行缩放。默认值为false。
lockScalingX: true, // 当设置为trueObject水平方向将无法被缩放。默认值为false。
lockScalingY: true, // 当设置为trueObject垂直方向将无法被缩放。默认值为false。
lockRotation: true, // 当设置为trueObject的旋转将被锁定。默认值为false。
type: "group",
version: "5.3.0",
originX: "left",
originY: "top",
width: 132,
height: 62,
fill: "rgb(0,0,0)",
stroke: null,
strokeWidth: 0,
strokeDashArray: null,
strokeLineCap: "butt",
strokeDashOffset: 0,
strokeLineJoin: "miter",
strokeUniform: false,
strokeMiterLimit: 4,
scaleX: 1,
scaleY: 1,
angle: 0,
flipX: false,
flipY: false,
opacity: 1,
shadow: null,
visible: true,
backgroundColor: "",
fillRule: "nonzero",
paintFirst: "fill",
globalCompositeOperation: "source-over",
skewX: 0,
skewY: 0,
objects: [
{
type: "image",
version: "5.3.0",
originX: "left",
originY: "top",
left: -66,
top: -33,
width: 264,
height: 132,
fill: "rgb(0,0,0)",
stroke: null,
strokeWidth: 0,
strokeDashArray: null,
strokeLineCap: "butt",
strokeDashOffset: 0,
strokeLineJoin: "miter",
strokeUniform: false,
strokeMiterLimit: 4,
scaleX: 0.5,
scaleY: 0.5,
angle: 0,
flipX: false,
flipY: false,
opacity: 1,
shadow: null,
visible: true,
backgroundColor: "",
fillRule: "nonzero",
paintFirst: "fill",
globalCompositeOperation: "source-over",
skewX: 0,
skewY: 0,
cropX: 0,
cropY: 0,
selectable: false,
hasControls: false,
src: bgDeviceImage,
crossOrigin: null,
filters: []
},
{
type: "image",
version: "5.3.0",
originX: "left",
originY: "top",
left: -50.6281,
top: -22.9893,
width: 48,
height: 48,
fill: "rgb(0,0,0)",
stroke: null,
strokeWidth: 0,
strokeDashArray: null,
strokeLineCap: "butt",
strokeDashOffset: 0,
strokeLineJoin: "miter",
strokeUniform: false,
strokeMiterLimit: 4,
scaleX: 0.6174,
scaleY: 0.6174,
angle: 0,
flipX: false,
flipY: false,
opacity: 1,
shadow: null,
visible: true,
backgroundColor: "",
fillRule: "nonzero",
paintFirst: "fill",
globalCompositeOperation: "source-over",
skewX: 0,
skewY: 0,
cropX: 0,
cropY: 0,
selectable: false,
hasControls: false,
src: iconObjectSrc,
crossOrigin: null,
filters: []
},
{
type: "textbox",
version: "5.3.0",
originX: "left",
originY: "top",
left: -14.3377,
top: -15.4904,
width: 320,
height: 90.4,
fill: fontStyle.fill,
stroke: null,
strokeWidth: 1,
strokeDashArray: null,
strokeLineCap: "butt",
strokeDashOffset: 0,
strokeLineJoin: "miter",
strokeUniform: false,
strokeMiterLimit: 4,
scaleX: 0.1681,
scaleY: 0.1681,
angle: 0,
flipX: false,
flipY: false,
opacity: 1,
shadow: "",
visible: true,
backgroundColor: "",
fillRule: "nonzero",
paintFirst: "fill",
globalCompositeOperation: "source-over",
skewX: 0,
skewY: 0,
fontFamily: "arial",
fontWeight: "normal",
fontSize: 80,
text: record?.name,
underline: false,
overline: false,
linethrough: false,
textAlign: "left",
fontStyle: "normal",
lineHeight: 1.16,
textBackgroundColor: "",
charSpacing: 0,
styles: [],
direction: "ltr",
path: null,
pathStartOffset: 0,
pathSide: "left",
pathAlign: "baseline",
selectable: false,
hasControls: false
},
{
type: "image",
version: "5.3.0",
originX: "left",
originY: "top",
left: -47.6281,
top: -19.9893,
width: 40,
height: 40,
fill: "rgb(0,0,0)",
stroke: null,
strokeWidth: 0,
strokeDashArray: null,
strokeLineCap: "butt",
strokeDashOffset: 0,
strokeLineJoin: "miter",
strokeUniform: false,
strokeMiterLimit: 4,
scaleX: 0.6174,
scaleY: 0.6174,
angle: 0,
flipX: false,
flipY: false,
opacity: 1,
shadow: null,
visible: false,
backgroundColor: "",
fillRule: "nonzero",
paintFirst: "fill",
globalCompositeOperation: "source-over",
skewX: 0,
skewY: 0,
cropX: 0,
cropY: 0,
selectable: false,
hasControls: false,
src: notInVisableIcon,
crossOrigin: null,
filters: []
}
],
...restDeviceItem
};
};
return {
initDeviceGroupObjects,
isInViewBoundaries,
getDragDeviceObjectOrdinate,
isMoveDevice,
fetchViewsBoundaries,
fetchOrdinateByView,
fetchMoveDeviceObjectOrdinate,
isInCurrViewBoundaries
};
};