菏泽网站建设公司有哪些成都网络营销公司
我在项目中需要用到很多的图标,比如折线、饼图、柱状、关系等各种图标,我又比较懒,所以就封了一个基本的组件库,只需要传递options和canvasId,基本就可以了,代码如下:
<template><div class="wrapper-charts"><div class="text-title" v-if="isShowTitle"><div class="title-h3">{{ title || '' }}</div><div v-if="isShowSelect"><!-- <template #select> xxx </template> --><span class="title-tip" v-if="showInstitutionName">{{ institutionName || '' }}</span><slot name="select"><a-select size="small" style="width: 113px" :value="modelValue" class="selectType" @select="onChange":fieldNames="labelProps"><a-select-option value="全部">全部</a-select-option><a-select-option :value="item" v-for="(item, index) in selectOptions" :key="index">{{ item }}</a-select-option></a-select></slot></div></div><div class="wrapper-charts-content" :style="bodyStyle"><div class="charts-styles" :class="className" v-if="chartOptOneSort"><div v-size-direct="resizeChart" :ref="chartId" :id="chartId" :style="styles"></div></div><div class="no-data-available-chart" v-else><svg-icon name="noDataAvailable" width="121" height="130"></svg-icon><div>暂无数据</div></div></div></div>
</template><script setup>import { ref, onMounted, onBeforeUnmount, watch, nextTick, defineSlots, markRaw } from 'vue'import * as echarts from 'echarts'// Propsconst props = defineProps({modelValue: {type: [String, Number, null, Array],default: '全部'},isShowTitle: {type: Boolean,default: false},isShowSelect: {type: Boolean,default: true},loading: {type: Boolean,default: false},className: {type: String,default: ""},selectOptions: {type: Array,default: []},labelProps: {type: Object,default: {label: 'name',value: 'value',options: 'options'}},showInstitutionName: {type: Boolean,default: true},institutionName: {type: String,default: ''},title: {type: String,default: '高原病就珍'},// id 需要不一样,不然会覆盖chartId: {type: String,required: true,default: 'chartContainer'},option: {type: Object,required: true // option 是必须的},bodyStyle: {type: Object,default: {width: '100%',height: '100%'}},styles: {type: Object,default: {width: '100%',height: '100%'}},clickChart: {type: Function,required: false}})let chartInstance = ref(null)const emit = defineEmits(['update:modelValue', 'change', 'clickChart', 'finished']) // 用来触发事件const $solt = defineSlots()const onChange = (value) => {emit('update:modelValue', value)emit('change', value)}const chartOptOneSort = ref(false)// 初始化图表const initChart = () => {if (chartInstance.value) {chartInstance.value?.dispose() // 销毁已有实例,避免重复渲染}const dom = document.getElementById(props.chartId)chartInstance.value = markRaw(echarts.init(dom))if (props.loading) {chartInstance.value?.showLoading()}chartInstance.value?.off('click') // 移除旧的点击事件chartInstance.value?.setOption(props.option)// 监听图表渲染完成事件chartInstance.value?.on('finished', () => {chartInstance.value?.hideLoading()emit('finished')})// 监听图表点击事件chartInstance.value?.on('click', (params) => {// 通过 emit 触发 'click' 事件,传递参数emit('clickChart', params)})}// 监听 option 的变化并更新图表watch(() => props.option,(newOption) => {chartOptOneSort.value = newOption?.series?.length > 0;let isShowView = newOption?.series?.map(item => item.data.some(value => value > 0)) || [];chartOptOneSort.value = isShowView.some(item => item);if (chartOptOneSort.value) {nextTick(() => {if (chartInstance.value) {// chartInstance.value.clear();chartInstance.value?.dispose() // 销毁已有实例,避免重复渲染}initChart()})}},{ deep: true, immediate: true } // 深度监听)// 处理窗口大小变化时,重新调整图表尺寸const resizeChart = (contentRect) => {if (chartInstance.value) {chartInstance.value?.resize()}}// 在组件挂载时初始化图表,并添加 resize 事件监听onMounted(() => {// initChart();// window.addEventListener('resize', handleResize)})// 在组件卸载时销毁图表,并移除 resize 事件监听onBeforeUnmount(() => {if (chartInstance.value) {chartInstance.value?.dispose()}// window.removeEventListener('resize', handleResize)})defineExpose({chartInstance,resizeChart,initChart,onChange,chartOptOneSort})
</script><style lang="less" scoped>.wrapper-charts {width: 100%;height: 100%;}/* 可以根据需要设置图表的样式 */.text-title {display: flex;justify-content: space-between;align-items: center;margin-bottom: 10px;.title-h3 {font-size: 16px;font-style: normal;font-weight: 600;color: #333;}.title-tip {font-size: 14px;font-weight: 400;color: #5e6580;margin-right: 10px;}}.wrapper-charts-content {width: 100%;height: 100%;.charts-styles {width: 100%;height: calc(100% - 35px);}}.no-data-available-chart {width: 100%;height: 100%;display: flex;align-items: center;flex-direction: column;justify-content: center;color: #5e6580;font-family: 'PingFang SC';font-size: 14px;font-style: normal;font-weight: 400;}
</style>
在使用的页面中引入或者在全局配置都是可以的,我是才页面中引入的,
import StatisticsCharts from '@/components/ECharts/lineTrend.vue'
配置文件 config.ts
import { ref } from 'vue'
import * as echarts from 'echarts'
// charts-config// 折线图柱状数据配置
// https://echarts.apache.org/zh/option.html#tooltip.confine
export const colors = ['#405BC8', '#00CFBE', '#A96BFF']
export function convertToPercentage(decimal: number) {return (decimal * 100).toFixed(2) + ' %'
}
export const chartOptions = {color: colors,tooltip: {trigger: 'axis',triggerOn: 'mousemove',confine: true,height: 'auto',backgroundColor: 'rgba(40, 49, 67, 0.85);',borderColor: 'rgba(40, 49, 67, 0.85);',enterable: true,appendToBody: true,axisPointer: {type: 'cross',label: {backgroundColor: '#6a7985'}// crossStyle: {// color: '#fff'// }},// 自定义提示框内容formatter: function (data) {let tooltipHtml = `<div style="color:#ffffff;font-size: 14px;font-weight: 400;margin-bottom: 8px;max-height: 200px; overflow-y: auto;"><div style="color:#ffffff;font-size: 14px;font-weight: 400;margin-bottom: 8px;">${data[0].axisValue}</br></div>`data.forEach((item) => {tooltipHtml += `<div style="font-size: 12px;padding: 4px 0;width: auto;max-height: 200px; overflow-y: auto;"><div style="display:inline-block;margin-right:4px;width:10px;height:10px;background-color: ${item.color};"></div><span>${item.seriesName} :</span><span style="color:#ffffff">${item.seriesType == 'line' ? convertToPercentage(Number(item.data)) : item.data + '元'}</span></div>`})tooltipHtml += '</div>'return tooltipHtml},textStyle: {fontSize: 14}},toolbox: {top: '2%',right: '3%',show: false,feature: {// dataView: { show: true, readOnly: false },magicType: { show: true, type: ['line', 'bar'] },restore: { show: true }// saveAsImage: { show: true }}},legend: {width: '80%',itemHeight: 10,itemWidth: 10,top: '2%',left: '3%',itemGap: 15,type: 'scroll', // 数据过多时,分页显示icon: 'rect', // 设置图例的形状selected: [] //这里默认显示数组中前十个,如果不设置,则所有的数据都会显示在图表上},xAxis: [{type: 'category',boundaryGap: true, //坐标轴两边留白axisTick: {show: false},data: [],axisPointer: {type: 'shadow'},axisLabel: {show: true, //下方日期显示与否interval: 0, // 设置数据间隔rotate: 28, // 标题倾斜margin: 5, //刻度标签与轴线之间的距离textStyle: {fontSize: 12, //横轴字体大小color: '#8F94A7' //颜色}}}],yAxis: [{name: '',// interval: 5,position: 'left',alignTicks: true,type: 'value',splitLine: {show: false},axisLine: {show: false,// min: 0,// max: 10,lineStyle: { color: '#8F94A7' }},axisLabel: {show: true,fontSize: 14,color: '#8F94A7',formatter: function (value: string) {return `${Number(value)} 元`}}},{// name: '温度',// interval: 5,type: 'value',position: 'right',alignTicks: true,axisLine: {show: false// lineStyle: {// color: colors[2]// }},axisLabel: {show: true,fontSize: 14,formatter: function (value: string) {return `${(Number(value) * 100).toFixed(0)} %`},color: '#8F94A7'}}],// X轴可滚动dataZoom: [{type: 'slider', // 设置为滑动条型式show: true, // 显示dataZoom组件bottom: 0,height: 10,showDetail: false,startValue: 0, //滚动条的起始位置endValue: 9 //滚动条的截止位置(按比例分割你的柱状图x轴长度)// xAxisIndex: [0] // 表示控制第一个x轴// start: 0, // 默认显示的起始位置为0// end: 20, // 默认显示的结束位置为100// handleSize: 8, // 滑动条的手柄大小// handleStyle: {// color: '#DCE2E8' // 滑动条的手柄颜色// },// filterMode: 'filter' // 设置为filter模式,即数据超过范围时会被过滤掉},{type: 'inside', //设置鼠标滚轮缩放show: true,xAxisIndex: [0],startValue: 0,endValue: 9}],grid: {left: '3%',right: '4%',bottom: '3%',containLabel: true},series: [{name: '药品费用总额',type: 'bar',barWidth: '20',tooltip: {valueFormatter: function (value: string) {return `${Number(value)} 元`}},itemStyle: {normal: {barBorderRadius: [2, 2, 0, 0]}},data: []},{name: '医疗总费用',type: 'bar',barWidth: '20',itemStyle: {//柱形图圆角,鼠标移上去效果,如果只是一个数字则说明四个参数全部设置为那么多normal: {//柱形图圆角,初始化效果barBorderRadius: [2, 2, 0, 0]}},tooltip: {valueFormatter: function (value: string) {return `${Number(value)} 元`}},data: []},{name: '药占比',type: 'line',yAxisIndex: 1,smooth: true, //true 为平滑曲线,false为直线symbol: 'circle', //将小圆点改成实心 不写symbol默认空心 none 不显示symbolSize: 8, //小圆点的大小label: {show: true,position: 'top',formatter: function (params: any) {return convertToPercentage(Number(params.value))}},tooltip: {valueFormatter: function (value: string) {return convertToPercentage(Number(value))}},data: []}]
}
// 折线配置
export const chartLineOptions = {color: ['#209E85'],// title: {// text: 'Stacked Line'// },tooltip: {trigger: 'axis',triggerOn: 'mousemove',confine: true,height: 'auto',backgroundColor: 'rgba(40, 49, 67, 0.85);',borderColor: 'rgba(40, 49, 67, 0.85);',enterable: true,appendToBody: true,axisPointer: {type: 'cross',label: {backgroundColor: '#6a7985'}// crossStyle: {// color: '#fff'// }},// 自定义提示框内容formatter: function (data) {let tooltipHtml = `<div style="color:#ffffff;font-size: 14px;font-weight: 400;margin-bottom: 8px;max-height: 200px; overflow-y: auto;"><div style="color:#ffffff;font-size: 14px;font-weight: 400;margin-bottom: 8px;">${data[0].axisValue}</br></div>`data.forEach((item) => {tooltipHtml += `<div style="font-size: 12px;padding: 4px 0;width: auto;max-height: 200px; overflow-y: auto;"><div style="display:inline-block;margin-right:4px;width:10px;height:10px;background-color: ${item.color};"></div><span>${item.seriesName} :</span><span style="color:#ffffff">${item.seriesType == 'line' ? convertToPercentage(Number(item.data)) : item.data + '元'}</span></div>`})tooltipHtml += '</div>'return tooltipHtml},textStyle: {fontSize: 14}},legend: {data: []},grid: {left: '3%',right: '4%',bottom: '3%',containLabel: true},xAxis: {type: 'category',boundaryGap: true,data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']},yAxis: {name: '',// interval: 5,position: 'left',alignTicks: true,type: 'value',splitLine: {show: true // X 轴线},axisLine: {// Y 轴线show: false,// min: 0,// max: 10,lineStyle: { color: '#939495' }},axisLabel: {show: true,fontSize: 14,color: '#939495',formatter: '{value} 元'}},series: [{type: 'line',// symbol: 'none', //去掉折线图中的节点smooth: true, //true 为平滑曲线,false为直线symbol: 'circle', //将小圆点改成实心 不写symbol默认空心symbolSize: 8, //小圆点的大小itemStyle: {color: '#209E85' //小圆点和线的颜色},// areaStyle: {// color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [// {// offset: 0,// color: 'rgba(213,72,120,0.8)' //靠上方的透明颜色// },// {// offset: 1,// color: 'rgba(213,72,120,0.3)' //靠下方的透明颜色// }// ])// },label: {show: true,position: 'top',formatter: function (params: any) {return convertToPercentage(Number(params.value))}},tooltip: {valueFormatter: function (value: string) {return convertToPercentage(Number(value))}},stack: 'Total',data: [120, 132, 101, 134, 90, 230, 210]}]
}
// 柱状图配置
export const barChartOptions = {title: {textStyle: {//文字颜色color: '#07123C',fontWeight: 'bold',//字体系列fontFamily: 'sans-serif',//字体大小fontSize: 18}},toolbox: {top: '2%',right: '3%',show: false,feature: {// dataView: { show: true, readOnly: false },magicType: { show: true, type: ['line', 'bar'] },restore: { show: true }// saveAsImage: { show: true }}},tooltip: {trigger: 'axis',backgroundColor: 'rgba(40, 49, 67, 0.85);',borderColor: 'rgba(40, 49, 67, 0.85);',enterable: true,appendToBody: true,textStyle: {color: '#fff'}},legend: {// top: '2%',left: '3%',itemHeight: 10,itemWidth: 10,itemGap: 15,type: 'scroll', // 数据过多时,分页显示selected: [], //这里默认显示数组中前十个,如果不设置,则所有的数据都会显示在图表上icon: 'rect', // 设置图例的形状data: []},color: ['#13A89B'],barWidth: 20,calculable: true,grid: {left: '3%',right: '4%',bottom: '3%',containLabel: true},xAxis: {type: 'category',data: ['急诊科', '门诊科', '儿科', '妇科', '神经外科', '神经内科', '皮肤科', '放射科'],axisTick: {show: false},axisLabel: {// 轴文字show: true,color: '#A6AAB2',fontSize: 12,interval: 0,rotate: 20},axisLine: {lineStyle: {type: 'solid',color: '#E6E6E8',width: '1'}}},yAxis: {type: 'value',axisLabel: {// 轴文字show: true,color: '#A6AAB2',fontSize: 12}// max:99999//给y轴设置最大值},series: [{type: 'bar',data: [120, 200, 150, 80, 70, 110, 130, 50],// barGap:'80%',/*多个并排柱子设置柱子之间的间距*/// barCategoryGap:'50%',/*多个并排柱子设置柱子之间的间距*/itemStyle: {//柱状图上方显示数值normal: {//柱形图圆角,初始化效果barBorderRadius: [2, 2, 0, 0],color: '#13A89B',label: {show: true, //开启显示position: 'top', //在上方显示textStyle: {//数值样式color: '#5E6580',fontSize: 12}}}},showBackground: true,backgroundStyle: {color: '#f2f8ff'},label: {show: true,position: 'top',formatter: '{c}'}}],dataZoom: [{type: 'slider', //给x轴设置滚动条show: true, //flase直接隐藏图形xAxisIndex: [0],bottom: 0,height: 10,showDetail: false,startValue: 0, //滚动条的起始位置endValue: 9 //滚动条的截止位置(按比例分割你的柱状图x轴长度)},{type: 'inside', //设置鼠标滚轮缩放show: true,xAxisIndex: [0],startValue: 0,endValue: 9}]
}