
页面
<template>
<div id="myChart" ref="myChart" class="pie-chart"></div>
</template>
<script lang='ts' setup>
import { getPie3D, getParametricEquation } from "../utils/largeScreen"
import { ref, reactive, getCurrentInstance, onMounted } from 'vue'
import * as echarts from "echarts";
onMounted(() => {
intit()
})
function intit() {
const charEle = document.getElementById('myChart') as HTMLElement;
const echarts1 = echarts.init(charEle);
const optionData = [
{
value: 1089, name: '配发'
},
{
value: 735, name: '销毁'
},
{
value: 580, name: '借用'
},
{
value: 484, name: '维修'
},
{
value: 300, name: '其他'
}
]
const option = getPie3D(optionData, 0.8, 240, 180, 50, 0.6)
echarts1.setOption(option)
option.series.push({
backgroundColor: '#fff',
type: 'pie',
label: {
show: false
},
startAngle: -20,
clockwise: false,
avoidLabelOverlap: false,
radius: ['20%', '50%'],
center: ['50%', '50%'],
data: optionData,
itemStyle: {
opacity: 0,
color: (params: any) => {
let colorList = [
{
colorStart: '#0981FF',
colorEnd: '#83A1FF'
},
{
colorStart: '#63BBF0',
colorEnd: '#071829'
},
{
colorStart: '#1A171C',
colorEnd: '#DEC6FF'
},
{
colorStart: '#161510',
colorEnd: '#FFF189'
}, {
colorStart: '#0E1111',
colorEnd: '#FF9090'
}
]
return new echarts.graphic.LinearGradient(1, 0, 0, 0, [{
offset: 0,
color: colorList[params.dataIndex]['colorStart']
}, {
offset: 1,
color: colorList[params.dataIndex]['colorEnd']
}])
}
},
labelLine: {
show: false
},
})
echarts1.setOption(option)
window.onresize = function () {
echarts1.resize()
}
}
</script>
<style lang='less' scoped>
.pie-chart {
width: 100%;
height: 100%;
}
</style>
largeScreen.ts
const getPie3D = (pieData: any[], internalDiameterRatio: number, distance: any, alpha: any, pieHeight: any, opacity =0.8) => {
const series = []
let sumValue = 0
let startValue = 0
let endValue = 0
let legendData = []
let legendBfb: { name: any; value: string | boolean }[] = []
const k = 1 - internalDiameterRatio
pieData.sort((a: { value: number }, b: { value: number }) => {
return b.value - a.value
})
for (let i = 0; i < pieData.length; i++) {
console.log(pieData[i], "pieData[i]")
sumValue += pieData[i].value
const 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: ['50%', '50%']
}
console.log(pieData[i].itemStyle, "pieData[i].itemStyle")
if (typeof pieData[i].itemStyle !== 'undefined') {
console.log(pieData[i].itemStyle, "pieData[i].itemStyle")
const itemStyle = {}
itemStyle.color = typeof pieData[i].itemStyle.color !== 'undefined'
? pieData[i].itemStyle.color
: opacity
itemStyle.opacity =
typeof pieData[i].itemStyle.opacity !== 'undefined'
? pieData[i].itemStyle.opacity
: opacity
seriesItem.itemStyle = itemStyle
}
series.push(seriesItem)
}
legendData = []
legendBfb = []
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
const bfb = fomatFloat(series[i].pieData.value / sumValue, 4)
legendData.push({
name: series[i].name,
value: bfb
})
legendBfb.push({
name: series[i].name,
value: bfb
})
}
const boxHeight = getHeight3D(series, pieHeight)
const option = {
color: ["#3747B0", "#63BBF0", "#DFC6FF", "#FFD156", "#AD6565"],
legend: {
left: '70%',
top: 'middle',
orient: 'vertical',
itemWidth: 8,
itemHeight: 8,
textStyle: {
color: "#fff",
fontSize:fontSize(0.14),
fontFamily: "DINAlternateBold"
},
show: true,
data: legendData,
itemGap: 10,
formatter: function (param: any) {
const item = legendBfb.filter(item => item.name === param)[0]
const bfs = fomatFloat(item.value * 100, 2) + '%'
return `${item.name} ${bfs}`
},
},
labelLine: {
show: false,
},
label: {
show: false,
position: 'outside',
formatter: '{b} \n{c} {d}%'
},
tooltip: {
show: false,
},
xAxis3D: {
min: -0.7,
max: 1
},
yAxis3D: {
min: -0.7,
max: 1
},
zAxis3D: {
min: -0.7,
max: 1
},
grid3D: {
show: false,
boxWidth: 100,
boxHeight: boxHeight,
viewControl: {
alpha,
distance,
rotateSensitivity: 0,
zoomSensitivity: 0,
panSensitivity: 0,
autoRotate: false
}
},
series: series
}
return option
}
const getParametricEquation = (startRatio: number, endRatio: number, isSelected: boolean, isHovered: boolean, k: number, h: number) => {
const midRatio = (startRatio + endRatio) / 2
const startRadian = startRatio * Math.PI * 2
const endRadian = endRatio * Math.PI * 2
const midRadian = midRatio * Math.PI * 2
if (startRatio === 0 && endRatio === 1) {
isSelected = false
}
k = typeof k !== 'undefined' ? k : 1 / 3
const offsetX = isSelected ? Math.cos(midRadian) * 0.1 : 0
const offsetY = isSelected ? Math.sin(midRadian) * 0.1 : 0
const 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: number, v: number) {
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: number, v: number) {
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: number, v: number) {
if (u < -Math.PI * 0.5) {
return Math.sin(u)
}
if (u > Math.PI * 2.5) {
return Math.sin(u) * h * 0.1
}
return Math.sin(v) > 0 ? 1 * h * 0.1 : -1
}
}
}
const getHeight3D = (series: any[], height: number) => {
series.sort((a: { pieData: { value: number } }, b: { pieData: { value: number } }) => {
return b.pieData.value - a.pieData.value
})
return (height * 25) / series[0].pieData.value
}
const fomatFloat = (num: any, n: number) => {
let f = parseFloat(num)
if (isNaN(f)) {
return false
}
f = Math.round(num * Math.pow(10, n)) / Math.pow(10, n)
let s = f.toString()
let rs = s.indexOf('.')
if (rs < 0) {
rs = s.length
s += '.'
}
while (s.length <= rs + n) {
s += '0'
}
return s
}
function fontSize(res: number) {
let clientWidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
if (!clientWidth) return;
let fontSize = 100 * (clientWidth / 3840);
return res * fontSize;
}
export { getPie3D, getParametricEquation }