<template>
    <div class="model-container">
        <div class="view-container" ref="threeDBox"></div>
        <div id="loading">
            <el-progress
                type="circle"
                :percentage="percent"
                :show-text="false"
                :stroke-width="14"
            ></el-progress>
        </div>
        <div id="tag" class="tag-container" style="display: none">
            <i id="close" @click="close" class="el-icon-close"></i>
            <div>视频设备：三车道入口方向顶部</div>
            <div>设备状态：正常</div>
            <div>当前时间：{{ time }}</div>
        </div>
        <div class="btn"><el-button @click="ploeRotate">起杆</el-button></div>
    </div>
</template>

<script>
import * as THREE from 'three'
import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls.js'
// import {FBXLoader} from 'three/examples/jsm/loaders/FBXLoader.js'
import {GLTFLoader} from 'three/examples/jsm/loaders/GLTFLoader.js'
import {
    CSS2DObject,
    CSS2DRenderer,
} from 'three/examples/jsm/renderers/CSS2DRenderer.js'
import {GUI} from 'three/examples/jsm/libs/lil-gui.module.min.js'
import moment from 'moment'
export default {
    name: 'ModelIndex',
    data() {
        return {
            scene: null,
            camera: null,
            controls: null,
            renderer: null,
            css2Renderer: null,
            clock: null,
            mixer: null,
            stats: null,
            time: moment().format('YYYY-MM-DD HH:mm:ss'),
            timer: null,
            chooseObj: null,
            tag: null,
            percent: 0,
            gui: null,
            pole1: null,
            pole2: null,
            pole3: null,
            pole4: null,
            pole5: null,
            pole6: null,
            poloState: {
                pole1: 0,
                pole2: 0,
                pole3: 0,
                pole4: 0,
                pole5: 0,
                pole6: 0,
            },
        }
    },
    mounted() {
        this.init()
        this.animate()
        this.timer = setInterval(() => {
            this.time = moment().format('YYYY-MM-DD HH:mm:ss')
        }, 1000)
    },
    methods: {
        ploeRotate() {
            if (this.poloState.pole1 == 1) {
                this.pole1.rotation.set(Math.PI / 2, 0, 0, 'XZY')
                this.poloState.pole1 = 0
            } else {
                this.pole1.rotation.set(0, 0, 0, 'XZY')
                this.poloState.pole1 = 1
            }
        },
        close() {
            if (this.chooseObj) {
                //把原来选中模型对应的标签和发光描边隐藏
                this.chooseObj.remove(this.tag) //从场景移除
            }
        },
        loadModel() {
            const loader = new GLTFLoader()
            loader.load(
                './static/3DModel/sfz-lh.gltf',
                (gltf) => {
                    this.percent = 100
                    console.log('控制台查看加载gltf文件返回的对象结构', gltf)
                    // console.log('gltf对象场景属性', gltf.scene)

                    // gltf.scene.traverse(function (obj) {
                    //     if (obj.isMesh) {
                    //         obj.material = new THREE.MeshLambertMaterial()
                    //         // obj.material = obj.material.clone()
                    //         obj.material.color.set(0xffff00)
                    //         obj.material.blendColor.set(0xffff00)
                    //         console.log('obj.name', obj.material)
                    //     }
                    // })

                    // 标注
                    // const tag = new CSS2DObject(div)
                    // const obj = gltf.scene.getObjectByName('设备B标注')
                    // // const obj = gltf.scene.getObjectByName('停车场标注');
                    // //tag会标注在空对象obj对应的位置
                    // obj.add(tag)

                    this.pole1 = gltf.scene.getObjectByName('G-__580656')
                    this.pole2 = gltf.scene.getObjectByName('G-__580368')
                    this.pole3 = gltf.scene.getObjectByName('G-__580584')
                    this.pole4 = gltf.scene.getObjectByName('G-__580440')
                    this.pole5 = gltf.scene.getObjectByName('G-__580512')
                    this.pole6 = gltf.scene.getObjectByName('G-__580728')

                    this.scene.add(gltf.scene)
                    document.getElementById('loading').style.display = 'none'
                },
                (xhr) => {
                    console.log((xhr.loaded / xhr.total) * 100 + '% loaded')
                    let percent = Math.floor((xhr.loaded / xhr.total) * 100)
                    if (percent < 96) {
                        this.percent = percent
                    }
                },
                (error) => {
                    console.log(error)
                }
            )
        },
        GUIControler(mesh) {
            this.gui = new GUI()

            this.gui.domElement.style.right = '0px'
            this.gui.domElement.style.top = '100px'
            this.gui.domElement.style.width = '300px'

            this.gui.add(mesh.position, 'x', -100, 100).name('X坐标').step(0.1)
            this.gui.add(mesh.position, 'y', -100, 100).name('Y坐标').step(0.1)
            this.gui.add(mesh.position, 'z', -100, 100).name('Z坐标').step(0.1)
        },
        init() {
            let container = this.$refs.threeDBox
            this.scene = new THREE.Scene()
            this.scene.background = new THREE.Color(0x597238)
            this.scene.background = new THREE.CubeTextureLoader()
                .setPath('./static/3DModel/img/skyBox/')
                .load([
                    'posx.jpg',
                    'negx.jpg',
                    'posy.jpg',
                    'negy.jpg',
                    'posz.jpg',
                    'negz.jpg',
                ])

            this.camera = new THREE.PerspectiveCamera(
                30,
                window.innerWidth / window.innerHeight,
                1,
                3000
            )
            this.camera.position.set(-87.0511, 4.7929, 0.799)
            this.camera.lookAt(0, 0, 0)

            this.loadModel() //加载模型

            // const axesHelper = new THREE.AxesHelper(100)
            // this.scene.add(axesHelper)

            const ambient = new THREE.AmbientLight(0xffffff, 1)
            this.scene.add(ambient)

            const directionalLight = new THREE.DirectionalLight(0xffffff, 5)
            // 设置光源的方向：通过光源position属性和目标指向对象的position属性计算
            directionalLight.position.set(80, 100, 50)
            // 方向光指向对象网格模型mesh，可以不设置，默认的位置是0,0,0
            // directionalLight.target = mesh
            this.scene.add(directionalLight)

            // const dirLightHelper = new THREE.DirectionalLightHelper(
            //     directionalLight,
            //     5,
            //     0xffffff
            // )
            // this.scene.add(dirLightHelper)

            // const geometry = new THREE.BoxGeometry(0.5, 0.5, 0.5)
            // //材质对象Material
            const material = new THREE.MeshLambertMaterial({
                color: 0xfff000, //设置材质颜色
                transparent: true, //开启透明
                opacity: 1, //设置透明度
            })

            // const mesh = new THREE.Mesh(geometry, material)
            // mesh.position.set(-93.9, -2.65, 4.75)
            // this.scene.add(mesh) //网格模型添加到场景中

            const cubeMaterial = [
                //side
                new THREE.MeshBasicMaterial({
                    color: 0xffffff, //设置材质颜色
                    transparent: true, //开启透明
                    opacity: 1, //设置透明度
                    side: THREE.FrontSide,
                }),
                //top
                new THREE.MeshBasicMaterial({
                    map: new THREE.TextureLoader().load(
                        '/static/3DModel/img/video.jpg'
                    ),
                    side: THREE.DoubleSide,
                }),
                //bottom
                new THREE.MeshBasicMaterial({
                    map: new THREE.TextureLoader().load(
                        '/static/3DModel/img/video.jpg'
                    ),
                    side: THREE.DoubleSide,
                }),
            ]
            const geometry = new THREE.CylinderGeometry(0.15, 0.15, 0.05)
            // geometry.rotateX(Math.PI / 2)
            // geometry.rotateZ(Math.PI / 2)
            console.log('rotate', geometry)
            const mesh = new THREE.Mesh(geometry, cubeMaterial)
            mesh.position.set(8.2, 6.9, 1.3)
            mesh.rotation.set(0, 0, Math.PI / 2, 'XZY')
            this.scene.add(mesh) //网格模型添加到场景中

            // this.GUIControler(mesh)

            const div = document.getElementById('tag')
            // HTML元素转化为threejs的CSS2模型对象
            this.tag = new CSS2DObject(div)
            // tag.position.set(-93.9, -2.65, 4.75)
            // this.scene.add(tag)

            // mesh.add(tag)
            document.getElementById('close').style.pointerEvents = 'auto'

            this.css2Renderer = new CSS2DRenderer()

            this.css2Renderer.setSize(window.innerWidth, window.innerHeight)

            container.appendChild(this.css2Renderer.domElement)

            this.css2Renderer.domElement.style.pointerEvents = 'none'
            this.css2Renderer.domElement.style.position = 'absolute'
            this.css2Renderer.domElement.style.top = '0px'

            this.renderer = new THREE.WebGLRenderer({antialias: true})
            this.renderer.setPixelRatio(window.devicePixelRatio)
            this.renderer.setSize(window.innerWidth, window.innerHeight)

            this.renderer.outputColorSpace = THREE.SRGBColorSpace //设置为SRGB颜色空间
            container.appendChild(this.renderer.domElement)

            this.controls = new OrbitControls(
                this.camera,
                this.renderer.domElement
            )
            this.controls.target = new THREE.Vector3(-65.1083, 4.2508, 0.851)
            this.controls.update()
            window.addEventListener('resize', this.onWindowResize)

            this.renderer.domElement.addEventListener('click', (event) => {
                // .offsetY、.offsetX以canvas画布左上角为坐标原点,单位px
                const px = event.offsetX
                const py = event.offsetY
                // 屏幕坐标px、py转WebGL标准设备坐标x、y
                // width、height表示canvas画布宽高度
                const x = (px / window.innerWidth) * 2 - 1
                const y = -(py / window.innerHeight) * 2 + 1

                //创建一个射线投射器`Raycaster`
                const raycaster = new THREE.Raycaster()

                //.setFromCamera()计算射线投射器`Raycaster`的射线属性.ray
                // 形象点说就是在点击位置创建一条射线，射线穿过的模型代表选中
                raycaster.setFromCamera(new THREE.Vector2(x, y), this.camera)
                //.intersectObjects([mesh1, mesh2, mesh3])对参数中的网格模型对象进行射线交叉计算
                // 未选中对象返回空数组[],选中一个对象，数组1个元素，选中两个对象，数组两个元素
                const intersects = raycaster.intersectObjects([mesh])
                console.log('射线器返回的对象', intersects)
                // intersects.length大于0说明，说明选中了模型
                if (intersects.length > 0) {
                    // 选中模型的第一个模型，设置为红色
                    // intersects[0].object.material.color.set(0xff0000)
                    intersects[0].object.add(this.tag)
                    this.chooseObj = intersects[0].object
                } else {
                    // mesh.material.color.set(0xfff000)
                    // if (this.chooseObj) {
                    //     //把原来选中模型对应的标签和发光描边隐藏
                    //     this.chooseObj.remove(tag) //从场景移除
                    // }
                }
            })
            setTimeout(() => {
                this.state = '异常'
            }, 10000)
        },
        onWindowResize() {
            const width = window.innerWidth
            const height = window.innerHeight
            this.camera.aspect = width / height
            this.renderer.setSize(width, height)
            this.css2Renderer.setSize(width, height)
            this.camera.updateProjectionMatrix()
        },
        animate() {
            requestAnimationFrame(this.animate)
            this.css2Renderer.render(this.scene, this.camera)
            this.renderer.render(this.scene, this.camera)

            // 根据相机控件可视化调试相机位置
            // console.log('controls.target', this.controls.target)
            // console.log('camera.position', this.camera.position)
        },
        showData() {
            console.log('controls.target', this.controls.target)
            console.log('camera.position', this.camera.position)
        },
    },
    beforeDestroy() {
        this.gui.domElement.style.display = 'none'
        clearInterval(this.timer)
        this.timer = null
    },
}
</script>
<style lang='scss' scoped>
.model-container{
    position: relative;
    width: 100%;
    height: 100%;
    overflow: hidden;
    .view-container {
        width: 100%;
        height: 100%;
        overflow: hidden;
    }
    .tag-container{
        width: 240px;
        padding: 20px;
        border: 2px solid #fff;
        top: -80px;
        background-color: rgba(116, 130, 143, 0.9);
        color: #fff;
        border-radius: 10px;
        // box-shadow: 0 0 10px 4px #12f4e2;
    }
    #close{
        position: absolute;
        right: 10px;
        top: 10px;
        cursor: pointer;
    }
     #close:hover{
        color: #12f4e2;
    }
    .tag-container:after{
        content: '';
        height: 20px;
        width: 2px;
        background-color: #12f4e2;
        position: absolute;
        top: 100%;
        left: calc(50% - 1px);
    }
    .tag-container:before{
        content: '';
        height: 10px;
        width: 10px;
        border-radius: 5px;
        background-color: #12f4e2;
        position: absolute;
        top: calc(100% + 20px);
        left: calc(50% - 5px);
    }
    #loading{
        position: absolute;
        left: 0;
        top: 0;
        width: 100%;
        height: 100%;
        overflow: hidden;
        color: #fff;
        background-color: rgba(40, 85, 128, 0.9);
        display: flex;
        justify-content: center;
        align-items: center;
    }
    .btn{
        position: absolute;
        left: 50%;
        bottom: 20px;
        transform: translateX(-50%);
        z-index: 999;
    }
}

</style>