|
@@ -0,0 +1,212 @@
|
|
|
+<template>
|
|
|
+ <div class="container">
|
|
|
+ <div>
|
|
|
+ <canvas id="enlargeCopy" width="1200" height="600" tabindex="0"/>
|
|
|
+
|
|
|
+ <canvas id="enlarge" width="200" height="200" tabindex="0"/>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script lang="ts">
|
|
|
+ import { SGraphScene, SGraphView, SImageItem } from "@persagy-web/graph";
|
|
|
+ import { Component, Vue } from "vue-property-decorator";
|
|
|
+ import {SPoint, SColor, SPainter, SRect} from "@persagy-web/draw/lib";
|
|
|
+ import {SObject, SMouseButton, SMouseEvent} from "@persagy-web/base/lib";
|
|
|
+ import { SFloorParser } from "@persagy-web/big/lib";
|
|
|
+
|
|
|
+ class LargeView 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);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Component
|
|
|
+ export default class GIFCanvas extends Vue {
|
|
|
+ json: string = require('../../../public/assets/map/3.json');
|
|
|
+ viewCopy: SGraphView | null = null;
|
|
|
+ view: LargeView | null = null;
|
|
|
+ /**
|
|
|
+ * 页面挂载
|
|
|
+ */
|
|
|
+ mounted(): void {
|
|
|
+ // 1.实例化2个视图
|
|
|
+ this.view = new LargeView('enlarge'); // 标准视图
|
|
|
+ this.viewCopy = new SGraphView('enlargeCopy'); // 放大视图
|
|
|
+ // 实例化1个场景
|
|
|
+ const scene = new SGraphScene();
|
|
|
+ // 在场景中添加楼层平面图
|
|
|
+ let parser = new SFloorParser();
|
|
|
+ // @ts-ignore
|
|
|
+ parser.parseData(JSON.parse(JSON.stringify(this.json.EntityList[0].Elements)));
|
|
|
+ parser.spaceList.forEach(t => {scene.addItem(t);t.fillColor=new SColor('#47bbde75');t.connect('onMouseDown', this, this.spaceClick)});
|
|
|
+
|
|
|
+ // 监听标准视图的事件, 回调函数是 mouseMove
|
|
|
+ this.view.connect('viewMouseMove', this, this.mouseMove);
|
|
|
+
|
|
|
+ // 先将场景设置到放大视图中
|
|
|
+ this.viewCopy.scene = scene;
|
|
|
+ // 再设置到标准视图中
|
|
|
+ this.view.scene = scene;
|
|
|
+ // 场景适配标准视图,
|
|
|
+ this.view.fitSceneToView(1);
|
|
|
+ // 设置放大视图为此时标准视图的 6 倍, 注意 6 = 1200 / 200; 1200是放大视图的宽,200 是标准视图中 可视区域的宽
|
|
|
+ this.viewCopy.scale = 6 * this.view.scale;
|
|
|
+ // 设置标准视图不可放缩
|
|
|
+ this.view.scalable = false;
|
|
|
+ // 监听放大视图中滚轮放缩事件, wheelScale 是回调
|
|
|
+ this.viewCopy.connect('onMouseWheel', this, this.wheelScale);
|
|
|
+ // 监听放大视图中滚轮按下拖动事件, midMouseMove 是回调
|
|
|
+ this.viewCopy.connect('midMouseMove', this, this.midMouseMove);
|
|
|
+
|
|
|
+ // 将标准视图中 可视区域的中心点坐标转为场景坐标
|
|
|
+ const p1 = this.view.mapToScene(this.view.rectC.x, this.view.rectC.y);
|
|
|
+ // 在放大视图中 将场景定位到 相应位置
|
|
|
+ this.locationGraphy(p1);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 步骤5
|
|
|
+ mouseMove(item: SObject, ev: any[]) {
|
|
|
+ const p = ev[0];
|
|
|
+ this.locationGraphy(p)
|
|
|
+ }
|
|
|
+ // 定位点到放大视图的中心点
|
|
|
+ locationGraphy(point:any) {
|
|
|
+ let centerX = (this.viewCopy!!.width / 2) - point.x * this.viewCopy!!.scale;
|
|
|
+ let centerY = (this.viewCopy!!.height / 2) - point.y * this.viewCopy!!.scale;
|
|
|
+ this.viewCopy!!.origin = new SPoint(centerX, centerY)
|
|
|
+ }
|
|
|
+ // 放大视图 滚轮放缩事件回调
|
|
|
+ wheelScale(item: SObject, ev: any[]) {
|
|
|
+ // ev[0] view 的放缩比例
|
|
|
+ // ev[1] true 上滚 放大
|
|
|
+ if (this.view && this.viewCopy) {
|
|
|
+ if (ev[1]) {
|
|
|
+ this.view.rectW /= this.viewCopy.wheelZoom;
|
|
|
+ this.view.rectH /= this.viewCopy.wheelZoom;
|
|
|
+ } else {
|
|
|
+ this.view.rectW *= this.viewCopy.wheelZoom;
|
|
|
+ this.view.rectH *= this.viewCopy.wheelZoom;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 放大视图 滚轮按下拖动回调
|
|
|
+ midMouseMove(item: SObject, ev: any[]) {
|
|
|
+ if (this.viewCopy && this.view) {
|
|
|
+ const p = this.viewCopy.mapToScene(600, 300);
|
|
|
+ const p2 = this.view.mapFromScene(p.x, p.y);
|
|
|
+ this.view.rectC.x = p2.x;
|
|
|
+ this.view.rectC.y = p2.y;
|
|
|
+ this.view.update();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ spaceClick(){
|
|
|
+ console.log(arguments)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+</script>
|
|
|
+<style scoped lang="less">
|
|
|
+ .container{
|
|
|
+ & > div{
|
|
|
+ position: relative;
|
|
|
+ height: 600px;
|
|
|
+ }
|
|
|
+ canvas {
|
|
|
+ position: absolute;
|
|
|
+ }
|
|
|
+ #enlarge{
|
|
|
+ background: #fff;
|
|
|
+ }
|
|
|
+ }
|
|
|
+</style>
|