<!--
 * @Company: 沈阳信诚科技
 * @Email: html_venustar@163.com
 * @Author: Liuqiming
 * @Description: 
 * @LastEditors: Liuqiming
 * @LastEditTime: 2024-03-15 15:51:03
 * @Date: 2024-03-04 16:45:17
-->
<template>
  <div ref="echart" class="echartDiv"></div>
</template>
 
<script>
import * as echarts from 'echarts'
import 'echarts-gl'
import { onMounted, toRefs, ref, reactive, watch } from 'vue'
export default {
  props: {
    seriesData:{
      type: Array,
      default: () => [
        { value: 40, name: 'rose 1' },
        { value: 33, name: 'rose 2' },
        { value: 28, name: 'rose 3' },
        { value: 22, name: 'rose 4' },
      ]
    }
  },
  setup(props, context) {
    let state = reactive({
      echart: ref(),
    })
    const myChart = shallowRef(null)
    watch(props, ()=>{
      echartInit()
    }, { deep: true })
    const echartInit = () => {
      if(myChart.value && myChart.value != null && myChart.value != "" && myChart.value != undefined) {
        myChart.value.dispose();//销毁
      }
      myChart.value = echarts.init(state.echart)
      const series = getPie3D(optionsData, 0.8, 240, 28, 26, 0.5)
      // 准备待返回的配置项，把准备好的 legendData、series 传入。
      let option = {
        legend: {
          show: true,
          tooltip: {
            show: false,
          },
          // data: ['甲', '乙 25%', '丙 25%', '丁 25%'],
          bottom: 10,
          left: 'center',
          itemGap: 14,
          itemHeight: 8,
          itemWidth: 17,
          // right: '2%',
          textStyle: {
            color: '#fff',
            fontSize: 12,
          },
        },
        animation: true,
        title: {
          x: 'center',
          top: '20',
          textStyle: {
            color: '#fff',
            fontSize: 22,
          },
        },
        labelLine: {
          show: true,
          lineStyle: {
            color: '#7BC0CB',
          },
          normal: {
            show: true,
            length: 10,
            length2: 10,
          },
        },
        label: {
          show: true,
          position: 'outside',
          formatter: '{b} \n{d}%',
          textStyle: {
            color: '#fff',
            fontSize: '14px',
          },
        },
        xAxis3D: {
          min: -1,
          max: 1,
        },
        yAxis3D: {
          min: -1,
          max: 1,
        },
        zAxis3D: {
          min: -1,
          max: 1,
        },
        grid3D: {
          show: false,
          boxHeight: 1,
          top:-20,
          // bottom: '50%',
          viewControl: {
            distance: 130,
            alpha: 25,
            beta: 60,
            autoRotate: true, // 自动旋转
          },
        },
        series: series,
      }
      // 使用刚指定的配置项和数据显示图表。
      myChart.value.setOption(option)
    }

    function getParametricEquation(
      startRatio,
      endRatio,
      isSelected,
      isHovered,
      k,
      height,
    ) {

      // 计算
      let midRatio = (startRatio + endRatio) / 2

      let startRadian = startRatio * Math.PI * 2
      let endRadian = endRatio * Math.PI * 2
      let midRadian = midRatio * Math.PI * 2

      // 如果只有一个扇形，则不实现选中效果。
      if (startRatio === 0 && endRatio === 1) {
        isSelected = false
      }

      // 通过扇形内径/外径的值，换算出辅助参数 k（默认值 1/3）
      k = typeof k !== 'undefined' ? k : 1 / 3

      // 计算选中效果分别在 x 轴、y 轴方向上的位移（未选中，则位移均为 0）
      let offsetX = isSelected ? Math.cos(midRadian) * 0.1 : 0
      let offsetY = isSelected ? Math.sin(midRadian) * 0.1 : 0

      // 计算高亮效果的放大比例（未高亮，则比例为 1）
      let hoverRate = isHovered ? 1.05 : 1

      // 返回曲面参数方程
      return {
        u: {
          min: -Math.PI,
          max: Math.PI * 3,
          step: Math.PI / 32,
        },
        v: {
          min: 0,
          max: Math.PI * 2,
          step: Math.PI / 20,
        },
        x: function (u, v) {
          if (u < startRadian) {
            return (
              offsetX +
              Math.cos(startRadian) * (1 + Math.cos(v) * k) * hoverRate
            )
          }
          if (u > endRadian) {
            return (
              offsetX + Math.cos(endRadian) * (1 + Math.cos(v) * k) * hoverRate
            )
          }
          return offsetX + Math.cos(u) * (1 + Math.cos(v) * k) * hoverRate
        },
        y: function (u, v) {
          if (u < startRadian) {
            return (
              offsetY +
              Math.sin(startRadian) * (1 + Math.cos(v) * k) * hoverRate
            )
          }
          if (u > endRadian) {
            return (
              offsetY + Math.sin(endRadian) * (1 + Math.cos(v) * k) * hoverRate
            )
          }
          return offsetY + Math.sin(u) * (1 + Math.cos(v) * k) * hoverRate
        },
        z: function (u, v) {
          if (u < -Math.PI * 0.5) {
            return Math.sin(u)
          }
          if (u > Math.PI * 2.5) {
            return Math.sin(u)
          }
          return Math.sin(v) > 0 ? 1 * height : -1
        },
      }
    }
    // 生成模拟 3D 饼图的配置项
    function getPie3D(pieData, internalDiameterRatio) {
      let series = []
      let sumValue = 0
      let startValue = 0
      let endValue = 0
      let legendData = []
      let k =
        typeof internalDiameterRatio !== 'undefined'
          ? (1 - internalDiameterRatio) / (1 + internalDiameterRatio)
          : 1 / 3

      // 为每一个饼图数据，生成一个 series-surface 配置
      for (let i = 0; i < pieData.length; i++) {
        sumValue += pieData[i].value

        let seriesItem = {
          name: typeof pieData[i].name === 'undefined' ? `series${i}` : pieData[i].name,
          type: 'surface',
          parametric: true,
          wireframe: {
            show: false,
          },
          pieData: pieData[i],
          pieStatus: {
            selected: false,
            hovered: false,
            k: k,
          },
          center: ["10%", "30%"],
        }

        if (typeof pieData[i].itemStyle != 'undefined') {
          let itemStyle = {}

          typeof pieData[i].itemStyle.color != 'undefined'
            ? (itemStyle.color = pieData[i].itemStyle.color)
            : null
          typeof pieData[i].itemStyle.opacity != 'undefined'
            ? (itemStyle.opacity = pieData[i].itemStyle.opacity)
            : null

          seriesItem.itemStyle = itemStyle
        }
        series.push(seriesItem)
      }

      // 使用上一次遍历时，计算出的数据和 sumValue，调用 getParametricEquation 函数，
      // 向每个 series-surface 传入不同的参数方程 series-surface.parametricEquation，也就是实现每一个扇形。
      for (let i = 0; i < series.length; i++) {
        endValue = startValue + series[i].pieData.value
        series[i].pieData.startRatio = startValue / sumValue
        series[i].pieData.endRatio = endValue / sumValue
        series[i].parametricEquation = getParametricEquation(
          series[i].pieData.startRatio,
          series[i].pieData.endRatio,
          false,
          false,
          k,
          series[i].pieData.value,
        )

        startValue = endValue

        legendData.push(series[i].name)
      }
      return series
    }
    const colors = [
      'rgba(24, 254, 254, 0.7)',
      'rgba(255, 222, 77, 0.7)',
      'rgba(6, 247, 161, 0.7)',
      'rgba(0, 138, 255, 0.7)'
    ]
    // 传入数据生成 option
    let sumNum = 0
    props?.seriesData?.forEach(item => {
      sumNum += item.value
    })
    const optionsData = props?.seriesData?.map((item,i) => {
      return {
        name: item.name + ' ' + parseInt(item.value / sumNum * 100) + '%',
        value: item.value,
        itemStyle: {
          color: colors[i],
        },
      }
    })
    // [
    //   {
    //     name: '甲 25%',
    //     value: 4256,
    //     itemStyle: {
    //       color: 'rgba(24, 254, 254, 0.7)',
    //     },
    //   },

    //   {
    //     name: '乙 25%',
    //     value: 2356,
    //     itemStyle: {
    //       color: 'rgba(255, 222, 77, 0.7)',
    //     },
    //   },
    //   {
    //     name: '丙 25%',
    //     value: 2018,
    //     itemStyle: {
    //       color: 'rgba(6, 247, 161, 0.7)',
    //     },
    //   },
    //   {
    //     name: '丁 25%',
    //     value: 1998,
    //     itemStyle: {
    //       color: 'rgba(0, 138, 255, 0.7)',
    //     },
    //   },
    // ]

    //挂载
    onMounted(() => {
      echartInit()
      window.addEventListener('resize',() => {
        myChart.value.resize()
      })
    })

    return {
      ...toRefs(state),
      echartInit,
    }
  },
}
</script>
 
<style lang='scss' scoped>
.echartDiv {
  width: 100%;
  height: 100%;
}
</style>
