echarts水滴图配置
function initChart () {
const chartDom = document.getElementById('xxx')
chartDom.removeAttribute('_echarts_instance_')
echarts.init(chartDom).dispose()
const myChart = markRaw(echarts.init(chartDom))
const value = 50
const option = {
series: [
{
type: 'liquidFill',
radius: '100%',
data: [value / 100, value / 100],
backgroundStyle: {
color: {
type: 'radial',
x: 0.5,
y: 0.5,
r: 0.5,
colorStops: [
{
offset: 0,
color: 'rgba(0,24,55, 0)'
},
{
offset: 1,
color: 'rgba(147,255,252,0.24)'
}
],
globalCoord: false
}
},
outline: {
borderDistance: 2,
itemStyle: {
borderWidth: 2,
borderColor: '#155BA7'
}
},
color: [
{
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{
offset: 1,
color: color1
},
{
offset: 0,
color: color2
}
],
globalCoord: false
},
{
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{
offset: 1,
color: color1
},
{
offset: 0,
color: color2
}
],
globalCoord: false
}
],
label: {
normal: {
formatter: value + '%',
fontSize: 18,
color: '#fff'
}
}
}
]
}
window.addEventListener('resize', function () {
if (myChart) myChart .resize()
})
option && myChart.setOption(option)
}
封装3D环形图
<!-- 3D饼图 -->
<template>
<div :id="props.chartData.id" class="pieChart"></div>
</template>
<script setup>
import * as echarts from 'echarts'
import 'echarts-gl'
import { ref, defineProps, defineExpose, markRaw } from 'vue'
const props = defineProps({
chartData: {
type: Object
},
projectId: Number,
siteCodeStatistics: Function
})
function init () {
const chartDom = document.getElementById(props.chartData.id)
chartDom.removeAttribute('_echarts_instance_')
echarts.dispose(chartDom)
const myChart = markRaw(echarts.init(chartDom))
const option = getPie3D(props.chartData.pieData, props.chartData.ratio)
window.addEventListener('resize', function () {
myChart.resize()
})
myChart.setOption(option)
myChart.off('legendselectchanged')
myChart.on('legendselectchanged', legendselectchanged)
let hoveredIndex = ''
myChart.on('mouseover', function (params) {
let isSelected
let isHovered
let startRatio
let endRatio
let k
let i
if (hoveredIndex === params.seriesIndex) {
} else {
if (hoveredIndex !== '') {
isSelected = option.series[hoveredIndex].pieStatus.selected
isHovered = false
startRatio = option.series[hoveredIndex].pieData.startRatio
endRatio = option.series[hoveredIndex].pieData.endRatio
k = option.series[hoveredIndex].pieStatus.k
i = option.series[hoveredIndex].pieData.value
option.series[hoveredIndex].parametricEquation = getParametricEquation(
startRatio,
endRatio,
isSelected,
isHovered,
k,
i
)
option.series[hoveredIndex].pieStatus.hovered = isHovered
hoveredIndex = ''
}
if (params.seriesName !== 'mouseoutSeries') {
isSelected = option.series[params.seriesIndex].pieStatus.selected
isHovered = true
startRatio = option.series[params.seriesIndex].pieData.startRatio
endRatio = option.series[params.seriesIndex].pieData.endRatio
k = option.series[params.seriesIndex].pieStatus.k
option.series[params.seriesIndex].parametricEquation = getParametricEquation(
startRatio,
endRatio,
isSelected,
isHovered,
k,
option.series[params.seriesIndex].pieData.value + 5
)
option.series[params.seriesIndex].pieStatus.hovered = isHovered
hoveredIndex = params.seriesIndex
}
myChart.setOption(option)
}
})
myChart.on('globalout', function () {
if (hoveredIndex !== '') {
const isSelected = option.series[hoveredIndex].pieStatus.selected
const isHovered = false
const k = option.series[hoveredIndex].pieStatus.k
const startRatio = option.series[hoveredIndex].pieData.startRatio
const endRatio = option.series[hoveredIndex].pieData.endRatio
const i =
option.series[hoveredIndex].pieData.value
option.series[hoveredIndex].parametricEquation = getParametricEquation(
startRatio,
endRatio,
isSelected,
isHovered,
k,
i
)
option.series[hoveredIndex].pieStatus.hovered = isHovered
hoveredIndex = ''
}
myChart.setOption(option)
})
}
function getParametricEquation (
startRatio,
endRatio,
isSelected,
isHovered,
k,
h
) {
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 (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 (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 (u, v) {
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
}
}
}
function getPie3D (pieData, internalDiameterRatio) {
const series = []
let sumValue = 0
let startValue = 0
let endValue = 0
const legendData = []
const k =
typeof internalDiameterRatio !== 'undefined'
? (1 - internalDiameterRatio) / (1 + internalDiameterRatio)
: 1 / 3
for (let i = 0; i < pieData.length; i += 1) {
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
}
}
if (typeof pieData[i].itemStyle !== 'undefined') {
const { itemStyle } = pieData[i]
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)
}
for (let i = 0; i < series.length; i += 1) {
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,
props.chartData.boxHeight
? props.chartData.boxHeight
: series[i].pieData.value
)
startValue = endValue
legendData.push(series[i].name)
}
const option = {
tooltip: {
formatter: (params) => {
if (params.seriesName !== 'mouseoutSeries') {
return `${
params.seriesName
}<br/><span style="display:inline-block;margin-right:5px;border-radius:10px;width:10px;height:10px;background-color:${
params.color
};"></span>${option.series[params.seriesIndex].pieData.value}个`
}
return ''
}
},
legend: props.chartData.legend,
xAxis3D: {
min: -1,
max: 1
},
yAxis3D: {
min: -1,
max: 1
},
zAxis3D: {
min: -1,
max: 'dataMax'
},
grid3D: {
show: false,
boxHeight: props.chartData.boxHeight ? props.chartData.boxHeight : 35,
top: 'center',
left: '-20%',
viewControl: {
alpha: 13,
rotateSensitivity: 1,
zoomSensitivity: 0,
panSensitivity: 0,
autoRotate: true,
distance: 170
},
postEffect: {
enable: false,
bloom: {
enable: true,
bloomIntensity: 0.1
},
SSAO: {
enable: true,
quality: 'medium',
radius: 2
},
temporalSuperSampling: {
enable: true
}
}
},
series
}
if (props.chartData.grid3D) {
Object.assign(option.grid3D, props.chartData.grid3D)
}
return option
}
const selected = ref()
function legendselectchanged (params) {
const arr = Object.entries(params.selected).filter(([key, val]) => val === true)
const obj = Object.fromEntries(arr)
const keysArr = Object.keys(obj)
selected.value = keysArr.join()
props.siteCodeStatistics(props.projectId, selected.value)
}
defineExpose({ init, selected })
</script>
<style lang="less" scoped>
.pieChart {
width: 100%;
height: 100%;
}
</style>
3D环形图传入数据示例
const chartData = reactive({
id: 'pieChart',
pieData: [
{
name: '正常状态',
value: 40,
itemStyle: {
color: 'rgba(0, 255, 210, 1)'
}
},
{
name: '三级预警',
value: 20,
itemStyle: {
color: 'rgba(255, 239, 0, 1)'
}
},
{
name: '二级预警',
value: 10,
itemStyle: {
color: 'rgba(246, 138, 95, 1)'
}
},
{
name: '一级预警',
value: 20,
itemStyle: {
color: 'rgba(238, 46, 53, 1)'
}
},
{
name: '数据中断',
value: 10,
itemStyle: {
color: 'rgba(187, 191, 195, 1)'
}
}
],
ratio: 0.59,
legend: {
show: true,
right: '10%',
top: 'center',
icon: 'circle',
itemWidth: 10,
width: 70,
textStyle: {
color: 'auto',
fontSize: 14,
rich: {
a: {
width: 70,
fontSize: 14,
color: 'rgba(255, 255, 255, 1)'
},
b: {
width: 50,
fontSize: 14,
color: 'rgba(255, 255, 255, 1)'
}
}
},
formatter: (name) => {
const data = chartData.pieData
let target
let v
for (let i = 0; i < data.length; i++) {
if (data[i].name === name) {
target = data[i].value
v = ((target / total.value) * 100).toFixed(2) + '%'
return `{a|${name}}{b|${target}个}${v}`
}
}
}
}
})