首页 > 其他分享 >Echarts图表管理方式总结

Echarts图表管理方式总结

时间:2023-03-31 13:33:19浏览次数:37  
标签:总结 const title 图表 ChartStyle rgba data Echarts

由于最近项目图表非常多,而且很多都是有共性的,于是摸索除了一套便于管理的图表配置方式。
一种是处理共性的,可参考下方的1,2,3,4
一种是处理特殊性的,可参考下方的5,
其实两种方式可以共用。

1.基本样式模块化

把一些常用的属性一块一块写好。下面举一些例子

名称 示例
提示样式
label样式
常见legend
import * as echarts from 'echarts';

// 配置要用到的颜色组
const colorGroup = [
   ['rgba(255, 208, 0, 1)', 'rgba(255, 208, 0, 0.4)'],
   ['rgba(25,163,223,1)', 'rgba(25,163,223,.4)'],
   ['rgba(59, 255, 137, 1)', 'rgba(59, 255, 137, 0.4)'],
   ['rgba(0, 255, 247, 1)', 'rgba(0, 255, 247, 0.4)'],
   ['rgba(0, 205, 132, 1)', 'rgba(0, 205, 132, 0.4)'],
   ['#bfd214', '#6699ff'],
   ['#99da69', '#01babc'],
   ['#5ff6e9', '#7370fd'],
   ['#f5b159', '#f4d66c'],
   ['#695af2', '#92f6be'],
   ['#b9f692', '#f4d66c'],
   ['rgba(0,244,255,1)', 'rgba(0,77,167,1)'],
   ['rgba(230, 230, 0, 1)', 'rgba(230, 230, 0, 0.4)'],
   ['rgba(255, 77, 77, 1)', 'rgba(255, 77, 77, 0.5)'],
   ['rgba(  255, 255, 102, 1)', 'rgba(  255, 255, 102, 0.5)'],
];

// 自定义提示框样式
const getTooltip=(title,unit)=>({
   trigger: 'axis',
   axisPointer: {
      type: 'cross',
      label: {
         backgroundColor: '#6a7985'
      }
   },
   formatter: (params)=>{
      return `<div style="width:200px">
         <div>${params[0].name}</div>
         <div style="display:flex;justify-content:space-between;align-items:center;height:10px">
            <div style="height:100%;display:flex;align-items:center;">
               <div style="width:10px;height:10px;border-radius:5px;background:${params[0].color};margin-right:4px"></div>
               <div>${title}</div>
            </div>
            <div>${params[0].value}${unit}</div>
         </div>
      </div>`
   }
})

// 图表标题样式
const TitleStyle = {
   left: 'center',
   textStyle: {
      color: '#09d9b9',
      fontWeight: 'bold',
      fontSize: '18px'
   }
};

// 横轴滑块
const DataZoom=(length,max=5)=>({
   top: "92%",
   id: 'dataZoomX',
   type: 'slider',
   xAxisIndex: [0],
   filterMode: 'filter',
   zoomLock: true,
   height: 16,
   brushSelect: false,
   show: length>max,  // 当数据条数大于5时显示
   maxValueSpan:max   // 当前窗口允许显示的数据条数
})

// 横轴基本样式
const XAxisBaseStyle = {
   axisLine: { onZero: false },
   splitLine: { show: false },
   axisLine: {
      show: true,
      lineStyle: {
         color: '#5e96c7'
      }
   },
   nameTextStyle: {
      color: '#9ec2ff',
      fontSize: 12
   }
};

// 横轴样式(+ 格式化label)
const XAxisStyle = {
	...XAxisBaseStyle,
   axisLabel: {
      textStyle: {
         color: '#9ec2ff',
         fontSize: 12
      },
      // 自定义样式,由于横坐标基本都是 2022-12-13 11:10:10 这样的,
      // 所以这边单独做了格式化
      formatter: function (params) {
         let [date, time] = params.split(' ');
         return date + '\n' + time;
      }
   },
};



// 是否应用X轴间隔:每隔几个坐标要隐藏中间的数据。
// (有时候数据多也不像用间隔,所以再加个isApply参数)
const getIntervalXAxis = (isApply,length,max=5) => ({
   ...XAxisBaseStyle,
   axisLabel: {
      textStyle: {
         color: '#9ec2ff',
         fontSize: 12
      },
      formatter: function (params) {
         let [date, time] = params.split(' ');
         return date + '\n' + time;
      },
      ...((length > max && isApply)?{interval:Math.floor(length / max)}:{})
   }
});

// 图标位置
const GridStyle = {
   x: 46,
   y: 55,
   x2: 40,
   y2: 60
};

// 标题样式
const TitleStyle = {
   left: 'center',
   textStyle: {
      color: '#09d9b9',
      fontWeight: 'bold',
      fontSize: '18px'
   }
};

// legend固定样式
const TwoLegendStyle = {
   data: ['最高值', '最低值'],
   top: '2%',
   right:'4%',
   textStyle: {
      color: '#ffffff'
   }
};
// ...

2. 图表series样式模块化

折线:

// 折线图样式
const SmoothLine = (firstColor = 'rgba(255, 208, 0, 1)', secondColor = 'rgba(255, 208, 0, 0.4)') => ({
   type: 'line',
   symbol: 'circle', // 默认是空心圆(中间是白色的),改成实心圆
   showAllSymbol: true,
   symbolSize: 0,
   smooth: true,
   lineStyle: {
      normal: {
         width: 1,
         color: firstColor // 线条颜色
      },
      borderColor: 'rgba(0,0,0,.4)'
   },
   itemStyle: {
      color: firstColor
   },
   areaStyle: {
      //区域填充样式
      normal: {
         //线性渐变,前4个参数分别是x0,y0,x2,y2(范围0~1);相当于图形包围盒中的百分比。如果最后一个参数是‘true’,则该四个值是绝对像素位置。
         color: new echarts.graphic.LinearGradient(
            0,
            0,
            0,
            1,
            [
               {
                  offset: 0,
                  color: secondColor
               },
               {
                  offset: 1,
                  color: 'rgba(10,219,250, 0)'
               }
            ],
            false
         ),
         shadowColor: secondColor, //阴影颜色
         shadowBlur: 20 //shadowBlur设图形阴影的模糊大小。配合shadowColor,shadowOffsetX/Y, 设置图形的阴影效果。
      }
   }
});

柱体:

// 柱状图样式
const BarStyle = (firstColor = 'rgba(0,244,255,1)', secondColor = 'rgba(0,77,167,1)') => ({
   type: 'bar',
   barMaxWidth: 20,
   barGap: '10%',
   itemStyle: {
      normal: {
         color: {
            type: 'linear',
            x: 0,
            y: 0,
            x2: 0,
            y2: 1,
            colorStops: [
               {
                  offset: 0,
                  color: firstColor // 0% 处的颜色
               },
               {
                  offset: 1,
                  color: secondColor // 100% 处的颜色
               }
            ],
            global: false // 缺省为 false
         }
      }
   }
});

3. 图表options模块化

import ChartStyle from './ChartStyle';  // 把上面配置的所有样式都导进来


// 1. 单折线
// data : 图表数据
// title : 图标标题
// unit : 图标单位
// colors: 颜色组
// isSider: 是否显示滑块

const getLineOps = ({ data = {}, title = '标题', unit = '', colors = ChartStyle.colorGroup[0], isSider = true }) => {

   // 这些看数据结构处理
   const timepoints = data.map((item) => item.t).reverse();
   const values = data.map((item) => item.v).reverse();

   const option = {
      tooltip: ChartStyle.getTooltip(title, unit),
      grid: ChartStyle.GridStyle,
      title: {
         text: title,
         ...ChartStyle.TitleStyle
      },
      // 如果有滑块要求,再配置滑块属性
      dataZoom: isSider ? ChartStyle.DataZoom(timepoints.length) : [],
  
      xAxis: {
         type: 'category',
         data: timepoints,
         boundaryGap: true,
         // 如果要滑块,我这边就不应用间隔了
         ...ChartStyle.getIntervalXAxis(!isSider, timepoints.length)
      },
      yAxis: {
         type: 'value',
         name: unit,
         ...ChartStyle.AxisStyle
      },
      series: [
         {
            data: values,
            ...ChartStyle.SmoothLine(colors[0], colors[1])
         }
      ]
   };
   return option;
};

// 2. 双折线
const getTwoLinesOps = ({ data = [tops, lows], title = '标题', unit = '', colors = [ChartStyle.colorGroup[1], ChartStyle.colorGroup[2]], isSider = true }) => {
   const timepoints = data[0].map((item) => item.t).reverse();
   const top_values = data[0].map((item) => item.v).reverse();
   const low_values = data[1].map((item) => item.v).reverse();

   const option = {
      tooltip: ChartStyle.Tooltip,
      grid: ChartStyle.GridStyle,
      legend: ChartStyle.TwoLegendStyle,
      title: {
         text: title,
         ...ChartStyle.TitleStyle
      },
      dataZoom: isSider ? ChartStyle.DataZoom(timepoints.length) : [],
      xAxis: {
         type: 'category',
         data: timepoints,
         boundaryGap: false,
         ...ChartStyle.getIntervalXAxis(!isSider, timepoints.length)
      },
      yAxis: {
         type: 'value',
         name: unit,
         ...ChartStyle.AxisStyle
      },
      series: [
         {
            name: '最高值',
            data: top_values,
            ...ChartStyle.SmoothLine(...colors[0])
         },
         {
            name: '最低值',
            stack: 'Total',
            data: low_values,
            ...ChartStyle.SmoothLine(...colors[1])
         }
      ]
   };
   return option;
};

// 以此类推,可以配置各种图表的options

4. 图表配置

给各类图表配置一些默认属性

export const Charts = {
   water_level: {
      name: '水位',
      maxTitle: '历史最高水位',
      minTitle: '历史最低水位',
      unit: 'm',
      instance: null,
      colors: [colorGroup[1], colorGroup[1], colorGroup[4]], // 颜色组
      getOneOps: getLineOps,// 如果是单数据,使用的配置函数
      getTwoOps: getTwoLinesOps// 如果是双数据,使用的配置函数
   },
    flow_rate: {
      name: '流速',
      maxTitle: '历史最大流速',
      minTitle: '历史最低流速',
      unit: 'm/s',
      instance: null,
      colors: [colorGroup[2], colorGroup[1], colorGroup[4]],
      getOneOps: getLineOps,
      getTwoOps: getTwoLinesOps
   },
};

如何使用?

// 1. 获取默认配置的属性
// 假设有个图表叫water_level
const key='water_level'
const Chart = Charts[key]  // 获取默认属性

// 2. 传入图表数据,获取图表options
// 当有多个图表都要遍历渲染,或者这个图表有多种展现形式,那么用这种bind的形式就非常不错
// 下面用的是getOneOps 单数据的情况,还可以根据情况切换其他options,比如配置的getTwoOps
// 假设data是该图表获取到的数据,
const getOps = Chart.getOneOps.bind(null, {
		  data:data.list, // 传入数据
		  title:data.cn_col, // 图表标题,没有的话可以用默认属性 Chart.name
		  unit:data.unit,// 图表标题,没有的话可以用默认属性 Chart.unit
		  colors: Chart.colors[0], // 图表配置的颜色
		  isSider: false // 是否显示滑块
	   });

// 3. 获取dom与渲染
if (Chart.instance === null) {
   Chart.instance = echarts.init(document.getElementById(key));
}
Chart.instance.setOption(getOps()); 

对应的图表容器

<div id={key} className="mybox"></div>

5. 图表容器封装

有时候图表要放在一个统一的容器里,或者有些内容也要放在和它们一样的容器里,这时候可以用到高阶组件。假设有个容器样式长这样,那么首先就要设计好这个容器样式,然后只要传入标题和内容/图表就能出效果。这种模式适合数据统一由父级获取的情况
![[Pasted image 20230331112220.png]]

  1. 高阶组件封装
import React from 'react';
import * as echarts from 'echarts';

// 包装内容:传入内容组件,再传入一些配置
// chartbox-base类是容器样式
export const wrapContent = (Component, { title = '模块名称', id = 'moduleid' }) => {
   class Container extends React.Component {
      render() {
         return (
            <div className="chartbox-base" id={id} key={id}>
               <div className="header">
                  <span className='title'>{title}</span>
               </div>
               <div className="content">
                  {
                     Component && <Component {...this.props} />
                  }
               </div>
            </div>
         );
      }
   }
   return Container;
};

// 包装图表:传入配置与内容组件,由于内容组件可要可不要,所以挪到了后面
// 这里的配置包含option 也就是图表的option
// 有了这个高阶组件,图表注册和销毁就不用再外层处理了
export const wrapChart = ({id = 'moduleid', title = '模块名称', option={}, minHeight='220px' },Component) => {
   class Container extends React.PureComponent {
      componentDidMount(){
         if (typeof this.chart === 'undefined') {
            this.chart = echarts.init(document.getElementById(id));
         }

         option && this.chart.setOption(option);
      }


      componentWillUnmount(){
         this.chart.dispose();
      }
      render() {
         return (
            <div className="chartbox-base" key={id} >
               <div className="header">
                  <span className='title'>{title}</span>   
               </div>
               {
                  Component 
               }
               <div className="content" id={id} style={{minHeight}}>
                  
               </div>
            </div>
         );
      }
   }

   return Container;
};
  1. 如何使用?

首先得有一个父界面来放容器呀。假设要放入一个内容,一个图表,它们共用同一个容器:

import BaseInfo from './BaseInfo';
import WaterStats from './WaterStats';


<div>
	<BaseInfo/>
	<WaterStats data={}/>       // 可传入在父级获取到的一些数据
</div>

那这些组件是怎么来的呢?

  1. 内容组件BaseInfo.js
import React from 'react';
import { wrapContent } from '../utils';  // 导入刚才封装内容的高阶组件

const BaseInfo = () => {
   return <div>
	   放入内容
   </div>
};

// 包装了之后,就会多出一个
export default wrapContent(BaseInfo, { title: '农场简介', id: 'baseInfo' });
  1. 图表组件WaterStats.js
import React from 'react';
import { wrapChart,ChartStyle } from '../utils';

// 除了基本的图表,也可以放入额外的内容,这里就发挥到了wrapChart的第二个参数的作用了
const TopInfo = ({data}) => {
   return (
      <div className='otherinfo'>一些内容 </div>
   );
};

const WaterStats = ({data}) => {
   const option = {
      // 配置图表option
   };

   // 
   const DOM = wrapChart({ title: '水文统计', id: 'water_stats', option, minHeight: '160px' }, <TopInfo data={data} />);
   
   return <DOM />;
};

export default WaterStats;

标签:总结,const,title,图表,ChartStyle,rgba,data,Echarts
From: https://www.cnblogs.com/sanhuamao/p/17276007.html

相关文章

  • echarts如何在x轴的tooltip上加上描述文字
     想要实现的效果,如下图: 实现该操作的代码如下:1tooltip:{2formatter:"month:{b0}<br>"34}实现该效果的实例图如下:   ......
  • 3/30每日总结:地图下钻功能的实现
    在main中新建 然后导入html文件其中代码如下:<!DOCTYPEhtml><html><head><metacharset="UTF-8"><!--重要meta,必须!--><metaname="viewport"content="width=320,initial-scale=1.0,maximum-scale=1.0,mi......
  • 总结三次题目集的知识点、题量、难度等情况
    前言:题目集1是Java入门,大至涵盖了Java的几种基本语言结构,如循环,选择,数组。与c语言大致相似,上手较容易。但是题目难度不低,7-10GPS数据处理,不仅题目长难以理解,对有难度的字符串要求掌握熟练,输出要考虑的情况也很多,题目也达12题之多。其他题目在c语言里写过近似一模一样的题,写这个题......
  • python基础学习总结
    python关键字也是以下划线或者字母开头。python关键字可以通过导包获取关键字如下: ['False','None','True','and','as','assert','async','await','break','class','continue'......
  • 每日总结2023-03-30
    今天完成了部分个人界面成果: 实现了fragment跳转到Activity,对于导航栏的颜色变化仍有不懂,对于地图的预加载、实现仍不会实现。登录功能可以实现但未完成。 ......
  • 3.30App端地铁查询 设计思路 源程序代码、运行结果截图、编程总结分析。
    App端地铁查询设计思路源程序代码、运行结果截图、编程总结分析。 关于地铁查询App的设计思路。设计思路:我们沿用pc端的数据库设计结构,减少了我们的工作量。查询方法以及设计思路都很javaweb设计的大同小异。在设计中我们遇到的主要问题就是安卓Studio中的mysql数据库的......
  • 每日总结 3.30
    今天继续学习了微信小程序的开发,做了一个页面,如下: 代码量大概100行。继续为外包杯学习小程序。 ......
  • 每日总结2023/3/25
    前期我们已经找到了目标客户的需求,精准定位了目标顾客最强烈的痛点,如何解决客户的问题?如何能让客户接受你的解决方案?购买你的产品?精益产品开发——Stage-Fit的第二个阶段:方案阶段,告诉我们如何做出最有效的解决方案——你需要不断迭代你的解决方案,不断试错,直到它是最完美的那一个。......
  • 3.30软件工程学习总结
    今天由于课程较多,没有较多的时间学代码,但也有点时间基本上完成了团队外包杯项目的简单的展示页面设计制作。今天还思考了,觉得自己差的还是挺多的,以后在完成了团队内我能完成的任务后,在可利用的时间里还是要学习更多的内容,学习别人做的部分。......
  • 每日总结-23.3.29-利于云服务器和javaweb简单实现一个网站
    每日总结-23.3.29-利于云服务器和javaweb简单实现一个网站 3月29日总结今日使用云服务器和tomcat实现了简单网站的搭建。使用工具(个人体验,仅作参考,使用其他版本或工具应该也行):1.移动云新人体验免费云服务器一台。(个人专享:通用型云主机)活动页面 (https://ecloud.10086.......