Now all kinds of frameworks and libraries are very powerful, but also because of their powerful functions, many configurations are too heavy, so there are only a few that are really useful. Today, we encapsulate a general-purpose cylindrical graph based on echarts!
If you want to know about other components, you can see that other components I encapsulated before have good ideas or other components that will be shared.
Transverse drag time axis based on antd package
The general cylindrical graph mainly contains several parts.
- title display, label display on xAxis;
- maxShow, bar chart display should not be more than 12, otherwise it will affect the beauty (or observation data);
- In UI, we need to support the modification of the color and width of the column without data hints.
- In terms of interaction, we need to support the most basic click events, double-click events, return to temporarily fix the data part of the current click, all data sets and echarts objects. Besides click events, we also need to support resize, so that when the viewport changes, the pie chart will be redrawn accordingly.
- Support the most commonly used toolbox, tooltip and other configurations;
- Need to support deletion, new configuration (sometimes we encapsulate the imperfect need the user to execute the configuration part);
Realization function
Based on the above points, we started to write code:
In the component DidMount cycle, we accept the attributes from the parent component and construct the most basic option. Before constructing the option, we first do the processing of maxShow.
First declare an empty data to be processed
let newChartsData = [];
Then process 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: 'Other'}]; } else { newChartsData = [...chartsData] }
* Note here that we default not to deal with maxShow, that is to say, adding parent not to pass, so the default is all displayed, without using zoom configuration, it is recommended that maxShow=12 is the best; specific time default 12 or default not to deal with the data to be processed by users, I deal with most of the data situation. In this case, it will not be more than 12, so it will not be processed by default.
Initialize the sketchpad, build option s, etc.
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: 'Click to download', } }, 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, //How wide is the border set? borderColor: bgColor, }, hoverAnimation: false, hoverOffset: 0, data: newChartsData.length ? newChartsData : [{value: 0, name: 'No data'}], }, ], graphic: newChartsData.length ? null : [{ type: 'text', left: 'center', top: radius[0] === '0' ? 'auto' : center[1], bottom: 10, cursor: 'auto', style: { text: 'No data', textAlign: 'center', fill: '#bfbfbf', fontSize: 16, stroke: '#bfbfbf', lineWidth: 0 } }] };
In addition, I added the display code about no data. See the way I encapsulated it before. Flexible encapsulation of react pie chart components based on echarts There is no repetition here.
Add and delete additional configuration functions, instantiate option s
if (deleteOption) { deleteOption.map(item => { delete option[item] }); } // Delete function if (options) { option = {...option, ...options} } // Supplementary options myCharts.setOption(option);
Add click event return value, resize anti-jitter function
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); }
Complete code
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'; /* * Column Graph Component * Including no data to show, onresize redraw events * You can customize option s to support multiple mouse events * Other functions such as zoom, zoom, etc., which are not encapsulated for the time being, can be added through options'own definitions * deleteOption: ['title', 'toolbox', 'tooltip', 'graphic'] Containing attributes contained in echarts * * */ /* * chartsData format * const barChartsData = { * xAxis: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'], * data:[10, 52, 200, 334, 390, 330, 220] * }; * Standby color: * '#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, // graphic data idPrefix: PropTypes.oneOfType([ PropTypes.string.isRequired, // Unique identification distinguishes multiple bar graphs. PropTypes.number.isRequired, // Unique identification distinguishes multiple bar graphs. ]), getCharts: PropTypes.func, // Getting echarts objects out onResize: PropTypes.func, // Global onResize event, eChartsEvent: PropTypes.func, // Graphic click events, return the data of each graph and the corresponding param, echarts objects barWidth: PropTypes.string, // Width of column bottom: PropTypes.string || PropTypes.number, // Bottom distance title: PropTypes.string, // Title bar, name chartColor: PropTypes.string, // Column area color label: PropTypes.bool, // Is the x-axis label displayed? tooltip: PropTypes.bool, // Do you show tooltip? options: PropTypes.object, // Modify the configuration you want to update, directly to eCharts deleteOption: PropTypes.array, // Delete unwanted configurations eventType: PropTypes.oneOf(_eventType), // Event type }; 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: 'Click to download', } }, top: 13, right: 13 }, tooltip: { trigger: 'axis', axisPointer: { // Coordinate axis indicator, coordinate axis trigger is effective type: 'shadow' // The default is a straight line, optional:'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: 'No data', textAlign: 'center', fill: '#bfbfbf', fontSize: 16, stroke: '#bfbfbf', lineWidth: 0 } }] }; if (deleteOption) { deleteOption.map(item => { delete option[item] }); } // Delete function if (options) { option = {...option, ...options} } // Supplementary 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;
Two more pictures
Normally displayed
Display of no data
Color matching website
The default color of the bar chart I choose is the default color matching of ant gallery, many small partners do not know how to match the color, then below and share several color matching websites (basically cut out from our company UE mouth);
- antd official colour - with this basic is enough
- Colordot - A color picker for humans
- Colourco.de - find your colour palette
- Color Scheme Designer 3 Advanced Online Colour Matching Device Colour Matching Network
- Color Hunt - Trendy Color Palettes