cuiqian2004
4 天以前 2af5f043b60c1f7ac38ecccc8f5bf44743134325
pages/map/js/ctx.js
@@ -115,14 +115,26 @@
               stopContextMenu: true, // 禁止长按菜单
               fireRightClick: true,
               fireMiddleClick: true,
               targetFindTolerance: 10, // 增大触摸容差
               isTouchSupported: true,
               enableRetinaScaling: true,
               renderOnAddRemove: false,
               imageSmoothingEnabled: true
               imageSmoothingEnabled: true,
               perPixelTargetFind: true, // 点击图形自身才选中
               targetFindTolerance: 5 // 增大触摸容差
            })
            const originalShouldClearSelection = this.canvas._shouldClearSelection;
            // 重写方法
            this.canvas._shouldClearSelection = function(e) {
               // 只有当点击在对象上,并且是我们期望的条件(如边框)时,才执行默认的清除逻辑
               // 点击空白处直接返回 false,不清除选择
               if (e.target && e.subTargets) {
                  // 这里可以添加更精细的判断,例如结合后面的边框判断
                  return originalShouldClearSelection.call(this, e);
               }
               return false;
            };
            this.canvas.clear()
            this.eleWidth = cantainerEl.clientWidth
            this.eleHeight = cantainerEl.clientHeight
@@ -445,7 +457,24 @@
            _this.onOjectMoving(e.target)
         });
         _this.canvas.on("mouse:down", function(opt) {
            console.log("mouse:down", opt);
            // 如果点击的是空白处(没有目标对象)
            if (!opt.target) {
               // 取消当前选中
               _this.canvas.discardActiveObject();
               // 重新渲染画布
               _this.canvas.renderAll();
            } else {
               if (!opt.target.selectable) {
                  _this.canvas.discardActiveObject();
                  // 重新渲染画布
                  _this.canvas.renderAll();
               }
               console.log("mouse:down", opt.target.eleType);
            }
         });
         cantainerEl.addEventListener('touchstart', function(e) {
            //      console.log('touchstart:', e.touches.length);
@@ -508,7 +537,7 @@
      },
      canvasTouchStart(e) {
         const _this = this
         _this.pointerSelectObject(e)
         //   _this.pointerSelectObject(e)
         if (!_this.canvas.getActiveObject()) {
            // 根据触摸点数量判断交互类型
            if (e.touches.length === 1) {
@@ -791,6 +820,33 @@
         const objActive = this.canvas.getActiveObject()
         let pointerList = []
         let pointerList2 = []
         return
         if (objActive instanceof fabric.Group) {
            const ptr = pointer
            // 计算相对于 Group 的本地坐标
            const localX = ptr.x - objActive.left;
            const localY = ptr.y - objActive.top;
            // 判断这个本地坐标是否“真的”点中了某个子对象
            let hit = false;
            objActive._objects.forEach((obj) => {
               if (obj.selectable) {
                  if (this.isPointOnStroke(obj, pointer, 8)) {
                     hit = true;
                  }
               }
            });
            console.log(hit)
            // 如果已经选中,但这一次没点中任何子对象 → 取消选中
            if (!hit) {
               this.canvas.discardActiveObject();
               this.canvas.requestRenderAll();
            }
         }
         for (let i = objects.length - 1; i >= 0; i--) {
            const obj = objects[i];
@@ -1268,6 +1324,7 @@
         }
      },
      clearObjects() {
         if (!this.canvas) return;
         this.canvas.discardActiveObject()
         const objects = this.canvas.getObjects()
@@ -1283,6 +1340,8 @@
         this.objEditing = null;
         this.editObject = null;
         this.drawingObj = null;
         this.objAgvLaser = null
         this.objAgvLaserLine = null
         if (this.pressObjTimer) {
            clearTimeout(this.pressObjTimer);
            this.pressObjTimer = null;
@@ -1859,12 +1918,20 @@
         const scale2 = 1 / scale
         let list = this.canvas.getObjects()
         const filter = ["agv", "current_teaching", "edit_teaching", "edit_teaching_pt", "cmd", "station",
         const filter = ["agv", "public_teaching", "current_teaching", "edit_teaching", "edit_teaching_pt", "cmd",
            "station",
            "station_mark", "station_tip"
         ]
         list = list.filter((a) => filter.includes(a.eleType))
         list.forEach((obj) => {
            if (obj.eleType == "edit_teaching") {
            if (obj.eleType == "public_teaching") {
               // const subObjs = obj.getObjects()
               // subObjs.forEach((obj2) => {
               //    obj2.set({
               //       strokeWidth: obj2.strokeOriginWidth * scale2
               //    })
               // })
            } else if (obj.eleType == "edit_teaching") {
               obj.set({
                  strokeWidth: 2 * scale2
               })
@@ -1874,7 +1941,7 @@
                  scaleY: scale2
               })
            }
            if (obj.eleType == "station" || obj.eleType == "edit_teaching") {
             if (obj.eleType == "station" || obj.eleType == "edit_teaching") {
               const tipObj = obj.tipObj
               if (tipObj) {
                  tipObj.set({
@@ -1884,8 +1951,7 @@
                  })
                  tipObj.setCoords()
               }
            }
            if (obj.eleType == "cmd") {
            } else if (obj.eleType == "cmd") {
               const obj2 = obj.mainObj
               if (obj2?.eleType == "station") {
                  if (obj.id == `cancel`) {
@@ -2063,9 +2129,6 @@
            }
         })
         let path2 = ""
         const theta = 20;
         let headlen = 10;
         var main_road = teachingData.main_road || 0
         const len = pos_list.length
         let fromX = 0,
@@ -2079,33 +2142,7 @@
               y: this.getYOnImg(pt.y)
            }
            if (index > 0) {
               // if ((index % 50 == 0 || index == len - 1 || index % 50 == 1)) {
               //    if (index % 50 == 0 || index == len - 1) {
               //       toX = pt2.x
               //       toY = pt2.y
               //       path2 += ` L${pt2.x} ${pt2.y}`
               //       // 计算各角度和对应的P2,P3坐标
               //       let angle = (Math.atan2(fromY - toY, fromX - toX) * 180) / Math.PI,
               //          angle1 = ((angle + theta) * Math.PI) / 180,
               //          angle2 = ((angle - theta) * Math.PI) / 180,
               //          topX = headlen * Math.cos(angle1),
               //          topY = headlen * Math.sin(angle1),
               //          botX = headlen * Math.cos(angle2),
               //          botY = headlen * Math.sin(angle2);
               //       let arrowX = fromX - topX,
               //          arrowY = fromY - topY;
               //       arrowX = toX + topX;
               //       arrowY = toY + topY;
               //       path2 += " L " + arrowX + " " + arrowY;
               //       arrowX = toX + botX;
               //       arrowY = toY + botY;
               //       path2 += " M " + arrowX + " " + arrowY;
               //       path2 += " L " + toX + " " + toY;
               //    }
               // } else {
               //    path2 += ` L${pt2.x} ${pt2.y}`
               // }
               path2 += ` L${pt2.x} ${pt2.y}`
            } else {
               path2 = `M${pt2.x} ${pt2.y}`
@@ -2114,11 +2151,9 @@
            fromY = pt2.y
         }
         let strokeWidth = 5
         let stroke = "#95DE64"
         let stroke = "#69C0FF"
         if (main_road == 1) {
            stroke = "#69C0FF"
         }
         const objPath = new fabric.Path(
            path2, {
               id: "current_teaching",
@@ -2150,124 +2185,130 @@
               pos_list.push(item)
            }
         })
         let teachingGroup = []
         let path2 = ""
         const theta = 20;
         let pathArrow = ""
         const theta = 30;
         let headlen = 10;
         var main_road = 1
         var main_road = teachingData.main_road
         const len = pos_list.length
         let fromX = 0,
            fromY = 0,
            toX = 0,
            toY = 0;
         let right = 0
         let bottom = 0
         let left = this.mapInfo.img_x
         let top = this.mapInfo.img_y
         var scale = this.canvas.getZoom()
         if (scale < 1) {
            scale = 1
         }
         const scale2 = 1 / scale
         for (let index = 0; index < len; index++) {
            const pt = pos_list[index]
            let pt2 = {
               x: this.getXOnImg(pt.x),
               y: this.getYOnImg(pt.y)
            }
            if (fromX == pt2.x && fromY == pt2.y) {
               pos_list.splice(index, 1)
               index--;
               continue;
            }
            if (index > 0) {
               // if ((type == "public_teaching") && (index % 50 == 0 || index == len - 1 || index % 50 == 1)) {
               //    if (index % 50 == 1 || index == len - 1) {
               //       if (teachingData.bidirection == 1 && index < len - 1) { //- 1
               //          toY = fromY
               //          toX = fromX
               //          fromX = pt2.x
               //          fromY = pt2.y
               //          let angle = (Math.atan2(fromY - toY, fromX - toX) * 180) / Math.PI,
               //             angle1 = ((angle + theta) * Math.PI) / 180,
               //             angle2 = ((angle - theta) * Math.PI) / 180,
               //             topX = headlen * Math.cos(angle1),
               //             topY = headlen * Math.sin(angle1),
               //             botX = headlen * Math.cos(angle2),
               //             botY = headlen * Math.sin(angle2);
               //          let arrowX = fromX - topX,
               //             arrowY = fromY - topY;
               //          arrowX = toX + topX;
               //          arrowY = toY + topY;
               //          let path3 = " L " + arrowX + " " + arrowY;
               //          arrowX = toX + botX;
               //          arrowY = toY + botY;
               //          path3 += " M " + arrowX + " " + arrowY;
               //          path3 += " L " + toX + " " + toY;
               if (type == "public_teaching") {
                  const offset = index % 50
                  if (offset > 20 && offset < 41) {
                     if (offset == 21) {
               //          path2 += path3
               //          fromY = toY
               //          fromX = toX
               //       }
               //    }
               //    if (index % 50 == 0 || index == len - 1) {
               //       toX = pt2.x
               //       toY = pt2.y
               //       // if (fromX == toX && fromY == toY) {
               //       //    if (index - 2 >= 0) {
               //       //       const pt3 = pos_list[index - 2]
               //       //       fromX = this.getXOnImg(pt3.x),
               //       //          fromY = this.getYOnImg(pt3.y)
               //       //    } else {
               //       //       continue;
               //       //    }
               //       // }
               //       path2 += ` L${pt2.x} ${pt2.y}`
                        pathArrow = `M${pt2.x} ${pt2.y}`
                     } else
                        pathArrow += ` L${pt2.x} ${pt2.y}`
                     if (offset == 40) {
                        const pt = pos_list[index - 2]
                        fromX = this.getXOnImg(pt.x)
                        fromY = this.getYOnImg(pt.y)
                        //   console.log(fromX,fromY, this.getXOnImg(pt.x),this.getYOnImg(pt.y))
                        toX = pt2.x
                        toY = pt2.y
                        let angle = (Math.atan2(fromY - toY, fromX - toX) * 180) / Math.PI,
                           angle1 = ((angle + theta) * Math.PI) / 180,
                           angle2 = ((angle - theta) * Math.PI) / 180,
                           topX = headlen * Math.cos(angle1),
                           topY = headlen * Math.sin(angle1),
                           botX = headlen * Math.cos(angle2),
                           botY = headlen * Math.sin(angle2);
                        let arrowX = fromX - topX,
                           arrowY = fromY - topY;
                        arrowX = toX + topX;
                        arrowY = toY + topY;
                        pathArrow += " M " + arrowX + " " + arrowY;
                        pathArrow += " L " + toX + " " + toY;
                        arrowX = toX + botX;
                        arrowY = toY + botY;
                        pathArrow += " L " + arrowX + " " + arrowY;
               //       // 计算各角度和对应的P2,P3坐标
               //       let angle = (Math.atan2(fromY - toY, fromX - toX) * 180) / Math.PI,
               //          angle1 = ((angle + theta) * Math.PI) / 180,
               //          angle2 = ((angle - theta) * Math.PI) / 180,
               //          topX = headlen * Math.cos(angle1),
               //          topY = headlen * Math.sin(angle1),
               //          botX = headlen * Math.cos(angle2),
               //          botY = headlen * Math.sin(angle2);
               //       let arrowX = fromX - topX,
               //          arrowY = fromY - topY;
               //       arrowX = toX + topX;
               //       arrowY = toY + topY;
               //       path2 += " L " + arrowX + " " + arrowY;
               //       arrowX = toX + botX;
               //       arrowY = toY + botY;
               //       path2 += " M " + arrowX + " " + arrowY;
               //       path2 += " L " + toX + " " + toY;
               //    }
               //    //   console.log(`箭头 L${pt2.x} ${pt2.y}`)
               // } else {
               //    //   console.log(`点 L${pt2.x} ${pt2.y} ${index} == ${len-1}`)
               //    path2 += ` L${pt2.x} ${pt2.y}`
               // }
                        const objArrow = new fabric.Path(
                           pathArrow, {
                              stroke: "#fff",
                              strokeWidth:2,// * scale2,
                              strokeOriginWidth:2,
                              fill: "#ffffff00",
                              selectable: false,
                           })
                        teachingGroup.push(objArrow)
                     }
                  }
               }
               path2 += ` L${pt2.x} ${pt2.y}`
            } else {
               main_road = pt.main_road
               if (main_road == 1) {
                  headlen = 15
               }
               if (main_road === undefined)
                  main_road = pt.main_road
               path2 = `M${pt2.x} ${pt2.y}`
            }
            // if (left > pt2.x) {
            //    left = pt2.x
            // }
            // if (top > pt2.y) {
            //    top = pt2.y
            // }
            // if (right < pt2.x) {
            //    right = pt2.x
            // }
            // if (bottom < pt2.y) {
            //    bottom = pt2.y
            // }
            fromX = pt2.x
            fromY = pt2.y
         }
         // console.log("addTeachingPath",path2)
         // path2 += " Z"
         let strokeWidth = 2
         let stroke = "#95DE64"
         let strokeWidth = 8
         let stroke = "#69C0FF"
         if (type == "station_teaching") {
            stroke = "#69C0FF"
            stroke = "#69C0FF80"
         } else {
            if (main_road == 1) {
               stroke = "#69C0FF"
               //stroke = "#69C0FF"
               if (teachingData.bidirection == 1) {
                  stroke = "#FF00FF"
                  stroke = "#ffaa0080"
               }
               strokeWidth = 12
            } else {
               strokeWidth = 8
               if (teachingData.bidirection == 1) {
                  stroke = "#ffaa00"
                  stroke = "#FF00FF80"
               }
            }
         }
         teachingData.main_road = main_road
         let list = this.canvas.getObjects() || []
         list = list.filter((a) => a.eleType == "station_teaching" || a.eleType == "public_teaching")
         let lenTeaching = list.length
@@ -2276,15 +2317,29 @@
            lenTeaching = list.length
         }
         let ptList = []
         const objPath = new fabric.Path(
         const obj = new fabric.Path(
            path2, {
               id: id,
               eleType: type,
               stroke: stroke,
               strokeWidth,
               strokeWidth:strokeWidth,// * scale2,
               strokeOriginWidth:strokeWidth,
               // strokeDashArray: [5, 3],
               // strokeLineCap: 'butt',
               // originX: "center",
               // originY: "center",
               selectable: true,
               fill: "#ffffff00",
            })
         // this.canvas.add(obj)
         teachingGroup.unshift(obj)
         const objPath = new fabric.Group(
            teachingGroup, {
               id: id,
               eleType: type,
               // stroke: stroke,
               // strokeWidth,
               fill: "#ffffff00",
               hasControls: false,
               lockRotation: true,
@@ -2292,7 +2347,12 @@
               lockScalingY: true,
               lockMovementX: true,
               lockMovementY: true,
               // perPixelTargetFind: true,
               // left: left - strokeWidth / 2,
               // top: top - strokeWidth / 2,
               // width: right - left + strokeWidth,
               // height: bottom - top + strokeWidth,
               mainRoad: main_road,
               data: teachingData
            })
@@ -2302,6 +2362,7 @@
         return objPath
      },
      isObjectFullyContained(outerObj, innerObj) {
         const outer = outerObj.getBoundingRect(true, true);
         const inner = innerObj.getBoundingRect(true, true);
@@ -2356,7 +2417,7 @@
         let id = ""
         if (teachingMode.mode == "Public") {
            eleType = "public_teaching"
            id = `public_teaching_${teachingMode.name}`
            id = `public_teaching_${teachingMode.name}_${teachingMode.edge_name}`
         } else if (teachingMode.mode == "Stations") {
            eleType = "station_teaching"
            id = `station_teaching_${teachingMode.src_dst}`
@@ -3079,48 +3140,100 @@
            x: this.getXOnImg(param.x),
            y: this.getYOnImg(param.y)
         }
         if (this.objAgvLaser) {
            this.objAgvLaser.set({
               stroke: "#00ff00",
               rx: 2,
               ry: 2
            })
         }
         let ellipse = new fabric.Ellipse({
            id: "agv_laser",
            eleType: "agv_laser",
            left: pt.x,
            top: pt.y,
            rx: 2,
            ry: 2,
            stroke: "#00aa00",
            rx: 3,
            ry: 3,
            stroke: "#ff0000",
            strokeWidth: 1,
            fill: "#00aa00",
            fill: "#00ff00",
            originX: "center",
            originY: "center",
            selectable: false,
            hasControls: true,
            lockRotation: true,
            lockScalingX: true,
            lockScalingY: true,
            lockMovementX: true,
            lockMovementY: true,
            hasControls: false,
         });
         this.canvas.add(ellipse)
         const offX = 20 * Math.cos(angle)
         const offY = 20 * Math.sin(angle)
         if (this.objAgvLaser) {
            this.canvas.remove(this.objAgvLaser)
         this.objAgvLaser = ellipse
         if (this.objAgvLaserLine) {
            this.canvas.remove(this.objAgvLaserLine)
         }
         const line = new fabric.Line([pt.x, pt.y, pt.x + offX,
            pt.y + offY
         ], {
            id: "agv_laser_angle",
            eleType: "agv_laser_angle",
            stroke: "#00aa00",
            stroke: "#00ff00",
            strokeWidth: 1,
            lockRotation: true,
            lockScalingX: true,
            lockScalingY: true,
            lockMovementX: true,
            lockMovementY: true,
            selectable: false,
            hasControls: false,
         });
         this.objAgvLaser = line
         this.objAgvLaserLine = line
         this.canvas.add(line)
      },
      addTrajectoryPoint(list) {
         const objs = []
         let right = 0
         let bottom = 0
         let left = this.mapInfo.img_x
         let top = this.mapInfo.img_y
         for (let i in list) {
            const pt = list[i]
            const pt2 = {
               x: this.getXOnImg(pt[0]),
               y: this.getYOnImg(pt[1])
            }
            let ellipse = new fabric.Ellipse({
               left: pt2.x,
               top: pt2.y,
               rx: 2,
               ry: 2,
               stroke: "#00ff00",
               strokeWidth: 1,
               fill: "#00ff00",
               originX: "center",
               originY: "center",
            });
            objs.push(ellipse)
            if (left > pt2.x - 2) {
               left = pt2.x - 2
            }
            if (top > pt2.y - 2) {
               top = pt2.y - 2
            }
            if (right < pt2.x + 2) {
               right = pt2.x + 2
            }
            if (bottom < pt2.y + 2) {
               bottom = pt2.y + 2
            }
         }
         const groupObj = new fabric.Group(objs, {
            id: `trajectory_point_group`,
            eleType: "trajectory_point_group",
            left,
            top,
            width: right - left,
            height: bottom - top,
            selectable: false,
            hasControls: true,
         })
         this.canvas.add(groupObj)
      },
      updateLaserPoint(param) {
@@ -3162,7 +3275,7 @@
               top: pt2.y,
               width: 1,
               height: 1,
               fill: "#F5222D",
               fill: "#ff00ff",
               originX: "left",
               originY: "top",
               // selectable: false,
@@ -3596,7 +3709,7 @@
                  const show = item.param?.show || false
                  for (let i2 in teachingPathList) {
                     const teachingPath = teachingPathList[i2]
                     const id = `public_teaching_${teachingPath.name}`
                     const id = `public_teaching_${teachingPath.name}_${teachingPath.edge_name}`
                     const obj = await this.addTeachingPath(teachingPath, id, "public_teaching",
                        show)
                     obj.set({
@@ -3627,7 +3740,7 @@
                  let list = _this.canvas.getObjects() || []
                  if (item.param.mode == "Public") {
                     list = list.filter((a) => a.eleType == "public_teaching")
                     const id = `public_teaching_${item.param.name}`
                     const id = `public_teaching_${item.param.name}_${item.param.edge_name}`
                     const curIndex = list.findIndex((a) => a.id == id)
                     if (curIndex > -1) {
@@ -3649,6 +3762,35 @@
                  const teachingMode = item.param
                  _this.showEditTeachingPath(teachingMode)
               } else if (item.method == "update_teaching") {
                  let list = _this.canvas.getObjects() || []
                  list = list.filter((a) => a.eleType == "public_teaching")
                  const id = `public_teaching_${item.param.name}_${item.param.edge_name}`
                  const curIndex = list.findIndex((a) => a.id == id)
                  if (curIndex > -1) {
                     const obj = list[curIndex]
                     let strokeWidth = 1.5
                     let stroke = "#69C0FF"
                     if (item.param.main_road == 1) {
                        //stroke = "#69C0FF"
                        if (item.param.bidirection == 1) {
                           stroke = "#ffaa00"
                        }
                        strokeWidth = 3
                     } else {
                        if (item.param.bidirection == 1) {
                           stroke = "#FF00FF"
                        }
                     }
                     obj.set({
                        strokeWidth,
                        stroke
                     })
                  }
               } else if (item.method == "set_selectable") {
                  if (item.param)
                     _this.setAllObjectSelectable(true)
@@ -3723,7 +3865,10 @@
                  this.updateAgvLaser(item.param || {})
               } else if (item.method == "point_cloud") {
                  this.updateLaserPoint(item.param || {})
               } else if (item.method == "point_trajectory") {
                  this.addTrajectoryPoint(item.param || [])
               }
            }
            if (_this.canvas)
               _this.canvas.renderAll()
@@ -3737,7 +3882,7 @@
         if (type == "string") {
            let tip = ex
            console.log(ex)
            plus.nativeUI.alert(tip, undefined, "错误");
            plus.nativeUI.alert(tip, undefined);
            return
         }
         let exStr = JSON.stringify(ex)
@@ -3746,7 +3891,7 @@
         let tip = typeof ex.msg == "string" ? ex.msg : exStr
         console.log(tip)
         plus.nativeUI.alert(tip, undefined, "错误");
         plus.nativeUI.alert(tip, undefined);
      },
      showToast(ex) {
         const type = typeof ex