/** * @交互说明 * 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, // 当设置为true,Object将无法被锁定比例进行缩放。默认值为false。 lockScalingX: true, // 当设置为true,Object水平方向将无法被缩放。默认值为false。 lockScalingY: true, // 当设置为true,Object垂直方向将无法被缩放。默认值为false。 lockRotation: true, // 当设置为true,Object的旋转将被锁定。默认值为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 }; };