侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

基于echarts 灵活封装react柱形图组件

前端  /  管理员 发布于 6年前   501

现在各种框架各种库都很强大,但是也因为功能强大,导致很多配置都过于繁重,真正有用的就那么几个,今天就基于echarts封装一个通用柱形图!

想要了解其他的组件可以看下我之前封装的其他组件有好的思路或者其他的也会分享出来的;基于antd封装横向拖动时间轴


通用柱形图主要包含几个部分

title展示,xAxis上label的展示;

maxShow, 柱形图展示最多不应大于12个不然会影响美观(或者说观察数据);

UI方面我们需要支持修改柱形图的颜色以及柱形的宽度,无数据提示;

交互方面我们需要支持最基础的点击事件、双击事件,返回暂时固定当前点击的数据部分、所有数据集合以及echarts对象, 除去点击事件我们还需要支持resize,以便视口变化的时候,饼图随之重绘;

支持最普遍使用的toolbox,tooltip等配置;

需要支持删除、新增配置(有时候我们封装的不够完美就需要使用者执行配置一下部分);


实现功能

基于以上几点我们开始写代码:

在componentDidMount周期中接受父组件传来的属性,构建最基本的option,在构建option之前我们先做下关于maxShow的处理;


先声明一个空数据接受处理后的数据
let newChartsData = [];


然后处理maxShow
if (maxShow && maxShow >= 0 && chartsData.length > maxShow) {      chartsData.sort((a, b) => {        return b.value - a.value;      });      newChartsData = chartsData.slice(0, maxShow);      let total = 0;      chartsData.map((item, index) => {        if (index > 4) {          total += item.value        }      });      newChartsData = [...newChartsData, {value: total, name: '其他'}];    }    else {      newChartsData = [...chartsData]    }

*这里注意下,我们默认是不处理maxShow,也就是说加入父级没传那么默认是全部展示的,在没有用zoom配置的的前提下,建议maxShow=12是最佳的;具体时间默认12还是默认不处理要根据使用者处理的数据来定,我处理的数据多数情况下不会多于12,所以默认不处理;


初始化画板,构建option等操作
let myCharts = echarts.init(document.getElementById(`${idPrefix}_pie`));    if (getCharts && typeof func === 'function') {      getCharts(myCharts);    }    myCharts.clear();    _eventType.map(item => {      myCharts.off(item);    }); let option = {      color: newChartsData.length ? chartColor : '#bfbfbf',      title: {        text: title,        top: 20,        x: 'center'      },      toolbox: {        feature: {          saveAsImage: {            type: 'png',            title: '点击下载',          }        },        top: 13,        right: 13      },      tooltip: {        trigger: 'item',        formatter: "{a} <br/>{b} : {c} ({d}%)"      },      series: [        {          name: title,          type: 'pie',          radius,          center,          avoidLabelOverlap: false,          label: {            show: label,          },          labelLine: {            normal: {              show: label            }          },          itemStyle: {            borderWidth: 2, //设置border的宽度有多大            borderColor: bgColor,          },          hoverAnimation: false,          hoverOffset: 0,          data: newChartsData.length ? newChartsData : [{value: 0, name: '暂无数据'}],        },      ],      graphic: newChartsData.length        ? null        : [{          type: 'text',          left: 'center',          top: radius[0] === '0' ? 'auto' : center[1],          bottom: 10,          cursor: 'auto',          style: {            text: '暂无数据',            textAlign: 'center',            fill: '#bfbfbf',            fontSize: 16,            stroke: '#bfbfbf',            lineWidth: 0          }        }]    };

这当中以及添加了关于无数据的展示代码,具体实现的方式请看我之前封装的基于echarts 灵活封装react饼图组件这里就不在重复了;


添加删除补充配置功能、实例化option
 if (deleteOption) {      deleteOption.map(item => {        delete option[item]      });    } // 删除函数    if (options) {      option = {...option, ...options}    } // 补充的options    myCharts.setOption(option);

添加点击事件返回值、添加resize 防抖函数
 if (eChartsEvent && typeof eChartsEvent === 'function') {      myCharts.on(eventType, 'series', params => {        eChartsEvent(params, chartsData, myCharts);      });    }    window.onresize = () => {      let target = this;      if (target.resizeFlag) {        clearTimeout(target.resizeFlag);      }      target.resizeFlag = setTimeout(function () {        myCharts.resize();        if (onResize && typeof onResize === 'function') {          onResize();        }        target.resizeFlag = null;      }, 100);    }


完整代码
import react, {PureComponent} from 'react';import echarts from 'echarts/lib/echarts';import 'echarts/lib/chart/bar';import 'echarts/lib/component/title';import 'echarts/lib/component/tooltip';import 'echarts/lib/component/toolbox';import 'echarts/lib/component/graphic';import PropTypes from 'prop-types';/** 柱形图组件* 包含无数据展示,onresize重绘事件* 可以自定义option, 支持多种鼠标事件* 暂时未封装zoom,zoom等其他功能可通过 options自己定义添加* deleteOption: ['title', 'toolbox', 'tooltip', 'graphic'] 包含echarts含有的属性** *//* * chartsData 格式 * const barChartsData = { *  xAxis: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'], *  data:[10, 52, 200, 334, 390, 330, 220] * }; * 备用颜色: * '#13c2c2', '#52c41a', '#faad14', '#f5222d', '#722ed1', '#eb2f96', '#faad14'] * */const _eventType = ['click', 'dblclick', 'mousedown', 'mousemove', 'mouseup', 'mouseover', 'mouseout', 'globalout', 'contextmenu'];class BarChart extends PureComponent {  static propTypes = {    chartsData: PropTypes.object.isRequired, // 图形数据    idPrefix: PropTypes.oneOfType([      PropTypes.string.isRequired, // 唯一标识区分多个柱形图,,      PropTypes.number.isRequired, // 唯一标识区分多个柱形图,,    ]),    getCharts: PropTypes.func, // 把echarts 对象传出去    onResize: PropTypes.func, // 全局onResize事件,    eChartsEvent: PropTypes.func, // 图形点击事件, 返回这各图形的数据以及对应的param,echarts 对象    barWidth: PropTypes.string, // 柱子的宽度    bottom: PropTypes.string || PropTypes.number, // 底部距离    title: PropTypes.string, // 标题栏,名字    chartColor: PropTypes.string, // 柱形区域颜色    label: PropTypes.bool, // 是否展示x轴label    tooltip: PropTypes.bool, // 是否展示tooltip    options: PropTypes.object, // 修改 更新的想要的配置,直接那eCharts的就可以    deleteOption: PropTypes.array, // 删除不需要的配置    eventType: PropTypes.oneOf(_eventType), // 事件类型  };  static defaultProps = {    title: '',    barWidth: '25',    chartColor: '#1890ff',    label: false,    eventType: 'click',    bottom: '8%',    tooltip: true  };  componentDidMount() {    const {      chartsData, idPrefix, getCharts, onResize, title, chartColor,      label, deleteOption, options, eChartsEvent, eventType, barWidth,      bottom    } = this.props;    let myCharts = echarts.init(document.getElementById(`${idPrefix}_bar`));    if (getCharts && typeof func === 'function') {      getCharts(myCharts);    }    _eventType.map(item => {      myCharts.off(item);    });    let series = jsON.parse(jsON.stringify(chartsData.data));    myCharts.clear();    if (!chartsData.data.length) {      chartsData.data = [7, 8, 6, 9]    }    let option = {      color: series.length ? chartColor : ['#bfbfbf'],      title: {        text: title,        top: 20,        x: 'center'      },      toolbox: {        feature: {          saveAsImage: {            type: 'png',            title: '点击下载',          }        },        top: 13,        right: 13      },      tooltip: {        trigger: 'axis',        axisPointer: {   // 坐标轴指示器,坐标轴触发有效          type: 'shadow' // 默认为直线,可选为:'line' | 'shadow'        }      },      grid: {        left: '3%',        right: '4%',        bottom: series.length ? bottom : 40,        containLabel: true      },      xAxis: [        {          type: 'category',          data: series.length ? chartsData.xAxis : [],          axisTick: {            alignWithLabel: true          },          axisLine: {            lineStyle: {              color: series.length ? '#333' : '#ccc',            }          },          axisLabel: {            show: series.length && label,          }        }      ],      yAxis: [        {          type: 'value',          show: series.length,          splitLine: {            show: false,          },        }      ],      series: [        {          name: title,          type: 'bar',          barWidth,          data: chartsData.data        }      ],      graphic: series.length        ? null        : [{          type: 'text',          left: 'center',          bottom: 15,          cursor: 'auto',          style: {            text: '暂无数据',            textAlign: 'center',            fill: '#bfbfbf',            fontSize: 16,            stroke: '#bfbfbf',            lineWidth: 0          }        }]    };    if (deleteOption) {      deleteOption.map(item => {        delete option[item]      });    } // 删除函数    if (options) {      option = {...option, ...options}    } // 补充的options    if (eChartsEvent && typeof eChartsEvent === 'function') {      myCharts.on(eventType, 'series', params => {        eChartsEvent(params, chartsData, myCharts);      });    }    myCharts.setOption(option);    window.onresize = () => {      let target = this;      if (target.resizeFlag) {        clearTimeout(target.resizeFlag);      }      target.resizeFlag = setTimeout(function () {        myCharts.resize();        if (onResize && typeof onResize === 'function') {          onResize();        }        target.resizeFlag = null;      }, 100);    }  }  render() {    const {idPrefix} = this.props;    return (      <div        id={`${idPrefix}_bar`}        style={{width: '100%', height: '100%'}}/>    )  }}export default BarChart;



  • 上一条:
    vue表单校验
    下一条:
    页面刷新时vuex数据持久化问题的解决方案
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 使用 Alpine.js 排序插件对元素进行排序(0个评论)
    • 在js中使用jszip + file-saver实现批量下载OSS文件功能示例(0个评论)
    • 在vue中实现父页面按钮显示子组件中的el-dialog效果(0个评论)
    • 使用mock-server实现模拟接口对接流程步骤(0个评论)
    • vue项目打包程序实现把项目打包成一个exe可执行程序(0个评论)
    • 近期文章
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf文件功能(0个评论)
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • 在go + gin中gorm实现指定搜索/区间搜索分页列表功能接口实例(0个评论)
    • 在go语言中实现IP/CIDR的ip和netmask互转及IP段形式互转及ip是否存在IP/CIDR(0个评论)
    • PHP 8.4 Alpha 1现已发布!(0个评论)
    • Laravel 11.15版本发布 - Eloquent Builder中添加的泛型(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2016-11
    • 2017-06
    • 2017-07
    • 2017-08
    • 2017-09
    • 2017-10
    • 2017-11
    • 2018-03
    • 2018-04
    • 2018-05
    • 2018-06
    • 2018-09
    • 2018-11
    • 2018-12
    • 2019-02
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2021-04
    • 2021-05
    • 2021-07
    • 2021-08
    • 2021-09
    • 2021-10
    • 2021-11
    • 2022-08
    • 2022-09
    • 2022-10
    • 2022-11
    • 2022-12
    • 2023-01
    • 2023-02
    • 2023-03
    • 2023-04
    • 2023-05
    • 2023-06
    • 2023-07
    • 2023-09
    • 2023-10
    • 2023-11
    • 2023-12
    • 2024-01
    • 2024-02
    • 2024-03
    • 2024-04
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客