<template>
  <div>
    <div class="tools-bar" style="position: absolute;z-index: 10001;">
      <el-popover placement="bottom" width="200" class="el-po" trigger="click">
        <div ref="stencilContainer" class="x6-stencil"></div>
        <i class="el-icon-s-operation opt-btn" slot="reference"></i>
      </el-popover>
    </div>
    <div class="content" :style="{ height: contentHeight }">
      <!-- <div ref="stencilContainer" class="x6-stencil"></div> -->
      <div class="middle-box">
        <div ref="container" class="x6-content" :style="{ height: contentHeight }" id="container"></div>
        <div id="map-container11" class="mp-view" :style="{ height: contentHeight }"></div>
      </div>
    </div>
  </div>
</template>

<script>
import { Graph, Shape, Addon, Path } from '@antv/x6';
const { Stencil } = Addon
const { Rect, Circle } = Shape
import AMapLoader from '@amap/amap-jsapi-loader';
export default {
  data() {
    return {
      contentHeight: '0px', //容器高度，x6高度
      mapHeight: "200px", //地图高度
      center: { lng: 0, lat: 0 },//地图中心点变量
      zoom: 3,//地图缩放变量

      graph: undefined,//x6画布
      stencil: undefined,//x6拖拽

      projection: undefined,//地图projection参数

      map: null,//高德地图
      data: {
        // 节点
        nodes: [
          {
            id: 'node1', // String，可选，节点的唯一标识
            x: 0,       // Number，必选，节点位置的 x 值
            y: 0,       // Number，必选，节点位置的 y 值
            width: 80,   // Number，可选，节点大小的 width 值
            height: 40,  // Number，可选，节点大小的 height 值
            label: 'hello', // String，节点标签
          },
          {
            id: 'node2', // String，节点的唯一标识
            x: 160,      // Number，必选，节点位置的 x 值
            y: 180,      // Number，必选，节点位置的 y 值
            width: 80,   // Number，可选，节点大小的 width 值
            height: 40,  // Number，可选，节点大小的 height 值
            label: 'world', // String，节点标签
          },
        ],
        // 边
        edges: [
          {
            source: 'node1', // String，必须，起始节点 id
            target: 'node2', // String，必须，目标节点 id
          },
        ],
      }
    }
  },
  mounted() {
    this.init()
    this.initCell()
    this.initGraph();
    this.initStencil()
    this.initGaodeMap();
    this.graph.disableMouseWheel();//禁止滑轮
    this.graph.zoom(0);//设置默认画布大小

  },
  methods: {
    onRender() {
      //根据地理坐标计算屏幕坐标

      //获取所有的点
      const container = this.$refs.container
      const ports = container.querySelectorAll(
        '.x6-port-body',
      )
      //每个点的屏幕坐标重新计算
      this.graph.getNodes().forEach((node) => {
        let mapPoint = node.store.data.mapPoint
        //由地理位置转换为屏幕位置
        var lnglat = new TMap.LatLng(mapPoint.lat, mapPoint.lng)
        var pixel = this.map.projectToContainer(lnglat);
        let x6postion = this.graph.pageToLocal(pixel.round().x, pixel.round().y)
        node.position(x6postion.x, x6postion.y);

      })
    },
    init() {
      this.contentHeight = document.documentElement.clientHeight - 45 + "px";
      this.mapHeight = document.documentElement.clientHeight - 45 + "px";
    },
    //初始化图形
    initCell() {
      //桩
      const ports = {
        groups: {
          top: {
            position: 'top',
            attrs: {
              circle: {
                r: 4,
                magnet: true,
                stroke: '#5F95FF',
                strokeWidth: 1,
                fill: '#fff',
                style: {
                  visibility: 'hidden',
                },
              },
            },
          },
          right: {
            position: 'right',
            attrs: {
              circle: {
                r: 4,
                magnet: true,
                stroke: '#5F95FF',
                strokeWidth: 1,
                fill: '#fff',
                style: {
                  visibility: 'hidden',
                },
              },
            },
          },
          bottom: {
            position: 'bottom',
            attrs: {
              circle: {
                r: 4,
                magnet: true,
                stroke: '#5F95FF',
                strokeWidth: 1,
                fill: '#fff',
                style: {
                  visibility: 'hidden',
                },
              },
            },
          },
          left: {
            position: 'left',
            attrs: {
              circle: {
                r: 4,
                magnet: true,
                stroke: '#5F95FF',
                strokeWidth: 1,
                fill: '#fff',
                style: {
                  visibility: 'hidden',
                },
              },
            },
          },
        },
        items: [
          {
            group: 'top',
          },
          {
            group: 'right',
          },
          {
            group: 'bottom',
          },
          {
            group: 'left',
          },
        ],
      }
      //自定义节点
      Graph.registerNode(
        'custom-rect',
        {
          inherit: 'rect',
          width: 66,
          height: 36,
          attrs: {
            body: {
              strokeWidth: 1,
              stroke: '#5F95FF',
              fill: '#EFF4FF',
            },
            text: {
              fontSize: 12,
              fill: '#262626',
            },
          },
          ports: { ...ports },
        },
        true,
      )
    },
    //初始化高德地图
    initGaodeMap() {
      this.$nextTick(() => {
        let map = new TMap.Map('map-container11', {
          zoom: 12, // 设置地图缩放级别
          center: new TMap.LatLng(39.984104, 116.307503),// 设置地图中心点坐标
          keyboardShortcuts: false, //设置禁止通过键盘控制地图。默认情况下启用键盘快捷键。
          scrollwheel: false,
          scrollable: false,
          doubleClickZoom: false
        });
        var mapContainer = document.getElementById('container');
        var x6 = document.getElementsByClassName("x6-content");
        console.log(mapContainer)
        // 自定义SVG图层 - 继承DOMOverlay
        function SvgMarker(options) {
          TMap.DOMOverlay.call(this, options);
        }
        SvgMarker.prototype = new TMap.DOMOverlay();
        // 初始化
        SvgMarker.prototype.onInit = function (options) {
          this.options = options.options;
          this.map = options.map;
        };
        SvgMarker.prototype.createDOM = function () {
          let svg = x6[0];
          svg.setAttribute('width', '100%');
          svg.setAttribute('height', '100%');
          svg.style.cssText = 'position:absolute;top:0px;left:0px;height:1000px';
          return svg;
        };
        window.SvgMarker = SvgMarker;
        // 初始化地图
        console.log(123);



        console.log(132)

        var marker = new SvgMarker({
          map,
          options: [
            {
              position: new TMap.LatLng(39.96030543872138, 116.25809083213608),
              id: 0,
            },

          ]
        });
        marker.on('mouseenter', function (e) {
          e.setAttribute('style', 'fill: red;stroke:red; opacity:0.9;');
        });
        marker.on('mouseleave', function (e) {
          e.setAttribute('style', 'fill: blue;stroke:#FFFFFF;opacity:0.9;');
        });
        // 监听地图容器变化，动态修改svg图层大小，防止更新时元素移出svg图区
        map.on('resize', function () {
          document.getElementById('svgDom').setAttribute('width', mapContainer.offsetWidth);
          document.getElementById('svgDom').setAttribute('height', mapContainer.offsetHeight);
        })
        this.map = map;
        this.map.on('pan', (e) => {
          this.onRender();

        });
        this.map.on('dragend', (e) => {
          this.onRender();
        });

        // this.graph.fromJSON(dataNodes);
        let graph = this.graph;
        //屏幕坐标
        // dataNodes.nodes[0].wx11 = graph.localToPage(0, 0).x;
        // dataNodes.nodes[0].wy11 = graph.localToPage(0, 0).y;
        // dataNodes.nodes[1].wx11 = graph.localToPage(0, 180).x;
        // dataNodes.nodes[1].wy11 = graph.localToPage(0, 180).y;
        // //地理坐标
        // dataNodes.nodes[0].address = this.map.unprojectFromContainer({ x: dataNodes.nodes[0].wx11, y: dataNodes.nodes[0].wy11 });
        // dataNodes.nodes[1].address = this.map.unprojectFromContainer({ x: dataNodes.nodes[1].wx11, y: dataNodes.nodes[1].wy11 });

        // this.dataNodes = dataNodes;
      })



    },
    floatEqual(num1, num2) {
      return Math.abs(num1 - num2) < Number.EPSILON;
    },

    //初始化画布
    initGraph() {
      console.log("x6图层", this.$refs.container)

      console.log("地图地图", this.map)
      this.graph = new Graph({
        container: this.$refs.container,
        background: {//背景
          color: 'transport', // 设置画布背景颜色
        },
        grid: {//网格
          size: 10,      // 网格大小 10px
          visible: true, // 渲染网格背景
        },
        panning: {//画布是否可以拖动
          enabled: true, //开启支持拖拽平移
          // modifiers: 'shift', //按下修饰键并点击鼠标才能触发画布拖拽
        },
        // mousewheel: {//滚轮缩放画布
        //   enabled: true,
        //   modifiers: ['ctrl'],
        //   guard(e){//判断一个滚轮事件是否应该被处理

        //     return true
        //   }
        // },
        snapline: true,//对齐线
        selecting: {//点选/框选
          enabled: true,//开启点选/框选
          // rubberband: true,//启用框选
          showNodeSelectionBox: true,//是否显示节点的选择框
        },
        resizing: true,//缩放节点
        highlighting: {//高亮选项，指定触发某种交互时的高亮样式
          // 当链接桩可以被链接时，在链接桩外围渲染一个蓝色
          magnetAdsorbed: {
            name: 'stroke',
            args: {
              attrs: {
                //fill: '#5F95FF',
                stroke: '#5F95FF',
              },
            },
          },
          //当可以当父节点时，高亮
          embedding: {
            name: 'stroke',
            args: {
              padding: -1,
              attrs: {
                stroke: '#73d13d',
              },
            },
          },
        },
        connecting: {//连线配置
          //设置连接桩自动吸附，吸附距离为20
          snap: {
            radius: 20,
          },
          allowBlank: false,//是否允许连接到画布空白位置的点，设置为否
          allowNode: false,//是否允许边链接到节点（非节点上的链接桩）
          allowEdge: false,//是否允许边链接到另一个边
          anchor: 'center',//当连接到节点时，通过 anchor 来指定被连接的节点的锚点
          connectionPoint: 'anchor',//指定连接点
          router: {//路由将边的路径点 vertices 做进一步转换处理
            name: 'manhattan',
            args: {
              padding: 1,
            },
          },
          connector: {//连接器
            name: 'rounded',
            args: {
              radius: 8,
            },
          },
          createEdge() {//创建新的边
            return new Shape.Edge({
              attrs: {
                line: {
                  //stroke: '#A2B1C3',
                  stroke: 'green',
                  strokeWidth: 3,
                  targetMarker: {
                    name: 'block',
                    width: 12,
                    height: 8,
                  },
                },
              },
              zIndex: 20,
            })
          },
          validateConnection({ targetMagnet }) {//在移动边的时候判断连接是否有效
            return !!targetMagnet
          },
        },
        //节点嵌套
        embedding: {
          enabled: true,//开启节点嵌套
          findParent(node) {//在节点被移动时通过 findParent 指定的方法返回父节点
            const bbox = node.node.getBBox()
            return this.getNodes().filter((node) => {
              // 只有 data.parent 为 true 的节点才是父节点
              const data = node.getData()
              if (data && data.canBeParent) {
                const targetBBox = node.getBBox()
                return bbox.isIntersectWithRect(targetBBox)
              }
              return false
            })
          }
        },
        //限制子节点的移动范围
        translating: {
          restrict(view) {
            if (view) {
              const cell = view.cell
              if (cell.isNode()) {
                const parent = cell.getParent()
                if (parent) {
                  return parent.getBBox()
                }
              }
            }
            return null
          },
        },
      });
      //this.graph.fromJSON(this.data)

      //事件注册
      //鼠标移动到节点上，显示桩、给当前节点添加删除按钮
      this.graph.on('node:mouseenter', (e) => {
        const container = this.$refs.container
        const ports = container.querySelectorAll(
          '.x6-port-body',
        )
        this.showPorts(ports, true)
        this.showNodeTool(e.node, true)
        //当鼠标移动到节点上，关闭地图的拖拽
        this.changeMapDrag(false)
      })
      //鼠标移出节点，隐藏桩、删除当前节点删除按钮
      this.graph.on('node:mouseleave', (e) => {
        const container = this.$refs.container
        const ports = container.querySelectorAll(
          '.x6-port-body',
        )
        this.showPorts(ports, false)
        this.showNodeTool(e.node, false)
        //当鼠标移动到节点上，开启地图的拖拽
        // this.changeMapDrag(true)
        // this.map.ismoved1 = false;
        // setTimeout(() => {
        //   this.map.ismoved1 = true;
        // }, 100);
      })
      //鼠标移动到线上，给当前线添加删除按钮
      this.graph.on('edge:mouseenter', (e) => {
        this.showEdgeTool(e.edge, true)
      })
      //鼠标移出线，删除当前线的删除按钮
      this.graph.on('edge:mouseleave', (e) => {
        this.showEdgeTool(e.edge, false)
      })
      //移入父节点，父节点改变后
      this.graph.on('node:change:parent', ({ node }) => {
        node.attr({
          body: {
            stroke: 'none',
            fill: '#47C769',
          },
          label: {
            text: '节点-过程',
          },
        })
      })
      //节点添加到画布中
      this.graph.on('node:added', (args) => {
        //将在容器的位置坐标转换为地图的地理坐标
        this.pixelToPoint(args.node, args.node.store.data.position)
      })
      //节点点击
      this.graph.on('node:click', (args) => {
        this.map.ismoved1 = false;
        // this.map.ismoved1 = false;
        // args.e.stopPropagation();
        //将在容器的位置坐标转换为地图的地理坐标
        // this.pixelToPoint(args.node, args.node.store.data.position)
      })
      //节点在画布上移动
      this.graph.on('node:change:position', (args) => {
        //将在容器的位置坐标转换为地图的地理坐标
        // this.pixelToPoint(args.node, args.node.store.data.position)
      })
      this.graph.on('node:mouseup', (args) => {
        const container = this.$refs.container
        const ports = container.querySelectorAll(
          '.x6-port-body',
        )
        console.log(ports);
        this.graph.getNodes().forEach((node) => {
          //let mapPoint = node.store.data.mapPoint
          this.pixelToPoint(node, node.store.data.position)

        })
        //将在容器的位置坐标转换为地图的地理坐标
        //this.pixelToPoint(args.node, args.node.store.data.position)
      })
      //画布平移
      // this.graph.on('translate', ({ tx, ty }) => {
      //   console.log("平移tx",tx)
      //   //console.log("平移ty",ty)
      //   this.mapScrollBy(tx,ty)
      // })

      this.graph.on('blank:mousedown', (e) => {

        // this.changeMapDrag(true);
      })
      this.graph.on('edge:click', (e) => {
        console.log("dasd");
        // e.stopPropagation();
        // this.map.ismoved1 = false;

        // setTimeout(() => {
        //   this.map.ismoved1 = true;
        // },50);
      })

      //鼠标在空白画布上抬起
      this.graph.on('blank:mouseup', async (args) => {

        this.map.ismoved1 = false;

        //this.onRender();
        // setTimeout(() => {
        //   this.map.ismoved1 = true;
        // }, 200);
      })

      //鼠标在空白画布上抬起
      this.graph.on('blank:click', async ({ view, e }) => {

        // this.map.ismoved1 = true;
        // setTimeout(() => {
        //   this.map.ismoved1 = true;
        // }, 200);
      })


      //鼠标按下节点
      this.graph.on('node:mousedown', async ({ view, e }) => {

        // this.map.ismoved1 = false;
        // setTimeout(() => {
        //   this.map.ismoved1 = true;
        // }, 50);
      });
      //移动鼠标
      this.graph.on('node:mousemove', async ({ view, e }) => {

        this.map.ismoved1 = false;
        // setTimeout(() => {
        //   this.map.ismoved1 = true;
        // }, 50);
      });

      this.graph.on('blank:mousedown', async ({ view, e }) => {
        this.map.ismoved1 = true;
        this.changeMapDrag(true);
        //this.map.ismoved1 = false;

        // this.map.ismoved1 = false;
        // setTimeout(() => {
        //   this.map.ismoved1 = true;
        // }, 50);
      });
      //鼠标按下线
      this.graph.on('edge:mousedown', async ({ view, e }) => {
        this.map.ismoved1 = false;
        //this.map.ismoved1 = false;

        // this.map.ismoved1 = false;
        // setTimeout(() => {
        //   this.map.ismoved1 = true;
        // }, 50);
      });
      //滑轮事件
      this.graph.on('blank:mousewheel', (e) => {



        console.log(this.graph.zoom());
        console.log(e);
        if (e.delta == -1) {
          if (this.graph.zoom() == 5) {
            this.graph.zoom(-2.5)
            this.map.setZoom(13)

          }
          else if (this.graph.zoom() == 2.5) {
            this.graph.zoom(-1.5);
            this.map.setZoom(12)

          }
          else if (this.graph.zoom() == 1) {
            this.graph.zoom(-0.5)
            this.map.setZoom(11)
          }
          else if (this.graph.zoom() == 0.5) {
            this.graph.zoom(-0.25)
            this.map.setZoom(10)
          }
          else if (this.graph.zoom() == 0.25) {
            this.graph.zoom(-0.05)
            this.map.setZoom(9)
          }
          else if (this.graph.zoom() == 0.2) {
            this.graph.zoom(-0.1)
            this.map.setZoom(8)
          }
          else if (this.graph.zoom() == 0.1) {
            this.graph.zoom(-0.05)
            this.map.setZoom(7)
          }
          else if (this.graph.zoom() == 0.05) {
            this.graph.zoom(-0.025)
            this.map.setZoom(6)
          }
          else if (this.graph.zoom() == 0.025) {
            this.graph.zoom(-0.015)
            this.map.setZoom(5)
          }
        }

        if (e.delta == 1) {
          if (this.graph.zoom() == 2.5) {
            this.graph.zoom(2.5)
            this.map.setZoom(14)
          }
          else if (this.graph.zoom() == 1) {
            this.graph.zoom(1.5)
            this.map.setZoom(13)
          }
          else if (this.graph.zoom() == 0.5) {
            this.graph.zoom(0.5)
            this.map.setZoom(12)
          }
          else if (this.graph.zoom() == 0.25) {
            this.graph.zoom(0.25)
            this.map.setZoom(11)
          }
          else if (this.graph.zoom() == 0.2) {
            this.graph.zoom(0.05)
            this.map.setZoom(10)
          }

          else if (this.graph.zoom() == 0.1) {
            this.graph.zoom(0.1)
            this.map.setZoom(9)
          }
          else if (this.graph.zoom() == 0.05) {
            this.graph.zoom(0.05)
            this.map.setZoom(8)
          }
          else if (this.graph.zoom() == 0.025) {
            this.graph.zoom(0.025)
            this.map.setZoom(7)
          }
          else if (this.floatEqual(this.graph.zoom(), 0.01)) {
            this.graph.zoom(0.015)
            this.map.setZoom(6)
          }

        }
        this.onRender();
        // setTimeout(() => {
        //    this.onRender();
        // }, 1000);

      })

    },
    //初始化拖拽Stencil
    initStencil() {
      this.stencil = new Stencil({
        target: this.graph,//设置画布
        stencilGraphWidth: 200,//模板画布宽度
        stencilGraphHeight: 80,//模板画布高度
        groups: [
          {
            name: 'group1',//分组名称
            title: '元素',//分组标题
            collapsable: false,//分组是否可折叠，默认为 true
          },
        ],
      })
      //将Stencil挂载到页面上
      this.$refs.stencilContainer.appendChild(this.stencil.container)
      //定义模板节点
      const process = this.graph.createNode({
        shape: 'custom-rect',
        label: '过程',
        zIndex: 10,
        attrs: {
          body: {
            stroke: 'none',
            fill: '#3199FF',
          },
        },
      })
      const node = this.graph.createNode({
        shape: 'custom-rect',
        label: '节点',
        zIndex: 1,
        data: {
          canBeParent: true,
        },
      })
      //装载模板节点
      this.stencil.load([process, node], 'group1')
    },
    //链接桩显示/隐藏事件
    showPorts(ports, show) {
      ports.forEach(port => {
        port.style.visibility = show ? 'visible' : 'hidden'
      });
    },
    //节点上的删除按钮添加/删除事件
    showNodeTool(node, show) {
      if (show) {
        node.addTools({
          name: 'button-remove',
          args: {
            x: '100%',
            y: 0,
            offset: { x: -3, y: 3 },
          },
        })
      } else {
        node.removeTools()
      }
    },
    //线上的删除按钮添加/删除事件
    showEdgeTool(edge, show) {
      if (show) {
        edge.addTools({
          name: 'button-remove',
          args: { distance: -40 },
        })
      } else {
        edge.removeTools()
      }
    },
    //将像素坐标转换为地理坐标
    pixelToPoint(node, position) {
      //x6转屏幕
      console.log(position);
      let pmpostion = this.graph.localToPage(position.x, position.y);
      console.log(pmpostion);
      let ePoint = this.map.unprojectFromContainer({ x: pmpostion.x, y: pmpostion.y });
      console.log(ePoint)
      //let ePoint = this.map.containerToLngLat(new AMap.Pixel(position.x, position.y))
      //将数据记录到node中
      node.store.data.mapPoint = ePoint
      console.log("新位置数据", node)
    },
    //地图平移
    mapScrollBy(tx, ty) {
      this.projection.panBy(tx, ty)
    },
    //关闭/开启地图拖拽
    changeMapDrag(canDrag) {
      // this.map.setStatus({
      //   dragEnable: canDrag
      // })
      this.map.setDraggable(canDrag)
    }
  }

}
</script>

<style lang="scss" scoped>
.tools-bar {
  height: 45px;
  line-height: 45px;
  background: #fff;
  display: flex;

  .opt-btn {
    margin-top: 4px;
    font-size: 35px;
  }
}

.content {
  display: flex;

  .x6-stencil {
    width: 250px;
  }

  .middle-box {
    width: 100%;
    position: relative;

    .x6-content {
      width: 100%;
      position: absolute;
      z-index: 1;
    }

    .mp-view {
      width: 100%;
      position: absolute;
      z-index: 2;
    }
  }
}

.el-popover {
  height: 500px;
  overflow: auto;
}
</style>
<style>
.el-popover {
  height: 120px;
  overflow: auto;
}
</style>