SOURCE

console 命令行工具 X clear

                    
>
console

const data = [
    {
        name: 'A部门',
        value: 150,
        itemStyle: { color: 'red' }
    },
     {
        name: 'B部门',
        value: 450,
        itemStyle: { color: 'green' },
        selected: false
    },
     {
        name: 'C部门',
        value: 750,
        itemStyle: { color: 'blue' }
    }
]

function getSeries(data, k) {
    let sum = 0
    const series = data.map(i => {
        sum += i.value
        return {
            type: 'surface',
            name: i.name,
            parametric: true,
            value: i.value,
            wireframe: { show: false },
            itemStyle: { ...i.itemStyle },
            pieData: {...i, k},
            zlevel: 1
        }
    })
    let begin = 0
    let end = 0
    for (const item of series) {
        end = begin + item.value
        const startRatio = begin / sum
        const endRatio = end / sum
        item.pieData.startRatio = startRatio
        item.pieData.endRatio = endRatio
        item.parametricEquation = getEq(item)
        begin = end
    }

    const temp = data.map(i => {
        return {
            ...i,
            itemStyle: { ...i.itemStyle, color: 'rgba(255, 0, 0, 0)'}
        }
    })
    series.push({
        type: 'pie',
        startAngle: 10,
        clockwise: false,
        data: temp,
        labelLine: { show: true, lineStyle: { color: 'black' } },
        center: ['50%', '54%'],
        radius: [0, '50%'],
        z: 0
    })
    return series
}

function getEq(item) {
    const { startRatio, endRatio, isSelected, k } = item.pieData
    const s = startRatio * 2 * Math.PI
    const e = endRatio * 2 * Math.PI
    const h = isSelected ? 2 : 1
    return {
        u: {
            min: -Math.PI,
            max: 3 * Math.PI,
            step: Math.PI / 32
        },
        v: {
            min: 0,
            max: 2 * Math.PI,
            step: Math.PI / 32
        },
        x: function(u, v) {
            if (u < s) {
                return Math.cos(s) * (1 + Math.cos(v) * k)
            } else if (u > e) {
                return Math.cos(e) * (1 + Math.cos(v) * k)
            }
            return Math.cos(u) * (1 + Math.cos(v) * k)
        },
        y: function(u, v) {
            if (u < s) {
                return Math.sin(s) * (1 + Math.cos(v) * k)
            } else if (u > e) {
                return Math.sin(e) * (1 + Math.cos(v) * k)
            }
            return Math.sin(u) * (1 + Math.cos(v) * k)
        },
        z: function(u, v) {
            if (u < -Math.PI / 2) {
                return Math.sin(u)
            } else if (u > Math.PI * 2.5) {
                return Math.sin(u)
            }
            return Math.sin(v) > 0 ? h : -1
        }
    }
}

const series = getSeries(data, 1/3)
// console.log('===series', series)
const option = {
    grid3D: {
        show: false,
        boxHeight: 20,
        viewControl: { 
            alpha: 40, 
            beta: 0, 
            distance: 250,
            autoRotate: false,
            rotateSensitivity: 0,
            zoomSensitivity: 0,
            panSensitivity: 0
        }
    },
    xAxis3D: { min: -1, max: 1 },
    yAxis3D: { min: -1, max: 1 },
    zAxis3D: { min: -1, max: 1 },
    series
}
const dom = document.querySelector('#chart')
const chart = echarts.init(dom)
chart.setOption(option)

let hoverIndex = -1
chart.on('mouseover', (params) => {
    // console.log('hover', params)
    const subtype = params.componentSubType
    let idx = -1
    if (subtype === 'surface') {
        idx = params.seriesIndex
    } else if (subtype === 'pie') {
        idx = params.dataIndex
    }
    if (hoverIndex === idx) {
        return
    }
    if (hoverIndex !== -1) {
        const prevSerie = series[hoverIndex]
        prevSerie.pieData.isSelected = false
        prevSerie.parametricEquation = getEq(prevSerie)
        series.splice(hoverIndex,1, prevSerie)
    }
    hoverIndex = idx
    const serie = series[idx]
    if (serie) {
        serie.pieData = { ...serie.pieData, isSelected: true }
        serie.parametricEquation = getEq(serie)
        const tmpList = [...series]
        tmpList.splice(idx, 1, serie)
        chart.setOption({
            series: tmpList
        })
    }
})

chart.on('globalout', () => {
    if (hoverIndex !== -1) {
        const serie = series[hoverIndex]
        serie.pieData = { ...serie.pieData, isSelected: false }
        const list = [...series]
        list.splice(hoverIndex, 1, serie)
        chart.setOption({
            series: list
        })
    }
})
<div id="chart"></div>
#chart {
    width: 300px;
    height:300px;
    border: 1px solid red;
}

本项目引用的自定义外部资源