refactor: ts+echarts+resize方式简化

Former-commit-id: 0a85c26f3c27843cd4e20b367e62d1f9b40370d9
This commit is contained in:
haoxr
2023-01-25 18:53:14 +08:00
parent 235fea1070
commit 8c5537c49e
6 changed files with 283 additions and 456 deletions

View File

@@ -1,73 +0,0 @@
import { ref } from 'vue';
export default function () {
const chart = ref<any>();
const sidebarElm = ref<Element>();
const chartResizeHandler = () => {
if (chart.value) {
chart.value.resize();
}
};
const sidebarResizeHandler = (e: TransitionEvent) => {
if (e.propertyName === 'width') {
chartResizeHandler();
}
};
const initResizeEvent = () => {
window.addEventListener('resize', chartResizeHandler, {passive:true});
};
const destroyResizeEvent = () => {
window.removeEventListener('resize', chartResizeHandler);
};
const initSidebarResizeEvent = () => {
sidebarElm.value = document.getElementsByClassName('sidebar-container')[0];
if (sidebarElm.value) {
sidebarElm.value.addEventListener(
'transitionend',
sidebarResizeHandler as EventListener,
{passive:true}
);
}
};
const destroySidebarResizeEvent = () => {
if (sidebarElm.value) {
sidebarElm.value.removeEventListener(
'transitionend',
sidebarResizeHandler as EventListener
);
}
};
const mounted = () => {
initResizeEvent();
initSidebarResizeEvent();
};
const beforeDestroy = () => {
destroyResizeEvent();
destroySidebarResizeEvent();
};
const activated = () => {
initResizeEvent();
initSidebarResizeEvent();
};
const deactivated = () => {
destroyResizeEvent();
destroySidebarResizeEvent();
};
return {
chart,
mounted,
beforeDestroy,
activated,
deactivated
};
}

View File

@@ -7,16 +7,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import {
nextTick,
onActivated,
onBeforeUnmount,
onDeactivated,
onMounted
} from 'vue';
import { init, EChartsOption } from 'echarts';
import * as echarts from 'echarts'; import * as echarts from 'echarts';
import resize from '@/utils/resize';
const props = defineProps({ const props = defineProps({
id: { id: {
@@ -39,130 +30,115 @@ const props = defineProps({
} }
}); });
const { mounted, chart, beforeDestroy, activated, deactivated } = resize(); const options = {
grid: {
function initChart() { left: '2%',
const barChart = init(document.getElementById(props.id) as HTMLDivElement); right: '2%',
bottom: '10%',
barChart.setOption({ containLabel: true
grid: { },
left: '2%', tooltip: {
right: '2%', trigger: 'axis',
bottom: '10%', axisPointer: {
containLabel: true type: 'cross',
}, crossStyle: {
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross',
crossStyle: {
color: '#999'
}
}
},
legend: {
x: 'center',
y: 'bottom',
data: ['收入', '毛利润', '收入增长率', '利润增长率'],
textStyle: {
color: '#999' color: '#999'
} }
}
},
legend: {
x: 'center',
y: 'bottom',
data: ['收入', '毛利润', '收入增长率', '利润增长率'],
textStyle: {
color: '#999'
}
},
xAxis: [
{
type: 'category',
data: ['浙江', '北京', '上海', '广东', '深圳'],
axisPointer: {
type: 'shadow'
}
}
],
yAxis: [
{
type: 'value',
min: 0,
max: 10000,
interval: 2000,
axisLabel: {
formatter: '{value} '
}
}, },
xAxis: [ {
{ type: 'value',
type: 'category', min: 0,
data: ['浙江', '北京', '上海', '广东', '深圳'], max: 100,
axisPointer: { interval: 20,
type: 'shadow' axisLabel: {
} formatter: '{value}%'
} }
], }
yAxis: [ ],
{ series: [
type: 'value', {
min: 0, name: '收入',
max: 10000, type: 'bar',
interval: 2000, data: [7000, 7100, 7200, 7300, 7400],
axisLabel: { barWidth: 20,
formatter: '{value} ' itemStyle: {
} color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
}, { offset: 0, color: '#83bff6' },
{ { offset: 0.5, color: '#188df0' },
type: 'value', { offset: 1, color: '#188df0' }
min: 0, ])
max: 100,
interval: 20,
axisLabel: {
formatter: '{value}%'
}
} }
], },
series: [ {
{ name: '毛利润',
name: '收入', type: 'bar',
type: 'bar', data: [8000, 8200, 8400, 8600, 8800],
data: [7000, 7100, 7200, 7300, 7400], barWidth: 20,
barWidth: 20, itemStyle: {
itemStyle: { color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ { offset: 0, color: '#25d73c' },
{ offset: 0, color: '#83bff6' }, { offset: 0.5, color: '#1bc23d' },
{ offset: 0.5, color: '#188df0' }, { offset: 1, color: '#179e61' }
{ offset: 1, color: '#188df0' } ])
])
}
},
{
name: '毛利润',
type: 'bar',
data: [8000, 8200, 8400, 8600, 8800],
barWidth: 20,
itemStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: '#25d73c' },
{ offset: 0.5, color: '#1bc23d' },
{ offset: 1, color: '#179e61' }
])
}
},
{
name: '收入增长率',
type: 'line',
yAxisIndex: 1,
data: [60, 65, 70, 75, 80],
itemStyle: {
color: '#67C23A'
}
},
{
name: '利润增长率',
type: 'line',
yAxisIndex: 1,
data: [70, 75, 80, 85, 90],
itemStyle: {
color: '#409EFF'
}
} }
] },
} as EChartsOption); {
chart.value = barChart; name: '收入增长率',
} type: 'line',
yAxisIndex: 1,
onBeforeUnmount(() => { data: [60, 65, 70, 75, 80],
beforeDestroy(); itemStyle: {
}); color: '#67C23A'
}
onActivated(() => { },
activated(); {
}); name: '利润增长率',
type: 'line',
onDeactivated(() => { yAxisIndex: 1,
deactivated(); data: [70, 75, 80, 85, 90],
}); itemStyle: {
color: '#409EFF'
}
}
]
};
onMounted(() => { onMounted(() => {
mounted(); const chart = echarts.init(
nextTick(() => { document.getElementById(props.id) as HTMLDivElement
initChart(); );
chart.setOption(options);
window.addEventListener('resize', () => {
chart.resize();
}); });
}); });
</script> </script>

View File

@@ -4,15 +4,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { import * as echarts from 'echarts';
nextTick,
onActivated,
onBeforeUnmount,
onDeactivated,
onMounted
} from 'vue';
import { init, EChartsOption } from 'echarts';
import resize from '@/utils/resize';
const props = defineProps({ const props = defineProps({
id: { id: {
@@ -35,97 +27,80 @@ const props = defineProps({
} }
}); });
const { mounted, chart, beforeDestroy, activated, deactivated } = resize(); const options = {
title: {
show: true,
text: '订单线索转化漏斗图',
x: 'center',
padding: 15,
textStyle: {
fontSize: 18,
fontStyle: 'normal',
fontWeight: 'bold',
color: '#337ecc'
}
},
grid: {
left: '2%',
right: '2%',
bottom: '10%',
containLabel: true
},
legend: {
x: 'center',
y: 'bottom',
data: ['Show', 'Click', 'Visit', 'Inquiry', 'Order']
},
function initChart() { series: [
const funnelChart = init(document.getElementById(props.id) as HTMLDivElement); {
name: 'Funnel',
funnelChart.setOption({ type: 'funnel',
title: { left: '20%',
show: true, top: 60,
text: '订单线索转化漏斗图', bottom: 60,
x: 'center', width: '60%',
padding: 15, sort: 'descending',
textStyle: { gap: 2,
fontSize: 18, label: {
fontStyle: 'normal', show: true,
fontWeight: 'bold', position: 'inside'
color: '#337ecc' },
} labelLine: {
}, length: 10,
grid: { lineStyle: {
left: '2%', width: 1,
right: '2%', type: 'solid'
bottom: '10%', }
containLabel: true },
}, itemStyle: {
legend: { borderColor: '#fff',
x: 'center', borderWidth: 1
y: 'bottom', },
data: ['Show', 'Click', 'Visit', 'Inquiry', 'Order'] emphasis: {
},
series: [
{
name: 'Funnel',
type: 'funnel',
left: '20%',
top: 60,
bottom: 60,
width: '60%',
sort: 'descending',
gap: 2,
label: { label: {
show: true, fontSize: 20
position: 'inside' }
}, },
labelLine: { data: [
length: 10, { value: 60, name: 'Visit' },
lineStyle: { { value: 40, name: 'Inquiry' },
width: 1, { value: 20, name: 'Order' },
type: 'solid' { value: 80, name: 'Click' },
} { value: 100, name: 'Show' }
}, ]
itemStyle: { }
borderColor: '#fff', ]
borderWidth: 1 };
},
emphasis: {
label: {
fontSize: 20
}
},
data: [
{ value: 60, name: 'Visit' },
{ value: 40, name: 'Inquiry' },
{ value: 20, name: 'Order' },
{ value: 80, name: 'Click' },
{ value: 100, name: 'Show' }
]
}
]
} as EChartsOption);
chart.value = funnelChart;
}
onBeforeUnmount(() => {
beforeDestroy();
});
onActivated(() => {
activated();
});
onDeactivated(() => {
deactivated();
});
onMounted(() => { onMounted(() => {
mounted(); const chart = echarts.init(
nextTick(() => { document.getElementById(props.id) as HTMLDivElement
initChart(); );
chart.setOption(options);
window.addEventListener('resize', () => {
chart.resize();
}); });
}); });
</script> </script>
<style lang="scss" scoped></style>

View File

@@ -7,15 +7,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { import * as echarts from 'echarts';
nextTick,
onActivated,
onBeforeUnmount,
onDeactivated,
onMounted
} from 'vue';
import { init, EChartsOption } from 'echarts';
import resize from '@/utils/resize';
const props = defineProps({ const props = defineProps({
id: { id: {
@@ -37,71 +29,51 @@ const props = defineProps({
required: true required: true
} }
}); });
const options = {
const { mounted, chart, beforeDestroy, activated, deactivated } = resize(); grid: {
left: '2%',
function initChart() { right: '2%',
const pieChart = init(document.getElementById(props.id) as HTMLDivElement); bottom: '10%',
containLabel: true
pieChart.setOption({ },
grid: { legend: {
left: '2%', top: 'bottom',
right: '2%', textStyle: {
bottom: '10%', color: '#999'
containLabel: true }
}, },
legend: { series: [
top: 'bottom', {
textStyle: { name: 'Nightingale Chart',
color: '#999' type: 'pie',
} radius: [50, 130],
}, center: ['50%', '50%'],
series: [ roseType: 'area',
{ itemStyle: {
name: 'Nightingale Chart', borderRadius: 1,
type: 'pie', color: function (params: any) {
radius: [50, 130], //自定义颜色
center: ['50%', '50%'], const colorList = ['#409EFF', '#67C23A', '#E6A23C', '#F56C6C'];
roseType: 'area', return colorList[params.dataIndex];
itemStyle: { }
borderRadius: 1, },
color: function (params: any) { data: [
//自定义颜色 { value: 26, name: '家用电器' },
const colorList = ['#409EFF', '#67C23A', '#E6A23C', '#F56C6C']; { value: 27, name: '户外运动' },
return colorList[params.dataIndex]; { value: 24, name: '汽车用品' },
} { value: 23, name: '手机数码' }
}, ]
data: [ }
{ value: 26, name: '家用电器' }, ]
{ value: 27, name: '户外运动' }, };
{ value: 24, name: '汽车用品' },
{ value: 23, name: '手机数码' }
]
}
]
} as EChartsOption);
chart.value = pieChart;
}
onBeforeUnmount(() => {
beforeDestroy();
});
onActivated(() => {
activated();
});
onDeactivated(() => {
deactivated();
});
onMounted(() => { onMounted(() => {
mounted(); const chart = echarts.init(
nextTick(() => { document.getElementById(props.id) as HTMLDivElement
initChart(); );
chart.setOption(options);
window.addEventListener('resize', () => {
chart.resize();
}); });
}); });
</script> </script>
<style lang="scss" scoped></style>

View File

@@ -7,15 +7,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { import * as echarts from 'echarts';
nextTick,
onActivated,
onBeforeUnmount,
onDeactivated,
onMounted
} from 'vue';
import { init, EChartsOption } from 'echarts';
import resize from '@/utils/resize';
const props = defineProps({ const props = defineProps({
id: { id: {
@@ -38,89 +30,71 @@ const props = defineProps({
} }
}); });
const { mounted, chart, beforeDestroy, activated, deactivated } = resize(); const options = {
grid: {
function initChart() { left: '2%',
const radarChart = init(document.getElementById(props.id) as HTMLDivElement); right: '2%',
bottom: '10%',
radarChart.setOption({ containLabel: true
grid: { },
left: '2%', legend: {
right: '2%', x: 'center',
bottom: '10%', y: 'bottom',
containLabel: true data: ['预定数量', '下单数量', '发货数量'],
}, textStyle: {
legend: { color: '#999'
x: 'center', }
y: 'bottom', },
data: ['预定数量', '下单数量', '发货数量'], radar: {
textStyle: { // shape: 'circle',
color: '#999' radius: '60%',
} indicator: [
}, { name: '家用电器' },
radar: { { name: '服装箱包' },
// shape: 'circle', { name: '运动户外' },
radius: '60%', { name: '手机数码' },
indicator: [ { name: '汽车用品' },
{ name: '家用电器' }, { name: '家具厨具' }
{ name: '服装箱包' },
{ name: '运动户外' },
{ name: '手机数码' },
{ name: '汽车用品' },
{ name: '家具厨具' }
]
},
series: [
{
name: 'Budget vs spending',
type: 'radar',
itemStyle: {
borderRadius: 6,
color: function (params: any) {
//自定义颜色
const colorList = ['#409EFF', '#67C23A', '#E6A23C', '#F56C6C'];
return colorList[params.dataIndex];
}
},
data: [
{
value: [400, 400, 400, 400, 400, 400],
name: '预定数量'
},
{
value: [300, 300, 300, 300, 300, 300],
name: '下单数量'
},
{
value: [200, 200, 200, 200, 200, 200],
name: '发货数量'
}
]
}
] ]
} as EChartsOption); },
series: [
chart.value = radarChart; {
} name: 'Budget vs spending',
type: 'radar',
onBeforeUnmount(() => { itemStyle: {
beforeDestroy(); borderRadius: 6,
}); color: function (params: any) {
//自定义颜色
onActivated(() => { const colorList = ['#409EFF', '#67C23A', '#E6A23C', '#F56C6C'];
activated(); return colorList[params.dataIndex];
}); }
},
onDeactivated(() => { data: [
deactivated(); {
}); value: [400, 400, 400, 400, 400, 400],
name: '预定数量'
},
{
value: [300, 300, 300, 300, 300, 300],
name: '下单数量'
},
{
value: [200, 200, 200, 200, 200, 200],
name: '发货数量'
}
]
}
]
};
onMounted(() => { onMounted(() => {
mounted(); const chart = echarts.init(
nextTick(() => { document.getElementById(props.id) as HTMLDivElement
initChart(); );
chart.setOption(options);
window.addEventListener('resize', () => {
chart.resize();
}); });
}); });
</script> </script>
<style lang="scss" scoped></style>

View File

@@ -20,7 +20,7 @@ const date: Date = new Date();
const greetings = computed(() => { const greetings = computed(() => {
if (date.getHours() >= 6 && date.getHours() < 8) { if (date.getHours() >= 6 && date.getHours() < 8) {
return '晨起披衣出草堂,轩窗已自喜微凉🌅!'; return '晨起披衣出草堂,轩窗已自喜微凉🌅!';
} else if (date.getHours() >= 8 && date.getHours() < 18) { } else if (date.getHours() >= 8 && date.getHours() < 12) {
return '上午好🌞!'; return '上午好🌞!';
} else if (date.getHours() >= 12 && date.getHours() < 18) { } else if (date.getHours() >= 12 && date.getHours() < 18) {
return '下午好☕!'; return '下午好☕!';
@@ -209,5 +209,8 @@ const greetings = computed(() => {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
} }
.svg-icon {
fill: currentColor !important;
}
} }
</style> </style>