lcw
This commit is contained in:
@ -1,109 +1,169 @@
|
||||
<template>
|
||||
<div ref="chartRef" :style="{ width: '100%', height: '400px' }"></div>
|
||||
<div ref="chartRef" :style="{ width: '100%', height: '100%' }"></div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent, onMounted, ref } from 'vue'
|
||||
<script setup>
|
||||
import { defineComponent, onMounted, onUnmounted, ref, watch } from 'vue'
|
||||
import * as echarts from 'echarts'
|
||||
import 'echarts-gl'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'Pie3D',
|
||||
setup() {
|
||||
const chartRef = ref(null)
|
||||
let chart = null
|
||||
|
||||
const initChart = () => {
|
||||
if (!chartRef.value) return
|
||||
|
||||
chart = echarts.init(chartRef.value)
|
||||
const option = {
|
||||
backgroundColor: '#1a213c',
|
||||
tooltip: {
|
||||
formatter: '{b}: {c} ({d}%)',
|
||||
backgroundColor: 'rgba(0,0,0,0.7)',
|
||||
borderColor: '#1a213c',
|
||||
textStyle: {
|
||||
color: '#fff'
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
orient: 'vertical',
|
||||
right: '5%',
|
||||
top: 'center',
|
||||
textStyle: {
|
||||
color: '#fff'
|
||||
},
|
||||
formatter: function(name) {
|
||||
const data = option.series[0].data
|
||||
const total = data.reduce((sum, item) => sum + item.value, 0)
|
||||
const target = data.find(item => item.name === name)
|
||||
const percentage = ((target.value / total) * 100).toFixed(0)
|
||||
return `${name} ${target.value}`
|
||||
}
|
||||
},
|
||||
series: [{
|
||||
type: 'pie',
|
||||
radius: ['30%', '55%'],
|
||||
center: ['40%', '50%'],
|
||||
roseType: false,
|
||||
zlevel: 10,
|
||||
startAngle: 35,
|
||||
selectedMode: 'single',
|
||||
selectedOffset: 10,
|
||||
data: [
|
||||
{ value: 18, name: '红色', itemStyle: { color: '#ff4d4f' } },
|
||||
{ value: 13, name: '橙色', itemStyle: { color: '#ff7a45' } },
|
||||
{ value: 17, name: '黄色', itemStyle: { color: '#ffc53d' } },
|
||||
{ value: 2, name: '蓝色', itemStyle: { color: '#40a9ff' } }
|
||||
],
|
||||
label: {
|
||||
show: true,
|
||||
formatter: '{d}%',
|
||||
color: '#fff',
|
||||
position: 'outside',
|
||||
fontSize: 14,
|
||||
fontWeight: 'bold'
|
||||
},
|
||||
emphasis: {
|
||||
focus: 'self',
|
||||
scaleSize: 10,
|
||||
itemStyle: {
|
||||
shadowBlur: 20,
|
||||
shadowOffsetX: 5,
|
||||
shadowOffsetY: 5,
|
||||
shadowColor: 'rgba(0, 0, 0, 0.5)'
|
||||
}
|
||||
},
|
||||
itemStyle: {
|
||||
borderRadius: 4,
|
||||
borderColor: '#1a213c',
|
||||
borderWidth: 2
|
||||
},
|
||||
animationType: 'scale',
|
||||
animationEasing: 'elasticOut',
|
||||
animationDelay: function (idx) {
|
||||
return Math.random() * 200;
|
||||
}
|
||||
}]
|
||||
}
|
||||
|
||||
chart.setOption(option)
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
initChart()
|
||||
window.addEventListener('resize', () => {
|
||||
chart && chart.resize()
|
||||
})
|
||||
})
|
||||
|
||||
return {
|
||||
chartRef
|
||||
}
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
color: {
|
||||
type: Array,
|
||||
default:() => []
|
||||
}
|
||||
})
|
||||
const chartRef = ref(null)
|
||||
let chart = null
|
||||
const initChart = () => {
|
||||
if (!chartRef.value) return
|
||||
chart = echarts.init(chartRef.value)
|
||||
const option = {
|
||||
// backgroundColor: '#1a213c',
|
||||
tooltip: {
|
||||
formatter: '{b}: {c} ({d}%)',
|
||||
backgroundColor: 'rgba(0,0,0,0.7)',
|
||||
borderColor: '#1a213c',
|
||||
textStyle: {
|
||||
color: '#fff'
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
orient: 'vertical',
|
||||
right: '0%',
|
||||
top: 'center',
|
||||
textStyle: {
|
||||
color: '#fff'
|
||||
},
|
||||
formatter: function (name) {
|
||||
const data = option.series[0].data
|
||||
const total = data.reduce((sum, item) => sum + item.value, 0)
|
||||
const target = data.find(item => item.name === name)
|
||||
const percentage = ((target.value / total) * 100).toFixed(0)
|
||||
return `${name} ${target.value}`
|
||||
}
|
||||
},
|
||||
series: [{
|
||||
type: 'pie',
|
||||
radius: ['30%', '55%'],
|
||||
center: ['40%', '50%'],
|
||||
roseType: false,
|
||||
zlevel: 10,
|
||||
startAngle: 35,
|
||||
selectedMode: 'single',
|
||||
selectedOffset: 10,
|
||||
data:[...props.data],
|
||||
label: {
|
||||
show: true,
|
||||
formatter: '{d}%',
|
||||
color: '#fff',
|
||||
position: 'outside',
|
||||
fontSize: 14,
|
||||
fontWeight: 'bold'
|
||||
},
|
||||
emphasis: {
|
||||
focus: 'self',
|
||||
scaleSize: 10,
|
||||
itemStyle: {
|
||||
shadowBlur: 20,
|
||||
shadowOffsetX: 5,
|
||||
shadowOffsetY: 5,
|
||||
shadowColor: 'rgba(0, 0, 0, 0.5)'
|
||||
}
|
||||
},
|
||||
itemStyle: {
|
||||
borderRadius: 4,
|
||||
borderColor: '#1a213c',
|
||||
borderWidth: 2
|
||||
},
|
||||
// 启用全局动画控制器
|
||||
animation: true,
|
||||
// 关键:设置animationDelayUpdate确保数据更新时也有动画
|
||||
animationDelayUpdate: function (idx) {
|
||||
return idx * 300;
|
||||
},
|
||||
// 逐个显示的动画效果 - 改为从透明到不透明的过渡效果
|
||||
animationType: 'opacity',
|
||||
animationEasing: 'cubicOut',
|
||||
|
||||
// 关键:设置初始样式,让每个扇形从透明状态开始
|
||||
// 使用动画帧序列来控制动画过程
|
||||
animation: true,
|
||||
animationDuration: 1000,
|
||||
animationDelay: function (idx) {
|
||||
// 按照索引顺序依次显示,设置更明显的延迟
|
||||
return idx * 400;
|
||||
},
|
||||
|
||||
// 动画开始前的回调,确保动画效果
|
||||
animationBegin: function() {
|
||||
// 可以在这里进行额外的动画初始化
|
||||
return 0;
|
||||
},
|
||||
|
||||
// 动画帧序列,控制每个关键帧的样式
|
||||
animationFrame: function (idx, percent) {
|
||||
// percent参数是从0到1的动画进度
|
||||
return {
|
||||
opacity: percent,
|
||||
scale: 0.8 + percent * 0.2 // 从0.8放大到1
|
||||
};
|
||||
}
|
||||
}],
|
||||
media: [
|
||||
{
|
||||
query: { minAspectRatio: 1 },
|
||||
option: {
|
||||
series: [
|
||||
{ center: ['36%', '50%'] },
|
||||
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
chart.setOption(option)
|
||||
}
|
||||
onMounted(() => {
|
||||
initChart()
|
||||
window.addEventListener('resize', () => {
|
||||
chart && chart.resize()
|
||||
})
|
||||
})
|
||||
|
||||
// 监听数据变化,确保动画在数据更新时也能触发
|
||||
watch(
|
||||
() => props.data,
|
||||
(newData) => {
|
||||
if (chart && newData && newData.length > 0) {
|
||||
// 使用clear方法强制重新渲染并触发动画
|
||||
chart.clear()
|
||||
initChart()
|
||||
}
|
||||
},
|
||||
{ deep: true }
|
||||
)
|
||||
|
||||
// 组件卸载时清理资源
|
||||
const cleanup = () => {
|
||||
if (chart) {
|
||||
chart.dispose()
|
||||
chart = null
|
||||
}
|
||||
window.removeEventListener('resize', () => {
|
||||
chart && chart.resize()
|
||||
})
|
||||
}
|
||||
|
||||
// 组件卸载时执行清理
|
||||
onUnmounted(() => {
|
||||
cleanup()
|
||||
})
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
||||
<style scoped></style>
|
||||
|
||||
Reference in New Issue
Block a user