<template>
  <div class="three-model">
    <loading ref="pageLoading"></loading>
    <div class="map-3d" :style="'transform: rotate(' + mapDeg + 'deg);'">
      <img :src="require('@assets/png/3dmap.png')" alt="" />
    </div>
    <div class="three-html-layer">
      <div
        v-for="(info, index) of htmlLayer"
        :key="index"
        class="three-html-dom fan-info"
        :id="info.id"
        v-show="info.show"
        :style="'left: ' + info.x + 'px; top: ' + info.y + 'px;'"
      >
        <div class="fan-name pointer" v-show="info.id != 'build'" @click.stop="info.clickName">
          {{ info.name }}
        </div>
        <div
          class="fan-can-click"
          @click.stop="info.clickFan"
          :style="
            'left: ' +
            info.fanX +
            'px; top: ' +
            info.fanY +
            'px; width: ' +
            info.fanW +
            'px; height: ' +
            info.fanH +
            'px;'
          "
        ></div>
      </div>
      <div
        class="three-html-dom build-info"
        :id="fanInfoLayer.id"
        v-show="fanInfoLayer.show"
        :style="
          'left: ' + fanInfoLayer.x + 'px; top: ' + fanInfoLayer.y + 'px;'
        "
      >
        <div class="build-info-close" @click.stop="hideFanInfo">
          <i class="el-icon-close"></i>
        </div>
        <div
          class="build-info-item purple"
          :style="
            'left: ' + circleXY[0].x + 'px; top: -' + circleXY[0].y + 'px'
          "
        >
          <div class="build-info-item-num">{{ jkd }}</div>
          <div class="build-info-item-text">健康度</div>
        </div>
        <div
          class="build-info-item blue"
          :style="
            'left: ' + circleXY[1].x + 'px; top: -' + circleXY[1].y + 'px'
          "
        >
          <div class="build-info-item-num">{{ ysl }}</div>
          <div class="build-info-item-text">优</div>
        </div>
        <div
          class="build-info-item yellow"
          :style="
            'left: ' + circleXY[2].x + 'px; top: -' + circleXY[2].y + 'px'
          "
        >
          <div class="build-info-item-num">{{ lsl }}</div>
          <div class="build-info-item-text">良</div>
        </div>
        <div
          class="build-info-item orange"
          :style="
            'left: ' + circleXY[3].x + 'px; top: -' + circleXY[3].y + 'px'
          "
        >
          <div class="build-info-item-num">{{ csl }}</div>
          <div class="build-info-item-text">差</div>
        </div>
        <div
          class="build-info-item red"
          :style="
            'left: ' + circleXY[4].x + 'px; top: -' + circleXY[4].y + 'px'
          "
        >
          <div class="build-info-item-num">{{ gzsl }}</div>
          <div class="build-info-item-text">故障</div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import loading from "@com/coms/loading/loading.vue";
import * as THREE from "three";
import { GLTFLoader } from "@node/three/examples/jsm/loaders/GLTFLoader.js";
import { OrbitControls } from "@node/three/examples/jsm/controls/OrbitControls.js";
import { GeometryUtils } from "@node/three/examples/jsm/utils/GeometryUtils.js";
let camera, scene, renderer, controls;
let mixers = [];
let clock = new THREE.Clock();
let fanAnimates = [];
let fans = [];
// let cylinder = null;
export default {
  // 名称
  name: "ThreeModel1",
  // 使用组件
  components: {
    loading,
  },
  // 传入参数
  props: {
    data: {
      type: Object,
      default: () => {},
    },
  },
  // 自定义事件
  emits: {
    when: null,
  },
  // 数据
  data() {
    const that = this;
    return {
      mapSource: {},
      warScore: 60,
      pointer: false,
      jkd: null,
      ysl: null,
      lsl: null,
      csl: null,
      gzsl: null,
      htmlLayer: [
        {
          // 麻黄山
          id: "fan-mhs",
          x: 0,
          y: 0,
          show: true,
          ox: 50,
          oy: 10,
          fanW: 60,
          fanH: 100,
          fanX: 0,
          fanY: -110,
          position: null,
          name: "麻黄山",
          clickName: function () {
            that.clickMapItem([
              "MHS_FDC_SC",
              "MG01_01_TD",
              "MG01_02_TD",
              "MG01_03_TD",
              "MG01_04_TD",
              "MG01_05_TD",
            ]);
          },
          clickFan: () => {
            this.showFanInfo(this.htmlLayer[0].position);
            this.jkd = this.htmlLayer[0].jkd;
            this.ysl = this.htmlLayer[0].ysl;
            this.lsl = this.htmlLayer[0].lsl;
            this.csl = this.htmlLayer[0].csl;
            this.gzsl = this.htmlLayer[0].gzsl;
            that.clickMapItem([
              "MHS_FDC_SC",
              "MG01_01_TD",
              "MG01_02_TD",
              "MG01_03_TD",
              "MG01_04_TD",
              "MG01_05_TD",
            ]);
          },
        },
        {
          // 牛首山
          id: "fan-nss",
          x: 0,
          y: 0,
          show: true,
          ox: 35,
          oy: 0,
          fanW: 60,
          fanH: 100,
          fanX: 0,
          fanY: -110,
          position: null,
          name: "牛首山",
          clickName: function () {
            console.log("牛首山");
            that.clickMapItem([
              "NSS_FDC_SC",
              "NG01_27_TD",
              "NG01_28_TD",
              "NG01_30_TD",
              "NG01_31_TD",
              "NG01_32_TD",
            ]);
          },
          clickFan: () => {
            this.showFanInfo(this.htmlLayer[1].position);
            this.jkd = this.htmlLayer[1].jkd;
            this.ysl = this.htmlLayer[1].ysl;
            this.lsl = this.htmlLayer[1].lsl;
            this.csl = this.htmlLayer[1].csl;
            this.gzsl = this.htmlLayer[1].gzsl;
            that.clickMapItem([
              "NSS_FDC_SC",
              "NG01_27_TD",
              "NG01_28_TD",
              "NG01_30_TD",
              "NG01_31_TD",
              "NG01_32_TD",
            ]);
          },
        },
        {
          // 青山
          id: "fan-qs",
          x: 0,
          y: 0,
          show: true,
          ox: 60,
          oy: 10,
          fanW: 60,
          fanH: 100,
          fanX: 0,
          fanY: -100,
          position: null,
          name: "青山",
          clickName: function () {
            that.clickMapItem([
              "QS_FDC_SC",
              "QG01_67_TD",
              "QG01_69_TD",
              "QG01_71_TD",
              "QG01_72_TD",
              "QG01_73_TD",
            ]);
          },
          clickFan: () => {
            this.showFanInfo(this.htmlLayer[2].position);
            this.jkd = this.htmlLayer[2].jkd;
            this.ysl = this.htmlLayer[2].ysl;
            this.lsl = this.htmlLayer[2].lsl;
            this.csl = this.htmlLayer[2].csl;
            this.gzsl = this.htmlLayer[2].gzsl;
            that.clickMapItem([
              "QS_FDC_SC",
              "QG01_67_TD",
              "QG01_69_TD",
              "QG01_71_TD",
              "QG01_72_TD",
              "QG01_73_TD",
            ]);
          },
        },
        {
          // 石板泉
          id: "fan-sbq",
          x: 0,
          y: 0,
          show: true,
          ox: 40,
          oy: 0,
          fanW: 60,
          fanH: 90,
          fanX: 0,
          fanY: -90,
          position: null,
          name: "石板泉",
          clickName: function () {
            console.log("石板泉");
            that.clickMapItem([
              "SBQ_FDC_SC",
              "SG01_01_TD",
              "SG01_02_TD",
              "SG01_03_TD",
              "SG01_04_TD",
              "SG01_05_TD",
            ]);
          },
          clickFan: () => {
            this.showFanInfo(this.htmlLayer[3].position);
            this.jkd = this.htmlLayer[3].jkd;
            this.ysl = this.htmlLayer[3].ysl;
            this.lsl = this.htmlLayer[3].lsl;
            this.csl = this.htmlLayer[3].csl;
            this.gzsl = this.htmlLayer[3].gzsl;
            that.clickMapItem([
              "SBQ_FDC_SC",
              "SG01_01_TD",
              "SG01_02_TD",
              "SG01_03_TD",
              "SG01_04_TD",
              "SG01_05_TD",
            ]);
          },
        },
        {
          // 香山
          id: "fan-xs",
          x: 0,
          y: 0,
          show: true,
          ox: 25,
          oy: 20,
          fanW: 70,
          fanH: 100,
          fanX: -15,
          fanY: -110,
          position: null,
          name: "香山",
          clickName: function () {
            console.log("香山");
            that.clickMapItem([
              "XS_FDC_SC",
              "XG01_26_TD",
              "XG01_27_TD",
              "XG01_29_TD",
              "XG01_30_TD",
              "XG01_31_TD",
            ]);
          },
          clickFan: () => {
            this.showFanInfo(this.htmlLayer[4].position);
            this.jkd = this.htmlLayer[4].jkd;
            this.ysl = this.htmlLayer[4].ysl;
            this.lsl = this.htmlLayer[4].lsl;
            this.csl = this.htmlLayer[4].csl;
            this.gzsl = this.htmlLayer[4].gzsl;
            that.clickMapItem([
              "XS_FDC_SC",
              "XG01_26_TD",
              "XG01_27_TD",
              "XG01_29_TD",
              "XG01_30_TD",
              "XG01_31_TD",
            ]);
          },
        },
        {
          // 大武口
          id: "light-dwk",
          x: 0,
          y: 0,
          show: true,
          ox: 330,
          oy: 80,
          fanW: 60,
          fanH: 80,
          fanX: 0,
          fanY: -80,
          position: null,
          name: "大武口",
          clickName: function () {
            console.log("大武口");
          },
          clickFan: () => {
            console.log("大武口");
          },
        },
        {
          // 平罗
          id: "light-pl",
          x: 0,
          y: 0,
          show: true,
          ox: 330,
          oy: 80,
          fanW: 60,
          fanH: 80,
          fanX: 0,
          fanY: -80,
          position: null,
          name: "平罗",
          clickName: function () {
            console.log("平罗");
          },
          clickFan: () => {
            console.log("平罗");
          },
        },
        {
          // 马场湖
          id: "light-mch",
          x: 0,
          y: 0,
          show: true,
          ox: 230,
          oy: 80,
          fanW: 60,
          fanH: 80,
          fanX: 0,
          fanY: -80,
          position: null,
          name: "马场湖",
          clickName: function () {
            console.log("马场湖");
          },
          clickFan: () => {
            console.log("马场湖");
          },
        },
        {
          // 宣和
          id: "light-xh",
          x: 0,
          y: 0,
          show: true,
          ox: 260,
          oy: 90,
          fanW: 60,
          fanH: 80,
          fanX: 0,
          fanY: -80,
          position: null,
          name: "宣和",
          clickName: function () {
            console.log("宣和");
          },
          clickFan: () => {
            console.log("宣和");
          },
        },
        {
          // 海子井
          id: "light-hzj",
          x: 0,
          y: 0,
          show: true,
          ox: 290,
          oy: 120,
          fanW: 60,
          fanH: 80,
          fanX: 0,
          fanY: -80,
          position: null,
          name: "海子井",
          clickName: function () {
            console.log("海子井");
          },
          clickFan: () => {
            console.log("海子井");
          },
        },
        { // 大楼
           id: "build",
           x: 0,
           y: 0,
           show: true,
           ox: 290,
           oy: 120,
           fanW: 60,
           fanH: 100,
           fanX: -260,
           fanY: -200,
           position: null,
           name: "大楼",
           clickName: function () { console.log("大楼") },
           clickFan: () => { 
           this.showFanInfo(this.htmlLayer[10].position);
          },
         },
      ],
      fanInfoLayer: {
        id: "fan-info",
        x: 0,
        y: 0,
        show: false,
        ox: 70,
        oy: -40,
        position: null,
      },
      circleXY: [
        {
          x: 130 * Math.cos((180 / 180) * Math.PI) - 33,
          y: 130 * Math.sin((180 / 180) * Math.PI) + 33,
        },
        {
          x: 130 * Math.cos((135 / 180) * Math.PI) - 33,
          y: 130 * Math.sin((135 / 180) * Math.PI) + 33,
        },
        {
          x: 130 * Math.cos((90 / 180) * Math.PI) - 33,
          y: 130 * Math.sin((90 / 180) * Math.PI) + 33,
        },
        {
          x: 130 * Math.cos((45 / 180) * Math.PI) - 33,
          y: 130 * Math.sin((45 / 180) * Math.PI) + 33,
        },
        {
          x: 130 * Math.cos((0 / 180) * Math.PI) - 33,
          y: 130 * Math.sin((0 / 180) * Math.PI) + 33,
        },
      ],
      colors: [
        { colorName: "green", state: "dj", stateName: "待机", color: 0x05bb4c },
        { colorName: "blue", state: "yx", stateName: "运行", color: 0x4b55ae },
        { colorName: "pink", state: "xd", stateName: "限电", color: 0xc531c7 },
        { colorName: "red", state: "gz", stateName: "故障", color: 0xba3237 },
        {
          colorName: "orange",
          state: "jx",
          stateName: "检修",
          color: 0xe17e23,
        },
        { colorName: "gray", state: "lx", stateName: "离线", color: 0x606769 },
        { colorName: "white", state: "sl", stateName: "受累", color: 0xffffff },
      ],
      fanName: "",
      playAnimation: true,
      mapDeg: 0,
    };
  },
  // 函数
  methods: {
    rinseData() {
      if (this.mapSource && this.mapSource.MHS_FDC) {
        for (let pKey in this.mapSource) {
          this.htmlLayer.forEach((ele) => {
            if (
              pKey.toLowerCase().indexOf(ele.id.toLowerCase().split("-")[1]) !==
              -1
            ) {
              for (let cKey in this.mapSource[pKey]) {
                ele[cKey] = this.mapSource[pKey][cKey];
              }
            }
          });
        }
      }
    },
    // 点击风场或者光伏传回点击的值
    clickMapItem(videoArray = []) {
      this.$emit("clickMapItem", videoArray);
    },
    // Vector3 to screen
    vector3ToScreen: function (position) {
      const centerX = this.$el.scrollWidth / 2;
      const centerY = this.$el.scrollHeight / 2;
      const v3 = new THREE.Vector3(position.x, position.y, position.z);
      const standardVec = v3.project(camera);
      const screenX = Math.round(centerX * standardVec.x + centerX);
      const screenY = Math.round(-centerY * standardVec.y + centerY);
      return { x: screenX, y: screenY };
    },
    // 场景
    initScene: function () {
      scene = new THREE.Scene();
      // scene.background = new THREE.Color(0xa0a0a0);
    },
    // 相机
    initCamera: function () {
      camera = new THREE.PerspectiveCamera(
        45,
        this.$el.scrollWidth / this.$el.scrollHeight,
        0.1,
        10000
      );
      camera.position.set(50, 50, 50);
    },
    // 坐标轴
    initAxesHelper: function () {
      const axesHelper = new THREE.AxesHelper(150);
      scene.add(axesHelper);
      axesHelper.position.set(0, 0, 0);
    },
    // 渲染器
    initRender: function () {
      renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
      // renderer.setClearAlpha(0);
      renderer.setSize(this.$el.scrollWidth, this.$el.scrollHeight);
      this.$el.append(renderer.domElement);
    },
    // 灯光
    initLight: function () {
      // let light = new THREE.PointLight(0xffffff, 2);
      let light = new THREE.AmbientLight(0xffffff, 5);
      // light.position.set(50, 50, 50);
      scene.add(light);
    },
    // 控制器
    initControls: function () {
      controls = new OrbitControls(camera, renderer.domElement);
      controls.enablePan = false;
      controls.maxPolarAngle = (45 / 180) * Math.PI;
      controls.minPolarAngle = (45 / 180) * Math.PI;
      controls.maxAzimuthAngle = (45 / 180) * Math.PI;
      controls.minAzimuthAngle = (45 / 180) * Math.PI;
      controls.enableKeys = false;
      controls.enableZoom = false;
      controls.update();
      // controls.maxAzimuthAngle = 50 / 180 *  Math.PI;
      // controls.minAzimuthAngle = 40 / 180 *  Math.PI;
      // controls.addEventListener("change", () => {
      //     let cDeg = controls.getAzimuthalAngle() / Math.PI * 180;
      //     this.mapDeg = cDeg - 40 - 5;
      //     this.setEveryHTML();
      // });
    },
    // 初始化一个风机动画
    initFanAnimate: function (obj) {
      let fanAnimateObj = {
        speed: 0.05,
        rotate: 0,
        fan: obj.getObjectByName(`${obj.name}_leaf`),
        fan1: obj.getObjectByName(`${obj.name}_leaf_1`),
        fan2: obj.getObjectByName(`${obj.name}_leaf_2`),
        fan3: obj.getObjectByName(`${obj.name}_leaf_3`),
      };
      let fanAnimateFunction = function () {
        // fanAnimateObj.fan.rotateOnAxis(new THREE.Vector3(0, 1, 0), fanAnimateObj.speed);
        fanAnimateObj.fan.rotateY(fanAnimateObj.speed);
        // fanAnimateObj.fan1.rotateZ(fanAnimateObj.speed);
        // fanAnimateObj.fan2.rotateZ(fanAnimateObj.speed);
        // fanAnimateObj.fan3.rotateZ(fanAnimateObj.speed);
        // fanAnimateObj.rotate += fanAnimateObj.speed;
        // if (fanAnimateObj.rotate >= 360) {
        //     fanAnimateObj.rotate = 0;
        // }
        fanAnimateObj.animateId =
          window.requestAnimationFrame(fanAnimateFunction);
      };
      fanAnimateObj.stop = function () {
        window.cancelAnimationFrame(fanAnimateObj.animateId);
      };
      fanAnimateObj.start = function () {
        fanAnimateFunction();
      };
      fanAnimateFunction();
      fanAnimates.push(fanAnimateObj);
      return fanAnimateObj;
    },
    // 清空风机动画
    clearFanAnimate: function () {
      while (fanAnimates.length > 0) {
        let fanAnimateObj = fanAnimates.shift();
        fanAnimateObj.stop();
      }
      this.playAnimation = false;
    },
    // 开始风机动画
    startFanAnimate: function () {
      fans.forEach((fan) => {
        this.initFanAnimate(fan);
      });
      this.playAnimation = true;
    },
    // 内容
    initContent: function () {
      // 加载3D地面
      let loaderGround = new GLTFLoader(); /*实例化加载器*/
      loaderGround.load(
        "static/3d/fanvar.gltf",
        (gltf) => {
          gltf.scene.position.set(17, 10, -12);
          // console.log(gltf);
          scene.add(gltf.scene);
          let rootNode = gltf.scene.children[0];
          let fan = gltf.scene.children[0].children[0];
          rootNode.remove(fan);
          this.setFanPosition(rootNode, fan);
        },
        (xhr) => {},
        function (error) {
          console.error("load error!" + error.getWebGLErrorMessage());
        }
      );
      loaderGround.load(
        "static/3d/light.gltf",
        (gltf) => {
          gltf.scene.position.set(17, 10, -12);
          // console.log(gltf);
          scene.add(gltf.scene);
          let rootNode = gltf.scene.children[0];
          let light = gltf.scene.children[0].children[0];
          rootNode.remove(light);
          this.setLightPosition(rootNode, light);
        },
        (xhr) => {},
        function (error) {
          console.error("load error!" + error.getWebGLErrorMessage());
        }
      );
      loaderGround.load(
        "static/3d/build.gltf",
        (gltf) => {
          gltf.scene.position.set(0, 0, -35); // 10, 0, -50    -6, 0.13, -50
          scene.add(gltf.scene);
          gltf.scene.rotateY(120);
            this.htmlLayer[10].position = {
                x: -6,
                y: -4,
                z: -35,
            }
          scene.onAfterRender = () => {
            this.$emit("when");
            this.$refs.pageLoading.hide();
            this.setEveryHTML();
          };
        },
        (xhr) => {},
        function (error) {
          console.error("load error!" + error.getWebGLErrorMessage());
        }
      );
    },
    // 改变元素底盘的颜色（带底盘的）
    changeObjectColor: function (obj, colorName) {
      for (let i = 1; i <= 4; i++) {
        let c = obj.getObjectByName(`${obj.name}_c_${i}`);
        c.material = new THREE.MeshBasicMaterial({
          color: 0xf0f0f0,
          opacity: 0.8,
          transparent: true,
        });
      }
      let leaf = obj.getObjectByName(`${obj.name}_leaf`);
      for (let chind of leaf.children) {
        chind.material = new THREE.MeshBasicMaterial({
          color: 0xf0f0f0,
          opacity: 0.8,
          transparent: true,
        });
      }
      let chassis = obj.getObjectByName(`${obj.name}_chassis`);
      // let color = this.colors.find(t => t.colorName == colorName || t.state == colorName || t.stateName == colorName).color;
      chassis.material = new THREE.MeshBasicMaterial({
        // color: color,
        color: 0xf0f0f0,
        opacity: 0.8,
        transparent: true,
      });
    },
    // 改变元素的颜色（光伏）
    changeElColor: function (obj, colorName) {
      // let color = this.colors.find(t => t.colorName == colorName || t.state == colorName || t.stateName == colorName).color;
      // for (let i = 1; i <= 6; i++) {
      //     let el = obj.getObjectByName(`${obj.name}_item_${i}`);
      //     el.material = new THREE.MeshBasicMaterial({
      //         color: color,
      //         opacity: 0.8,
      //         transparent: true,
      //     });
      // }
    },
    // 设置风机name
    setFanName: function (obj, name) {
      obj.name = name;
      obj.userData.name = name;
      // "Cylinder881" "Cone277"
      let Cylinder881 = obj.getObjectByName("Cylinder881");
      let Cylinder882 = obj.getObjectByName("Cylinder882");
      let Cylinder883 = obj.getObjectByName("Cylinder883");
      let Cone277 = obj.getObjectByName("Cone277");
      Cylinder881.name = `${name}_c_1`;
      Cylinder881.userData.name = `${name}_c_1`;
      Cylinder882.name = `${name}_c_2`;
      Cylinder882.userData.name = `${name}_c_2`;
      Cylinder883.name = `${name}_c_3`;
      Cylinder883.userData.name = `${name}_c_3`;
      Cone277.name = `${name}_c_4`;
      Cone277.userData.name = `${name}_c_4`;
      // "Box719")
      let fanBig1_1 = obj.getObjectByName("Box719");
      let fanBig1_2 = obj.getObjectByName("Box720");
      let fanBig1_3 = obj.getObjectByName("Box721");
      fanBig1_1.name = `${name}_leaf_1`;
      fanBig1_1.userData.name = `${name}_leaf_1`;
      fanBig1_2.name = `${name}_leaf_2`;
      fanBig1_2.userData.name = `${name}_leaf_2`;
      fanBig1_3.name = `${name}_leaf_3`;
      fanBig1_3.userData.name = `${name}_leaf_3`;
      obj.children[obj.children.length - 1].name = `${name}_chassis`;
      obj.children[obj.children.length - 1].userData.name = `${name}_chassis`;
      obj.remove(fanBig1_1, fanBig1_2, fanBig1_3);
      var group = new THREE.Group();
      // var group = new THREE.Mesh(new THREE.BoxGeometry(0.01, 0.01, 0.01),
      //     new THREE.MeshBasicMaterial({
      //         color: 0xff0000
      //     })
      // );
      group.position.set(
        group.position.x + 0.0067,
        group.position.y,
        group.position.z + 0.01
      );
      fanBig1_1.position.set(
        fanBig1_1.position.x - 0.0067,
        fanBig1_1.position.y,
        fanBig1_1.position.z - 0.01
      );
      fanBig1_2.position.set(
        fanBig1_2.position.x - 0.0067,
        fanBig1_2.position.y,
        fanBig1_2.position.z - 0.01
      );
      fanBig1_3.position.set(
        fanBig1_3.position.x - 0.0067,
        fanBig1_3.position.y,
        fanBig1_3.position.z - 0.01
      );
      group.add(fanBig1_1, fanBig1_2, fanBig1_3);
      obj.add(group);
      group.name = `${name}_leaf`;
    },
    // 设置风机位置 颜色
    setFanPosition: function (rootNode, obj) {
      // 麻黄山
      let fan_mhs = obj.clone(true);
      fan_mhs.position.set(10, 5, -4);
      this.setFanName(fan_mhs, "fan_mhs");
      rootNode.add(fan_mhs);
      this.htmlLayer[0].position = fan_mhs.position;
      if (this.htmlLayer[0].jkd < this.warScore) {
        this.initCylinderGeometry(fan_mhs);
      }

      // 牛首山
      let fan_nss = obj.clone(true);
      fan_nss.position.set(-4, 4, -15);
      this.setFanName(fan_nss, "fan_nss");
      rootNode.add(fan_nss);
      this.htmlLayer[1].position = fan_nss.position;
      if (this.htmlLayer[1].jkd < this.warScore) {
        this.initCylinderGeometry(fan_nss); // 故障 显示红色圆柱
      }

      // 青山
      let fan_qs = obj.clone(true);
      fan_qs.position.set(15, 5, -9);
      this.setFanName(fan_qs, "fan_qs");
      rootNode.add(fan_qs);
      this.htmlLayer[2].position = fan_qs.position;
      if (this.htmlLayer[2].jkd < this.warScore) {
        this.initCylinderGeometry(fan_qs);
      }

      // 石板泉
      let fan_sbq = obj.clone(true);
      fan_sbq.position.set(4, 5, -2);
      this.setFanName(fan_sbq, "fan_sbq");
      rootNode.add(fan_sbq);
      this.htmlLayer[3].position = fan_sbq.position;
      if (this.htmlLayer[3].jkd < this.warScore) {
        this.initCylinderGeometry(fan_sbq);
      }

      // 香山
      let fan_xs = obj.clone(true);
      fan_xs.position.set(-9, 7, 21);
      this.setFanName(fan_xs, "fan_xs");
      rootNode.add(fan_xs);
      this.htmlLayer[4].position = fan_xs.position;
      if (this.htmlLayer[4].jkd < this.warScore) {
        this.initCylinderGeometry(fan_xs);
      }

      // 改一下颜色
      this.changeObjectColor(fan_mhs, "green"); // 麻黄山
      this.changeObjectColor(fan_nss, "xd"); // 牛首山
      this.changeObjectColor(fan_qs, "检修"); // 青山
      this.changeObjectColor(fan_sbq, "white"); // 石板泉
      this.changeObjectColor(fan_xs, "运行"); // 香山

      // 风机存入数组
      fans.push(fan_mhs);
      fans.push(fan_nss);
      fans.push(fan_qs);
      fans.push(fan_sbq);
      fans.push(fan_xs);

      // 开始风机动画
      this.startFanAnimate();

      // 设置位置
      this.setEveryHTML();
    },
    // 设置光伏name
    setLightName: function (obj, name) {
      obj.name = name;
      obj.userData.name = name;
      let Box661 = obj.getObjectByName("Box661");
      let Box668 = obj.getObjectByName("Box668");
      let Box669 = obj.getObjectByName("Box669");
      let Box664 = obj.getObjectByName("Box664");
      let Box667 = obj.getObjectByName("Box667");
      let Box670 = obj.getObjectByName("Box670");
      Box661.name = `${name}_item_1`;
      Box661.userData.name = `${name}_item_1`;
      Box668.name = `${name}_item_2`;
      Box668.userData.name = `${name}_item_2`;
      Box669.name = `${name}_item_3`;
      Box669.userData.name = `${name}_item_3`;
      Box664.name = `${name}_item_4`;
      Box664.userData.name = `${name}_item_4`;
      Box667.name = `${name}_item_5`;
      Box667.userData.name = `${name}_item_5`;
      Box670.name = `${name}_item_6`;
      Box670.userData.name = `${name}_item_6`;
    },
    // 设置光伏位置 颜色
    setLightPosition: function (rootNode, obj) {
      obj.scale.set(200, 200, 200);
      // let Box660 = obj.getObjectByName("Box660");
      // let Box666 = obj.getObjectByName("Box666");
      // let Box662 = obj.getObjectByName("Box662");
      // let Box663 = obj.getObjectByName("Box663");
      // let Box659 = obj.getObjectByName("Box659");
      // let Box665 = obj.getObjectByName("Box665");
      // obj.remove(Box660);
      // obj.remove(Box666);
      // obj.remove(Box662);
      // obj.remove(Box663);
      // obj.remove(Box659);
      // obj.remove(Box665);
      // 大武口
      let light_dwk = obj.clone(true);
      light_dwk.position.set(-22, 0, -28); // -20 +30 // -2 0 -58 // -6, 0.13, -50    10, 0, -50
      // this.setLightName(light_dwk, "light_dwk");
      rootNode.add(light_dwk);
      this.htmlLayer[5].position = light_dwk.position;
      // 平罗
      let light_pl = obj.clone(true);
      light_pl.position.set(-26, 0.13, -25);
      // this.setLightName(light_pl, "light_pl");
      rootNode.add(light_pl);
      this.htmlLayer[6].position = light_pl.position;
      // 马场湖
      let light_mch = obj.clone(true);
      light_mch.position.set(-47, 2, 0);
      // this.setLightName(light_mch, "light_mch");
      rootNode.add(light_mch);
      this.htmlLayer[7].position = light_mch.position;
      // 宣和
      let light_xh = obj.clone(true);
      light_xh.position.set(-38, 4, 3);
      // this.setLightName(light_xh, "light_xh");
      rootNode.add(light_xh);
      this.htmlLayer[8].position = light_xh.position;
      // 海子井
      let light_hzj = obj.clone(true);
      light_hzj.position.set(-30, 2, 4);
      // this.setLightName(light_hzj, "light_hzj");
      rootNode.add(light_hzj);
      this.htmlLayer[9].position = light_hzj.position;

      // 改变颜色
      this.changeElColor(light_dwk, "green"); // 大武口
      this.changeElColor(light_pl, "离线"); // 平罗
      this.changeElColor(light_mch, "yx"); // 马场湖
      this.changeElColor(light_xh, "red"); // 宣和
      this.changeElColor(light_hzj, "受累"); // 海子井

      // 设置位置
      this.setEveryHTML();
    },
    // 创建一个圆柱
    initCylinderGeometry: function (obj, mode = "fan") {
      let cr = 1.7;
      let xyz = [5.75, 6.85, -0.63];
      switch (mode) {
        case "fan":
          cr = 1.7;
          xyz = [5.75, 6.85, -0.63];
          break;
        case "light":
          cr = 3;
          xyz = [5.75, 6.85, -0.63];
          break;

        default:
          break;
      }
      let geometry = new THREE.CylinderGeometry(cr, cr, 4, 128, 1, true);
      //加载纹理
      let texture = new THREE.TextureLoader().load(
        "static/3d/beam-texture-red.png"
      );
      texture.wrapS = texture.wrapT = THREE.RepeatWrapping; //每个都重复
      texture.repeat.set(1, 1);
      texture.needsUpdate = true;
      let materials = [
        //圆柱侧面材质，使用纹理贴图
        new THREE.MeshBasicMaterial({
          map: texture,
          side: THREE.FrontSide,
          transparent: true,
        }),
        //圆柱顶材质
        new THREE.MeshBasicMaterial({
          transparent: true,
          opacity: 0,
          side: THREE.DoubleSide,
          // side: THREE.DoubleSide,THREE.FrontSide THREE.BackSide
        }),
        //圆柱底材质
        new THREE.MeshBasicMaterial({
          transparent: true,
          opacity: 0,
          side: THREE.DoubleSide,
        }),
      ];
      let cylinder = new THREE.Mesh(geometry, materials);
      cylinder.position.set(
        obj.position.x + xyz[0],
        obj.position.y + xyz[1],
        obj.position.z + xyz[2]
      );
      scene.add(cylinder);
    },
    // 设置每一个html的位置
    setEveryHTML: function () {
      this.htmlLayer.forEach((value) => {
        if (value.show && value.position) {
          const screen = this.vector3ToScreen(value.position);
          value.x = screen.x + value.ox;
          value.y = screen.y + value.oy;
        }
      });
    },
    // 判断时候是可点击对象 返回null 或object
    getClickObject: function (intersects) {
      const names = ["fan"];
      const namesRoot = ["fanvar"];
      let x = true;
      let obj = null;
      for (let intersect of intersects) {
        let temObj = intersect.object;
        while (x) {
          for (let name of names) {
            if (temObj.name.indexOf(`${name}_`) == 0) {
              obj = temObj;
              x = false;
              break;
            }
          }
          if (x && temObj.parent) {
            temObj = temObj.parent;
            continue;
          }
          break;
        }
      }
      if (obj) {
        while (obj.parent && !namesRoot.includes(obj.parent.name)) {
          obj = obj.parent;
        }
      }
      if (obj && !namesRoot.includes(obj.parent.name)) {
        obj = null;
      }
      return obj;
    },
    // 显示风机弹出层
    showFanInfo: function (position) {
      this.fanInfoLayer.position = {
        x: position.x,
        y: position.y,
        z: position.z,
      };
      const screen = this.vector3ToScreen(this.fanInfoLayer.position);
      this.fanInfoLayer.x = screen.x + this.fanInfoLayer.ox;
      this.fanInfoLayer.y = screen.y + this.fanInfoLayer.oy;
      this.fanInfoLayer.show = true;
    },
    // 隐藏风机弹出层
    hideFanInfo: function () {
      this.fanInfoLayer.show = false;
    },
    // 初始化云
    initCloud: function () {},
    // 初始化
    initThree: function () {
      this.initScene();
      // this.initAxesHelper();
      this.initCamera();
      this.initRender();
      this.initLight();
      this.initControls();
      this.initContent();
      this.initCloud();
      renderer.setAnimationLoop(this.animate);
    },
    // 动画
    animate: function () {
      renderer.render(scene, camera);
    },
  },
  // 生命周期钩子
  beforeCreate() {
    // 创建前
  },
  created() {
    // 创建后
  },
  beforeMount() {
    // 渲染前
  },
  mounted() {
    // 渲染后
    this.initThree();
    this.mapSource = this.data;
    this.rinseData();
  },
  beforeUpdate() {
    // 数据更新前
  },
  updated() {
    // 数据更新后
  },
  beforeUnmount() {
    // 销毁前
    renderer.setAnimationLoop(null);
    camera = null;
    scene = null;
    renderer = null;
  },
  watch: {
    data(res) {
      this.mapSource = res;
      this.rinseData();
    },
  },
};
</script>

<style lang="less" scoped>
.three-model {
  position: relative;
  overflow: hidden;
  // left: -112px;

  .map-3d {
    position: absolute;
    width: 1118px;
    height: 678px;
    left: calc(50% - 559px);
    top: calc(50% - 339px);
    z-index: -1;

    map {
      width: 100%;
      height: 100%;
    }
  }

  .three-html-layer {
    .three-html-dom {
      position: absolute;
    }

    .fan-name {
      display: inline-block;
      height: 22px;
      background: #222632;
      border: 1px solid #646464;
      border-radius: 10px;
      padding: 0 10px;
      font-size: 12px;
      font-weight: 400;
      color: #ffffff;
      line-height: 22px;
    }

    .fan-can-click {
      position: absolute;
      background: #ff0000;
      opacity: 0;
      cursor: pointer;
    }

    .build-info {
      width: 166px;
      height: 33px;
      // position: relative;

      .build-info-close {
        position: absolute;
        width: 40px;
        height: 40px;
        top: -20px;
        left: -20px;
        border-radius: 50%;
        background: #1a1f2fd8;
        border: 1px solid #05bb4c;
        box-shadow: 0px 8px 17px 1px #05bb4c66;
        cursor: pointer;
        color: @gray-l;
        transition: all 0.3s;
        display: flex;
        align-items: center;
        justify-content: center;
        font-size: 14px;

        &:hover {
          color: #05bb4c;
        }
      }

      .build-info-item {
        width: 66px;
        height: 66px;
        border-radius: 50%;
        background: #1a1f2fe5;
        position: absolute;

        &::after {
          content: "";
          position: absolute;
          width: 44px;
          height: 2px;
          left: calc(50% - 22px);
          top: calc(50% - 1px);
        }

        .build-info-item-num {
          font-size: 22px;
          font-weight: 500;
          color: #ffffff;
          text-align: center;
          line-height: 1.2;
          margin-top: 6px;
          margin-bottom: 3px;
        }

        .build-info-item-text {
          font-size: 12px;
          color: #ffffff;
          font-weight: 400;
          text-align: center;
        }

        &.blue {
          border: 2px solid #1da0d7;
          &::after {
            background: #1da0d7;
          }
        }

        &.red {
          border: 2px solid #ff0000;
          &::after {
            background: #ff0000;
          }
        }

        &.green {
          border: 2px solid #05bb4c;
          &::after {
            background: #05bb4c;
          }
        }

        &.purple {
          border: 2px solid #323e6f;
          &::after {
            background: #323e6f;
          }
        }

        &.orange {
          border: 2px solid #db5520;
          &::after {
            background: #db5520;
          }
        }

        &.yellow {
          border: 2px solid #edb32f;
          &::after {
            background: #edb32f;
          }
        }
      }
    }
  }
}
</style>
