<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>
