123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213 |
- <script setup lang="ts">
- import type { OptionsProps } from '@/types/dataAnalysis'
- import { onMounted, ref, shallowRef, watch, useAttrs } from 'vue'
- import { nextTick } from 'vue'
- import { debounceFunc } from '@/utils/common'
- import echarts from '.'
- // 图表需要的props
- const props = defineProps<OptionsProps>()
- // 传入的attrs
- const attrs = useAttrs()
- // 图表实例
- const linechart = shallowRef()
- // 图表Ref
- const chart = ref()
- // 颜色
- const colorList = [
- '#00e070',
- '#1495eb',
- '#993333', // Dark Red
- '#FFD700', // Bright Yellow
- '#FF00FF', // Magenta
- '#FFA500', // Orange
- '#800080', // Dark Purple
- '#A52A2A', // Brown
- '#FF4500', // Orange Red
- '#FF6347', // Tomato
- '#B22222', // Firebrick
- '#FF1493' // Deep Pink
- ]
- // 格式化tooltip
- const formatterTooltip = (params: Array<any>) => {
- let circle = `<span style="display:inline-block;margin-right:5px;border-radius:50%;width:10px;height:10px;left:5px;background-color:`
- let result = `<span style="font-weight:bold;">${params[0].axisValueLabel}</span>`
- params.map((item, index) => {
- let data = `${circle}${colorList[index]}"></span>
- <span >
- <span style="display: inline-block; box-sizing: border-box;
- padding-right: 50px;">${item['seriesName']}</span><span>${item['value']}<span>`
- result += `<br/>${data}`
- })
- return result
- }
- // 尺寸变化
- const changeSize = () => {
- nextTick(() => {
- linechart.value?.resize()
- })
- }
- // 初始化options
- const initOptions = () => {
- // 选项
- let options: any = {
- xAxis: {
- type: 'category',
- data: [],
- axisLabel: {
- showMaxLabel: true
- },
- axisTick: {
- alignWithLabel: true
- }
- },
- yAxis: {
- type: 'value',
- minInterval: 1
- },
- tooltip: {
- trigger: 'axis',
- formatter: formatterTooltip
- },
- legend: {
- orient: 'horizontal', //图例布局方式:水平 'horizontal' 、垂直 'vertical'
- x: 'right', // 横向放置位置,选项:'center'、'left'、'right'、'number'(横向值 px)
- y: 'top', // 纵向放置位置,选项:'top'、'bottom'、'center'、'number'(纵向值 px)
- data: []
- },
- grid: {
- left: '24px',
- right: '10px',
- containLabel: true
- },
- series: []
- }
- // 基本的series数据配置
- let baseSeries = {
- symbol: 'circle',
- symbolSize: 5,
- showSymbol: false,
- // itemStyle要在lineStyle前面,这个item会把line的样式覆盖掉,并且必须要有line,不然也会被item替换掉
- itemStyle: {
- color: 'rgb(255,255,255)',
- borderColor: '#1495eb', // symbol边框颜色
- borderWidth: 2 // symbol边框宽度
- },
- lineStyle: {
- color: '#1495eb'
- },
- name: '今日新增',
- data: [10, 22, 28, 43, 49],
- type: 'line',
- smooth: true
- }
- linechart.value.clear()
- if (props.seriesData.length) {
- // 最终的siries数组
- let finalSeriesList: any = []
- props.legendData.map((item, index) => {
- const seriesClone = JSON.parse(JSON.stringify(baseSeries))
- // 设置克隆的属性
- seriesClone.name = item
- let reuslt = props.seriesData.find((val) => {
- return val.name === item
- })
- seriesClone.data = Object.values(reuslt.data)
- seriesClone.itemStyle.borderColor = colorList[index]
- seriesClone.lineStyle.color = colorList[index]
- // 将克隆后的对象添加到 finalSeriesList 中
- finalSeriesList.push(seriesClone)
- })
- options.series = finalSeriesList
- options.legend.data = Object.values(props.legendData as any)
- options.xAxis.data = props.xAxisData as any
- } else {
- options = {
- title: {
- text: '暂无数据',
- x: 'center',
- y: 'center',
- textStyle: {
- fontSize: 16,
- fontWeight: 'normal'
- }
- }
- }
- }
- linechart.value.setOption(options, true)
- }
- // 改变加载状态
- const changeLoading = (state: boolean) => {
- if (state) linechart.value.showLoading()
- else linechart.value.hideLoading()
- }
- // 监听options信息的变化
- watch(
- () => [props.legendData, props.seriesData, props.xAxisData],
- () => {
- initOptions()
- },
- { deep: true }
- )
- watch(
- () => attrs['loading-state'] as boolean,
- (newval: boolean) => {
- changeLoading(newval)
- },
- { deep: true }
- )
- onMounted(() => {
- nextTick(() => {
- // 开始的时候,不要去直接初始化,先展示加载状态,等到数据加载完状态改变,再去设置
- linechart.value = echarts.init(chart.value)
- if (!attrs['loading-state']) initOptions()
- /**
- * @description: 只监听window会导致当侧边栏缩放时,dom大小变化但无法resize
- * 所以需要使用ovserver对整个dom进行监听
- * @return {*}
- */
- // window.addEventListener('resize', debounceFunc(changeSize, 500))
- const debounceChangeSize = debounceFunc(changeSize, 200)
- const ro = new ResizeObserver(debounceChangeSize)
- ro.observe(chart.value)
- })
- })
- </script>
- <template>
- <div class="chart" ref="chart" style="width: 100%; height: 365px"></div>
- </template>
- <style scoped>
- .t {
- color: red;
- display: inline-block;
- box-sizing: border-box;
- padding-right: 20px;
- }
- </style>
|