| | |
| | | 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 |
| | |
| | | _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); |
| | |
| | | }, |
| | | canvasTouchStart(e) { |
| | | const _this = this |
| | | _this.pointerSelectObject(e) |
| | | // _this.pointerSelectObject(e) |
| | | if (!_this.canvas.getActiveObject()) { |
| | | // 根据触摸点数量判断交互类型 |
| | | if (e.touches.length === 1) { |
| | |
| | | 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]; |
| | | |
| | |
| | | } |
| | | }, |
| | | clearObjects() { |
| | | |
| | | |
| | | if (!this.canvas) return; |
| | | this.canvas.discardActiveObject() |
| | | const objects = this.canvas.getObjects() |
| | |
| | | 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 |
| | | }) |
| | |
| | | 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({ |
| | |
| | | }) |
| | | tipObj.setCoords() |
| | | } |
| | | } |
| | | if (obj.eleType == "cmd") { |
| | | } else if (obj.eleType == "cmd") { |
| | | const obj2 = obj.mainObj |
| | | if (obj2?.eleType == "station") { |
| | | if (obj.id == `cancel`) { |
| | |
| | | pos_list.push(item) |
| | | } |
| | | }) |
| | | let teachingGroup = [] |
| | | let path2 = "" |
| | | |
| | | const theta = 20; |
| | | let pathArrow = "" |
| | | const theta = 30; |
| | | let headlen = 10; |
| | | var main_road = teachingData.main_road |
| | | 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") { |
| | | const offset = index % 50 |
| | | if (offset > 20 && offset < 41) { |
| | | if (offset == 21) { |
| | | |
| | | 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; |
| | | |
| | | 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 { |
| | | 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 = 1.5 |
| | | let strokeWidth = 8 |
| | | let stroke = "#69C0FF" |
| | | if (type == "station_teaching") { |
| | | stroke = "#69C0FF" |
| | | stroke = "#69C0FF80" |
| | | } else { |
| | | if (main_road == 1) { |
| | | //stroke = "#69C0FF" |
| | | if (teachingData.bidirection == 1) { |
| | | stroke = "#ffaa00" |
| | | stroke = "#ffaa0080" |
| | | } |
| | | strokeWidth = 3 |
| | | strokeWidth = 12 |
| | | |
| | | } else { |
| | | strokeWidth = 8 |
| | | if (teachingData.bidirection == 1) { |
| | | stroke = "#FF00FF" |
| | | stroke = "#FF00FF80" |
| | | } |
| | | } |
| | | } |
| | |
| | | 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, |
| | |
| | | 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 |
| | | }) |
| | |
| | | y: this.getYOnImg(param.y) |
| | | } |
| | | if (this.objAgvLaser) { |
| | | this.objAgvLaser.set({stroke: "#00ff00", rx: 2, |
| | | ry:2}) |
| | | this.objAgvLaser.set({ |
| | | stroke: "#00ff00", |
| | | rx: 2, |
| | | ry: 2 |
| | | }) |
| | | } |
| | | let ellipse = new fabric.Ellipse({ |
| | | id: "agv_laser", |
| | |
| | | selectable: false, |
| | | hasControls: false, |
| | | }); |
| | | |
| | | |
| | | this.objAgvLaserLine = line |
| | | this.canvas.add(line) |
| | | }, |
| | |
| | | originX: "center", |
| | | originY: "center", |
| | | }); |
| | | |
| | | |
| | | objs.push(ellipse) |
| | | if (left > pt2.x-2) { |
| | | left = pt2.x-2 |
| | | if (left > pt2.x - 2) { |
| | | left = pt2.x - 2 |
| | | } |
| | | if (top > pt2.y-2) { |
| | | top = pt2.y-2 |
| | | if (top > pt2.y - 2) { |
| | | top = pt2.y - 2 |
| | | } |
| | | if (right < pt2.x + 2) { |
| | | right = pt2.x + 2 |
| | |
| | | const curIndex = list.findIndex((a) => a.id == id) |
| | | if (curIndex > -1) { |
| | | const obj = list[curIndex] |
| | | |
| | | |
| | | |
| | | let strokeWidth = 1.5 |
| | | let stroke = "#69C0FF" |
| | | |
| | |
| | | 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) |
| | |
| | | |
| | | 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 |