<template>
  <div class="slide-in-top"  v-if="infoShow" style="width: 300px;height: 250px;position: absolute;"  :style="{
    left: infoPosition.x-150 + 'px',
    top: infoPosition.y-265 + 'px',
  }">
    <div  style="height: 200px;width: 100%;">
      <dv-border-box-7 class="full" :color="['rgba(0, 0, 0, 0.3)', '#0dcbec']" backgroundColor="rgba(0, 0, 0, 0.3)">
        <div class="full text-blur-out">
          <div style="width: 100%;height: 50px;color: #00ffe2;font-weight: bold;letter-spacing: 20px" class="center">{{infoProperties.name}}</div>
          <div style="width: 100%;height: 200px">
            <slot></slot>
          </div>
        </div>
      </dv-border-box-7>
    </div>
    <div class="line"></div>
    <div class="point"></div>
  </div>
</template>

<script>
import * as d3 from "d3";
import * as Three from "three";

export default {
  name: "mapForScene",
  inject: ['scene'],
  data(){
    return {
      infoShow: false,
      infoPosition: {x:0,y:0},
      mapCenterPosition: [106.292249,37.206647],
      scale: 8000,
      infoProperties: {},
      raycaster: null,
      mouse: {},
      map: {},
      onClickList: [],
      eventOffset: {x:0,y:0},
      activeInstersect: [],
      isInit: false,
    }
  },
  methods: {
    onLoad(){
      this.raycaster = new Three.Raycaster();
      this.mouse = new Three.Vector2();
      this.eventOffset = {};
      const _this = this;
      window.addEventListener( 'mousemove', this.onMouseMove, false );
      window.addEventListener( 'click', this.onMouseClick, false );
      this.isInit = true;
       // this.addPoints();
    },
    //三维坐标转换屏幕坐标
    transPosition(position=[0,0,0]){
      let world_vector = new Three.Vector3(position[0],position[1],position[2]);
      let vector =world_vector.project(this.scene.camera);
      let halfWidth =  this.scene.container.clientWidth / 2,
        halfHeight =  this.scene.container.clientHeight / 2;
      return [
        Math.round(vector.x * halfWidth + halfWidth),
        Math.round(-vector.y * halfHeight + halfHeight)
      ];
    },
    //添加地图
    async addMap(url='/data/ningxia.json'){
      const _this =this;
      let json = await this.scene.addJson(url)
      // 墨卡托投影转换
      const projection = d3.geoMercator().center(this.mapCenterPosition).scale(this.scale).translate([0, 0]);
      //地图对象模型（省份）
      let map = new Three.Object3D();
      this.map = map;
      json['features'].forEach(city => {
        let City = new Three.Object3D();
        city['geometry']['coordinates'].forEach(polygons => {
          polygons.forEach(polygon => {
            const shape = new Three.Shape();
            let linePoints = [];
            polygon.forEach((position,index) => {
              const [x,y] = projection(position)
              if(index==0){
                shape.moveTo(x,y);
              }
              shape.lineTo(x,y);   //添加区域定点
              linePoints.push(x,y);  //添加区域边界顶点
            })

            const extrudeSettings = {
              depth: 20,
              bevelEnabled: false
            };

            //构建区域模型
            const geometry = new Three.ExtrudeGeometry(shape, extrudeSettings)
            const material = new Three.MeshBasicMaterial({ color: '#02A1E2', transparent: true, opacity: 0.6 })
            const material1 = new Three.MeshBasicMaterial({ color: '#3480c4', transparent: true, opacity: 0.6 })
            const mesh = new Three.Mesh(geometry, [material, material1])

            //构建区域边界模型
            const lineGeometry = new Three.BufferGeometry();
            lineGeometry.attributes.position = new Three.BufferAttribute(new Float32Array(linePoints),2);
            const lineMaterial = new Three.LineBasicMaterial({ color: '#02A1E2' });
            const line = new Three.Line(lineGeometry, lineMaterial)

            City.add(mesh);
            City.add(line);
          })
        })
        //添加区域属性（GeoJson文件所包含的属性）
        City.properties = city.properties;
        if (city.properties.contorid) {
          const [x, y] = projection(city.properties.contorid);
          City.properties._centroid = [x, y];
        }
        // _this.scene.box3.push({
        //   position: city.properties.center,
        //   data: city.properties.name,
        //   areaCode: city.properties.adcode,
        //   x:0,
        //   y:0
        // })
        map.add(City)
      })
      _this.scene.scene.add(map)
    },
    //坐标渲染
    renderPosition(){
      const projection = d3.geoMercator().center(this.mapCenterPosition).scale(this.scale).translate([0, 0]);
      this.scene.box3.forEach(item => {
        const [x,y] =  projection(item.position);
        const [x2,y2] = this.transPosition([x,y,0]);
        item.x =x2;
        item.y = y2;
      })
    },
    //地图添加圆点标记
    addPoints(positionList=[[106.292249,38.206647],[106.492249,37.206647],[107.292249,37.206647]]){
      const projection = d3.geoMercator().center(this.mapCenterPosition).scale(this.scale).translate([0, 0]);
      let points = [];
      let normals = [];
      positionList.forEach(item => {
        const [x,y] =  projection(item);
        points.push(x,y);
        normals.push(0,0,1);
      })
       let geometry = new Three.BufferGeometry();
       let textureMap = new Three.TextureLoader().load( "/data/point.png");
       geometry.attributes.position = new Three.BufferAttribute(new Float32Array(points), 2);
      geometry.attributes.normal = new Three.BufferAttribute(new Float32Array(normals), 3);
       let material = new Three.PointsMaterial({
        wireframe: true,
        map: textureMap,
       color: 0xff000,
       size: 100.0,
         transparent: true,
       });
     let mesh  = new Three.Points(geometry, material);
     this.scene.scene.add(mesh);
    },
    //鼠标移动事件
    onMouseMove(event) {
      const _this =this;
      _this.mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
      _this.mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
      _this.eventOffset.x = event.clientX;
      _this.eventOffset.y = event.clientY;
      _this.infoPosition.x = _this.eventOffset.x + 2 ;
      _this.infoPosition.y = _this.eventOffset.y + 2 ;
    },
    //鼠标单击事件
    onMouseClick(){
      this.onClickList.forEach(item => {
        item(this.infoProperties);
      })
    },
    //判断鼠标指向（渲染鼠标指向实体）
    animate() {
      if(this.isInit){
        this.raycaster.setFromCamera( this.mouse, this.scene.camera );
        if(this.map) {
          let intersects = this.raycaster.intersectObjects(this.map.children, true);
          if (this.activeInstersect && this.activeInstersect.length > 0) {
            this.activeInstersect.forEach(element => {
              element.object.material[0].color.set('#02A1E2');
              element.object.material[1].color.set('#02A1E2');
            });
          }
          this.activeInstersect = [];
          for (let i = 0; i < intersects.length; i++) {
            if (intersects[i].object.material && intersects[i].object.material.length === 2) {
              this.activeInstersect.push(intersects[i]);
              intersects[i].object.material[0].color.set('#34ead5');
              intersects[i].object.material[1].color.set('#34ead5');
              intersects[i].object.geometry.parameters.options.depth = Math.random() * 10;
              intersects[i].object.geometry.needsUpdate = true;
              break; // 只取第一个
            }
          }
          this.createCityInfo();
        }
      }
    },
    //添加鼠标点击事件
    onClick(f){
      this.onClickList.push(f);
    },
    //信息框配置
    createCityInfo() { // 显示省份的信息
      if (this.activeInstersect.length !== 0 && this.activeInstersect[0].object.parent.properties.name) {
        this.infoProperties =  this.activeInstersect[0].object.parent.properties;
        this.infoShow = true;
      } else {
        this.infoShow = false;
      }
    }
  }
}
</script>

<style scoped>
  .line{
    width: 1px;
    height: 48px;
    margin: auto;
    background: linear-gradient(to top,rgba(0,0,0,1),rgba(0,0,0,0.5));
  }
  .point{
    width: 10px;
    height: 10px;
    margin: auto;
    border-radius: 50%;background: radial-gradient(#00ffe2,#004480,#02004a)
  }
  .full{
    width: 100%;
    height: 100%;
  }
  .center{
    display: flex;
    justify-content: center;
    align-items: center;
  }
  .slide-in-top{animation:slide-in-top .5s cubic-bezier(.25,.46,.45,.94) both}
  @keyframes slide-in-top{0%{transform:translateY(-200px);opacity:0}100%{transform:translateY(0);opacity:1}}
  @keyframes slide-in-elliptic-top-fwd{0%{transform:translateY(-600px) rotateX(-30deg) scale(0);transform-origin:50% 100%;opacity:0}100%{transform:translateY(0) rotateX(0) scale(1);transform-origin:50% 1400px;opacity:1}}

  .text-blur-out{animation:text-blur-out 0.3s cubic-bezier(.55,.085,.68,.53) both}
  @keyframes text-blur-out{0%{filter:blur(12px) opacity(0)}100%{filter:blur(.01)}}
</style>
