瀏覽代碼

新增鹰眼模式

YaolongHan 4 年之前
父節點
當前提交
d5d2982f4d

+ 2 - 0
docs/.vuepress/components/tuopu/FloorView.ts

@@ -77,6 +77,8 @@ export class FloorView extends SGraphView {
             this.origin.x += se.x - this._leftKeyPos.x;
             this.origin.y += se.y - this._leftKeyPos.y;
             this.update()
+            // 鼠标左键拖动
+            this.$emit('leftMove', se)
         };
         this._leftKeyPos.x = se.x;
         this._leftKeyPos.y = se.y;

+ 236 - 0
docs/.vuepress/components/tuopu/baseTopu9.vue

@@ -0,0 +1,236 @@
+<!-- 派生 设备类 -->
+<template>
+  <div ref="basetopu6" class="base-topu">
+    <canvas
+      id="floor_topu9"
+      :width="canvasWidth"
+      :height="canvasHeight"
+      tabindex="0"
+    ></canvas>
+    <!-- 鹰眼窗口 -->
+    <canvas
+      id="enlarge"
+      width="200"
+      height="150"
+      tabindex="0"
+      style="border: 1px solid red; position: absolute; bottom: 0; left: 0"
+    />
+  </div>
+</template>
+<script>
+import { SGraphScene } from "@persagy-web/graph";
+import { FloorView } from "./FloorView";
+import { PTopoParser } from "./PTopoParser";
+import { topuFactory } from "./items/topuFactory1";
+import { EagleView } from "./items/EagleView";
+import { SColor, SPoint } from "@persagy-web/draw/";
+import axios from "axios";
+import { data } from "./data/data1.js"; //模拟接口返回参数
+export default {
+  data() {
+    return {
+      canvasWidth: 0, // 画布的宽
+      canvasHeight: 0, // 画布的高
+      view: null, // 视图 view
+      enlarge_view: null, //鹰眼图
+      scene: null, // 场景类
+    };
+  },
+  methods: {
+    // 初始化
+    init() {
+      this.clearImg();
+      this.view ? (this.view.scene = this.scene) : null;
+      this.enlarge_view ? (this.enlarge_view.scene = this.scene) : null;
+      // 获取压缩包数据并解压
+      this.getMapBlob();
+    },
+
+    // 请求获取地图的压缩包
+    getMapBlob() {
+      const obj = {
+        graphId: "2dd925178d164a96941c34326ad340e8",
+        id: "376f578716fb48febe8fb291b527169f",
+      };
+
+      // 请求头上加 projectId
+      axios.interceptors.request.use(
+        (config) => {
+          config.headers = {
+            projectId: "Pj1101050029", //项目id
+          };
+          return config;
+        },
+        (error) => {
+          return Promise.reject(error);
+        }
+      );
+      // 生产环境放开此代码获取真实数据
+      // axios.post("/labsl/graph/pub/read", obj).then((res) => {
+      //   this.getDataSuc(data);
+      // });
+      // 以下为测试环境demo;
+      this.getDataSuc(data);
+    },
+
+    // 读图成功回调
+    getDataSuc(res) {
+      // if (res.data.result == "failure") return;
+      // 添加图片路径
+      if (data.content.elements.nodes && data.content.elements.nodes.length) {
+        data.content.elements.nodes = data.content.elements.nodes.map((obj) => {
+          if (obj.properties.type == "BaseEquipment") {
+            if (obj.style.default.url) {
+              obj.style.default.url = !obj.style.default.url.includes(
+                "/image-service/common/"
+              )
+                ? "/image-service/common/image_get?systemId=dataPlatform&key=" +
+                  obj.style.default.url
+                : obj.style.default.url;
+            } else {
+              // 默认图标
+              obj.style.default.url = !obj.style.default.url.includes(
+                "/image-service/common/"
+              )
+                ? "/image-service/common/image_get?systemId=dataPlatform&key=" +
+                  "1607752841478.svg"
+                : obj.style.default.url;
+            }
+          }
+          return obj;
+        });
+      }
+      const parse = new PTopoParser();
+      parse.factory = new topuFactory();
+      // 获取数据解析数据再将转化得实例添加到场景中
+
+      parse.parseData(data.content.elements);
+      parse.markers.forEach((item) => {
+        item.moveable = false;
+        this.scene.addItem(item);
+      });
+      parse.nodes.forEach((item) => {
+        item.moveable = false;
+        if ("BaseEquipment" == item.data.properties.type) {
+          item.setEquipName();
+          item.setStatusPointColor("#7ed321");
+        }
+
+        // 相关事件触发
+        item.connect("onMouseDown", this, this.onMousedown);
+        item.connect("onMouseUp", this, this.onMouseup);
+        item.connect("onMouseLeave", this, this.onMouseleave);
+        item.connect("onMouseEnter", this, this.onMouseenter);
+        // 监听放大视图中滚轮放缩事件, wheelScale 是回调
+        this.view.connect("onMouseWheel", this, this.wheelScale);
+        // 监听放大视图中滚轮按下拖动事件, midMouseMove 是回调
+        this.view.connect("leftMove", this, this.midMouseMove);
+        // 监听标准视图的事件, 回调函数是 mouseMove
+        this.enlarge_view.connect("viewMouseMove", this, this.mouseMove);
+        this.scene.addItem(item);
+
+      });
+      parse.relations.forEach((t) => {
+        t.moveable = false;
+        this.scene.addItem(t);
+      });
+      setTimeout(() => {
+        // 设置放大视图为此时标准视图的 6 倍, 注意 6 = 1200 / 200; 1200是放大视图的宽,200 是标准视图中 可视区域的宽
+        const scale = this.canvasHeight / 150;
+        this.view.scale = scale * this.enlarge_view.scale;
+        this.view.fitSceneToView();
+        this.enlarge_view.fitSceneToView(1);
+        // 设置标准视图不可放缩
+        this.enlarge_view.scalable = false;
+      });
+    },
+    // 鼠标点击事件
+    onMousedown(item, e) {
+      console.log("鼠标按下!", item, e);
+      this.$emit("onMousedown", item, e);
+    },
+    // 放大视图 滚轮放缩事件回调
+    wheelScale(item, ev) {
+      // ev[0] view 的放缩比例
+      // ev[1] true 上滚 放大
+      if (this.view && this.enlarge_view) {
+        if (ev[1]) {
+          this.enlarge_view.rectW /= this.view.wheelZoom;
+          this.enlarge_view.rectH /= this.view.wheelZoom;
+        } else {
+          this.enlarge_view.rectW *= this.view.wheelZoom;
+          this.enlarge_view.rectH *= this.view.wheelZoom;
+        }
+      }
+    },
+    // 步骤5
+    mouseMove(item, ev) {
+      const p = ev[0];
+      this.locationGraphy(p);
+    },
+    // 定位点到放大视图的中心点
+    locationGraphy(point) {
+      let centerX = this.view.width / 2 - point.x * this.view.scale;
+      let centerY = this.view.height / 2 - point.y * this.view.scale;
+      this.view.origin = new SPoint(centerX, centerY);
+    },
+    midMouseMove(item, ev) {
+      if (this.enlarge_view && this.view) {
+        const p = this.view.mapToScene(
+          this.canvasWidth / 2,
+          this.canvasHeight / 2
+        );
+        const p2 = this.enlarge_view.mapFromScene(p.x, p.y);
+        this.enlarge_view.rectC.x = p2.x;
+        this.enlarge_view.rectC.y = p2.y;
+        this.enlarge_view.update();
+      }
+    },
+    // 鼠标抬起事件
+    onMouseup(item, e) {
+      console.log("鼠标抬起!", item, e);
+    },
+    // 鼠标事件移入
+    onMouseenter(item, e) {
+      console.log("鼠标移入!", item, e);
+    },
+    // 鼠标事件移出
+    onMouseleave(item, e) {
+      console.log("鼠标移出!", item, e);
+    },
+    // 清空画布
+    clearImg() {
+      this.scene = new SGraphScene();
+      if (this.view) {
+        this.view.update();
+      }
+      if (this.enlarge_view) {
+        this.enlarge_view.update();
+      }
+    },
+  },
+  created() {
+    this.clearImg();
+  },
+  mounted() {
+    // 获取 canvas 的宽高
+    this.canvasWidth = 800;
+    this.canvasHeight = 600;
+    // 初始化场景类
+    this.view = new FloorView("floor_topu9");
+    this.enlarge_view = new EagleView("enlarge"); // 小图
+    if (this.scene) {
+      this.view.scene = this.scene;
+      this.enlarge_view.scene = this.scene;
+    }
+    this.init();
+  },
+};
+</script>
+<style lang="less" scoped>
+.base-topu {
+  width: 100%;
+  height: 100%;
+  position: relative;
+}
+</style>

+ 97 - 0
docs/.vuepress/components/tuopu/items/EagleView.ts

@@ -0,0 +1,97 @@
+import { SGraphView } from "@persagy-web/graph";
+import { SMouseButton, SMouseEvent } from "@persagy-web/base/";
+import {SPoint, SColor, SPainter, SRect} from "@persagy-web/draw/lib";
+export class EagleView extends SGraphView {
+    // 记录左键按下位置
+    private _leftKeyPos: SPoint = new SPoint();
+    // 可视区域即 大图中展示的区域 在 标准视图中的位置及大小
+    // 可视区域宽度
+    _rectW: number = 200;
+    get rectW():number{
+        return this._rectW;
+    }
+    set rectW(v:number) {
+        this._rectW = v;
+        this.update()
+    }
+    // 可视区域高度
+    _rectH: number = 100;
+    get rectH():number{
+        return this._rectH;
+    }
+    set rectH(v:number) {
+        this._rectH = v;
+        this.update()
+    }
+    // 可视区域中心点
+    rectC: SPoint = new SPoint(100, 100);
+    // 可视区域描述的矩形
+    rect: SRect = new SRect();
+    // 鼠标按下的点是否在区域内
+    inRect: boolean = false;
+
+    /**
+     * 鼠标按下事件
+     *
+     * @param event       事件参数
+     */
+    protected onMouseDown(event: MouseEvent): void {
+        let se = new SMouseEvent(event);
+        // 判断是否在可视区域内
+        if (this.rect.contains(event.offsetX, event.offsetY)) {
+            this.inRect = true;
+        }
+        // 设置可视区域中心点
+        this.rectC.x = event.offsetX;
+        this.rectC.y = event.offsetY;
+        this.update();
+        // 按下鼠标左键
+        if (se.buttons & SMouseButton.LeftButton) {
+            this._leftKeyPos.x = se.x;
+            this._leftKeyPos.y = se.y;
+        }
+        // 将事件对象中的坐标转为场景坐标,并抛出事件
+        const ev = this.toSceneMotionEvent(event);
+        this.$emit('viewMouseMove', ev);
+    }
+
+    /**
+     * 鼠标移动事件
+     *
+     * @param event       事件参数
+     */
+    protected onMouseMove(event: MouseEvent): void {
+        // 按下的点如果在可视区域内,则执行移动可视区域方法
+        if (this.inRect) {
+            this.rectC.x = event.offsetX;
+            this.rectC.y = event.offsetY;
+            const ev = this.toSceneMotionEvent(event);
+            this.$emit('viewMouseMove', ev);
+            this.update();
+        }
+    }
+
+    /**
+     * 鼠标抬起事件
+     *
+     * @param event       事件参数
+     */
+    protected onMouseUp(event: MouseEvent): void {
+        // 按键抬起时 初始化值
+        this.inRect = false;
+    }
+    /**
+     * 绘制前景
+     *
+     * @param painter 绘制对象
+     */
+    protected drawForeground(painter: SPainter): void {
+        // 设置画笔,画刷样式
+        painter.pen.color = new SColor('#efb42f');
+        painter.pen.lineWidth = 2;
+        painter.brush.color = new SColor('#efb42f38');
+        // 绘制可视区域
+        this.rect = new SRect(this.rectC.x - this.rectW / 2, this.rectC.y - this.rectH / 2, this.rectW, this.rectH);
+        painter.drawRect(this.rect);
+    }
+}

+ 8 - 9
docs/guides/index.js

@@ -92,15 +92,13 @@ const content = [
     {
         title: "平面图嵌入指南",
         children: [
-            // ["/guides/tDInsert/brief.md", "简介"],
-            // ["/guides/tDInsert/install.md", "安装"],
-            // ["/guides/tDInsert/get-start.md", "快速上手"],
-            // ["/guides/tDInsert/addEvent.md", "添加事件"],
-            // ["/guides/tDInsert/addPicture.md", "添加二次绘制图"],
-            // ["/guides/tDInsert/addTootip.md", "实现tooltip"],
-            // // ["/guides/tuopuInsert/dragScene.md", "画布拖动"],
-            // ["/guides/tDInsert/partChange.md", "局部放大与移动"],
-            // ["/guides/tDInsert/install.md", "平面图示例代码"]
+            ["/guides/tDInsert/brief.md", "简介"],
+            ["/guides/tDInsert/install.md", "安装"],
+            ["/guides/tDInsert/get-start.md", "快速上手"],
+            ["/guides/tDInsert/addEvent.md", "添加事件"],
+            ["/guides/tDInsert/addPicture.md", "添加二次绘制图"],
+            ["/guides/tDInsert/addTootip.md", "实现tooltip"],
+            ["/guides/tDInsert/partChange.md", "局部放大与移动"],
         ]
     },
     {
@@ -115,6 +113,7 @@ const content = [
             ["/guides/tuopuInsert/derive.md", "派生---设备类"],
             ["/guides/tuopuInsert/deriveeq.md", "派生---管道类"],
             ["/guides/tuopuInsert/toolitp.md", "tooltip"],
+            ["/guides/tuopuInsert/eagle-eyes.md", "鹰眼模式"],
         ]
     },
     {

+ 60 - 0
docs/guides/tuopuInsert/eagle-eyes.md

@@ -0,0 +1,60 @@
+## 鹰眼模式
+
+::: details 目录
+[[toc]]
+:::
+
+### 绘制示例
+<tuopu-baseTopu9/>
+
+### 源码
+
+::: details 示例demo
+<<< @/docs/.vuepress/components/tuopu/baseTopu9.vue
+:::
+
+::: details 鹰眼 view 类
+<<< @/docs/.vuepress/components/tuopu/items/EagleView.ts
+:::
+
+### 源码解析
+
+```js
+// <!-- 1 添加鹰眼canvas -->
+    <canvas
+      id="enlarge"
+      width="200"
+      height="150"
+      tabindex="0"
+      style="border: 1px solid red; position: absolute; bottom: 0; left: 0"
+    />
+// 2.实例化一个场景(scene), view和鹰眼view共用;
+  this.enlarge_view = new EagleView("enlarge"); // 小图
+    if (this.scene) {
+      this.view.scene = this.scene;
+      this.enlarge_view.scene = this.scene;
+    }
+//3.为场景中展示的元素绑定onMouseMove事件, 参数意义依次为 (事件名, 接收者, 回调函数);
+
+ // 监听放大视图中滚轮放缩事件, wheelScale 是回调
+        this.view.connect("onMouseWheel", this, this.wheelScale);
+        // 监听放大视图中滚轮按下拖动事件, midMouseMove 是回调
+        this.view.connect("leftMove", this, this.midMouseMove);
+        // 监听标准视图的事件, 回调函数是 mouseMove
+        this.enlarge_view.connect("viewMouseMove", this, this.mouseMove);
+
+// 4. FloorView.ts 中新增移动回调
+ protected onMouseMove(event: MouseEvent): void {
+        super.onMouseMove(event);
+        // 按左键移动
+        let se = new SMouseEvent(event);
+        if (se.buttons & SMouseButton.LeftButton) {
+            this.origin.x += se.x - this._leftKeyPos.x;
+            this.origin.y += se.y - this._leftKeyPos.y;
+            this.update()
+            // 鼠标左键拖动
+            this.$emit('leftMove', se)
+        };
+       ......
+    } // Function onMouseMove()
+```