preface
Ecarts is a chart control commonly used by us. It is particularly powerful. It is cumbersome to check the API every time you use it. Here are the commonly used configurations in development.
Official website: https://echarts.apache.org/handbook/zh/get-started
Configuration item: https://echarts.apache.org/zh/option.html#title
Third party sample platforms: https://www.makeapie.com/explore.html
quote
install
npm install echarts --save
quote
import * as echarts from 'echarts'; // Initialize the ecarts instance based on the prepared dom var myChart = echarts.init(document.getElementById('main')); // Draw a chart myChart.setOption({ title: { text: 'ECharts Getting started example' }, tooltip: {}, xAxis: { data: ['shirt', 'cardigan', 'Chiffon shirt', 'trousers', 'high-heeled shoes', 'Socks'] }, yAxis: {}, series: [ { name: 'sales volume', type: 'bar', data: [5, 20, 36, 10, 10, 20] } ] });
Set rendering mode
Mode selection
In the scene with good software and hardware environment and small amount of data, both renderers can be applied without too much entanglement.
In scenes with poor environment and performance problems that need to be optimized, you can determine which renderer to use through experiments.
For example, these experiences:
- When you need to create many ecarts instances and the browser is prone to crash (perhaps because the memory occupation exceeds the capacity of the mobile phone due to the large number of Canvas), you can use the SVG renderer to improve it. Roughly speaking, if the chart is running on a low-end Android, or we are using some specific charts, such as Water polo diagram Etc., the SVG renderer may work better.
- When the amount of data is large (empirical judgment > 1K) and there are many interactions, it is recommended to select the Canvas renderer.
Set code
// Use the Canvas renderer (default) var chart = echarts.init(containerDom, null, { renderer: 'canvas' }); // Equivalent to: var chart = echarts.init(containerDom); // Using the SVG renderer var chart = echarts.init(containerDom, null, { renderer: 'svg' });
Data change re rendering
chart.setOption(option, notMerge, lazyUpdate);
Or:
chart.setOption(option, { notMerge: false, lazyUpdate: false, silent: false });
Parameter interpretation:
- option See the configuration item manual for the configuration items and data of the chart.
- notMerge Optional, whether to not merge with the previously set option. The default is false, that is, merge.
- lazyUpdate Optional. Whether to not update the chart immediately after setting the option. The default is false, that is, update immediately.
- silent Optional. Prevent events from being thrown when calling setOption. The default value is false, that is, events are thrown.
The second parameter, notMerge, is set to true, that is, the previous options are not merged and the new options are used.
Size of response container
var myChart = echarts.init(document.getElementById('main')); window.onresize = function() { myChart.resize(); };
Note that when used in combination with VUE, you must wait for the DOM rendering to complete before calling, otherwise it will not take effect.
async leftbar_click() { this.show_left = !this.show_left; await this.$nextTick(); this.echart && this.echart.resize() }
In addition to calling resize() directly without parameters, you can also specify the width and height to achieve the effect that the chart size is not equal to the container size.
myChart.resize({ width: 800, height: 400 });
VUE encapsulation chart auto scaling
VUE encapsulates components to automatically scale the chart with page changes.
resize.js
import { debounce } from '@/utils/utils.js' export default { data() { return { $_mDom: null, $_resizeHandler: null } }, mounted() { this.initListener() }, activated() { if (!this.$_resizeHandler) { // avoid duplication init this.initListener() } // when keep-alive chart activated, auto resize this.resize() }, beforeDestroy() { this.destroyListener() }, deactivated() { this.destroyListener() }, methods: { // use $_ for mixins properties // https://vuejs.org/v2/style-guide/index.html#Private-property-names-essential $_sidebarResizeHandler(e) { if (e.propertyName === 'width') { this.$_resizeHandler() } }, initListener() { this.$_resizeHandler = debounce(() => { this.resize() }, 100) window.addEventListener('resize', this.$_resizeHandler) this.$_mDom = document.getElementById('app') this.$_mDom && this.$_mDom.addEventListener('transitionend', this.$_sidebarResizeHandler) }, destroyListener() { window.removeEventListener('resize', this.$_resizeHandler) this.$_resizeHandler = null this.$_mDom && this.$_mDom.removeEventListener('transitionend', this.$_sidebarResizeHandler) }, resize() { const { chart } = this chart && chart.resize() } } }
utils.js
/** * @param {Function} func * @param {number} wait * @param {boolean} immediate * @return {*} */ export function debounce(func, wait, immediate) { let timeout, args, context, timestamp, result const later = function() { // According to the last trigger interval const last = +new Date() - timestamp // The last call interval of the wrapped function last is less than the set interval wait if (last < wait && last > 0) { timeout = setTimeout(later, wait - last) } else { timeout = null // If it is set to immediate===true, because the start boundary has been called, there is no need to call here if (!immediate) { result = func.apply(context, args) if (!timeout) context = args = null } } } return function(...args) { context = this timestamp = +new Date() const callNow = immediate && !timeout // If the delay does not exist, reset the delay if (!timeout) timeout = setTimeout(later, wait) if (callNow) { result = func.apply(context, args) context = args = null } return result } }
Call in custom chart component
import * as echarts from 'echarts' import resize from "@/components/charts/mixins/resize.js" export default { mixins: [resize], data() { return { chart: null, }; }, }
Complete example
PieRateChart.vue
<template> <div :class="className" :style="{ height: height, width: width }"/> </template> <script> import * as echarts from 'echarts' import resize from "@/components/charts/mixins/resize.js" export default { mixins: [resize], props: { className: { type: String, default: "chart", }, width: { type: String, default: 0, }, height: { type: String, default: "300px", }, title: { type: String, default: '' }, mRate: { type: String, default: () => { return "0" } } }, data() { return { chart: null, }; }, watch: { mRate: function () { this.initChart() } }, async mounted() { await this.$nextTick(); this.initChart(); }, beforeDestroy() { if (!this.chart) { return; } this.chart.dispose(); this.chart = null; }, methods: { initChart() { if (!this.chart) { this.chart = echarts.init(this.$el); } let title = this.title; let num = parseFloat(this.mRate); let mydata = [num, 100 - num]; let opts = { backgroundColor: '#ffffff', tooltip: { show: true, }, color: ['#3c90f7', '#55bfc0'], series: [ { type: 'pie', radius: ['60%', '80%'], center: ['50%', '50%'], hoverAnimation: true, data: mydata, itemStyle: { normal: { borderWidth: 2, borderColor: '#ffffff', }, }, label: { show: false, }, }, ], title: { text: num + '%', top: '38%', textAlign: 'center', left: '49%', textStyle: { color: '#666', fontSize: 16, fontWeight: '400', }, }, }; this.chart.setOption(opts) }, } }; </script>
Configuration item
title
Title component, including main title and subtitle.
title:{ show:true, text : '', textStyle:{ color: '#333' , fontStyle: 'normal' , fontWeight: 'bolder' , fontFamily: 'sans-serif' , fontSize: 18 , lineHeight ... , width ... , height ... , textBorderColor ... , textBorderWidth ... , textBorderType: 'solid' , textBorderDashOffset: 0 , textShadowColor: 'transparent' , textShadowBlur: 0 , textShadowOffsetX: 0 , textShadowOffsetY: 0 , overflow: 'none' , ellipsis: '...' , }, subtext: '' , subtextStyle:{}, zlevel: 0 , z: 2 , left: 'auto' , top: 'auto' , right: 'auto' , bottom: 'auto' , }
xAxis/yAxis
The x/y axis in a rectangular coordinate system grid. Generally, a single grid component can only be placed on the next two x/y axes at most. More than two x/y axes need to be configured offset Property prevents overlapping of multiple x/y axes at the same location.
xAxis:[ { type: "category", data: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"], axisTick: { alignWithLabel: true, }, axisLabel: { rotate: 20 }, nameLocation: "end", name: "%" }, ]
axisTick: axis scale related settings.
axisLabel: related settings of axis scale label.
name: related is the text on one side of the axis, such as the display unit.
Custom label content
option = { yAxis: { axisLabel: { formatter: '{value} element', align: 'center' } } };
grid
For the drawing grid in the rectangular coordinate system, the upper and lower X axes and the left and right Y axes can be placed in a single grid. You can draw on a mesh Line chart,Histogram,Scatter chart (bubble chart).
grid: { top: 20, left: "2%", right: "2%", bottom: 10, containLabel: true, },
Percentages and specific values can be used in all four directions
When containLabel is true, left right top bottom width height determines the position of the rectangle formed by all contents including the coordinate axis label.
legend
Legend components.
The legend component shows different series of symbols, colors and names. You can control which series are not displayed by clicking the legend.
legend: { type: 'plain', orient: 'horizontal', data: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"], bottom: 20, align: 'left', textStyle: { color: '#333', }, itemGap: 10, formatter: (name) => { let item = null; for (const _item of chartData) { if (_item.chainName === name) { item = _item; break; } } if (item) { return name + ' ' + item.total + 'second ' + ((item.successCount * 100) / item.total).toFixed(1) + '%'; } else { return name; } }, },
Of which:
- itemGap: the interval between each item in the legend. Horizontal spacing for horizontal layout and vertical spacing for vertical layout.
tooltip
Suspension frame assembly.
tooltip: { show: true, formatter: '{b0}Success rate: {c0}%', },
dataZoom
The dataZoom component is used for area scaling, so that you can freely pay attention to the detailed data information, or overview the data as a whole, or remove the influence of outliers.
dataZoom: { right: '2%', //Distance of the lower slider from the bottom of the x-axis top: '5%', height: '90%', //Height adjustment of lower slider handle width: 20, type: 'slider', //Type, sliding block plug-in show: true, //Show lower slider yAxisIndex: [0], //Selected y-axis start: 0, //How much does the initial data show end: 100, //What is the maximum initial data displayed },
series
Line chart
series: [ { data: [820, 932, 901, 934, 1290, 1330, 1320], type: 'line', smooth: true } ]
Histogram
series: [ { type: 'bar', showBackground: false, data: valueData, barWidth: 16, itemStyle: { normal: { color: '#3c90f7', barBorderRadius: [0, 8, 8, 0], }, }, emphasis: { itemStyle: { color: specialColor, }, }, }, ],
Of which:
- emphasis: highlight graphic styles and label styles.
Pie chart
series: [ { type: 'pie', radius: ['30%', '45%'], center: ['50%', '30%'], hoverAnimation: true, itemStyle: { normal: { borderWidth: 2, borderColor: '#ffffff', label: { show: true, position: 'outside', color: '#ddd', formatter: function (params) { var percent = 0; var total = 0; for (var i = 0; i < mydata.length; i++) { total += mydata[i].value; } percent = ((params.value / total) * 100).toFixed(0); if (params.name !== '') { return 'name:' + params.name + '\n' + '\n' + 'proportion:' + percent + '%'; } else { return ''; } }, }, labelLine: { length: 30, length2: 100, show: true, color: '#00ffff', }, }, }, label: { show: false, }, data: mydata, labelLine: { show: true, }, }, ],
other
Multiple drawings
option = { xAxis: [ { type: 'category', gridIndex: 0, data: ['1 month', '2 month', '3 month'] }, { type: 'category', gridIndex: 1, data: ['4 month', '5 month', '6 month'], position: 'top' }, ], yAxis: [ { gridIndex: 0 }, { gridIndex: 1, inverse: true } ], grid: [ { bottom: '55%' }, { top: '55%' } ], series: [ // These series appear in the first Cartesian coordinate system { type: 'bar', data: [1, 5, 10] }, { type: 'bar', data: [2, 4, 3] }, // These series will appear in the second rectangular coordinate system, { type: 'line', xAxisIndex: 1, yAxisIndex: 1, data: [2, 5, 8] }, { type: 'line', xAxisIndex: 1, yAxisIndex: 1, data: [8, 2, 6] }, ], };
Two key attributes:
- Position in xAxis: 'top'
- Inverse in yAxis: true
The effects are as follows:
Gradient
var specialColor = { type: 'linear', x: 0, y: 0, x2: 1, y2: 0, colorStops: [ { offset: 0, color: '#3c90f7 ', / / color at 0% }, { offset: 1, color: '#55bfc0 ', / / color at 100% }, ], globalCoord: false, // The default is false }; option={ series: [ { type: 'bar', showBackground: false, data: [1,3,5,2,4], barWidth: 16, itemStyle: { normal: { color: '#3c90f7', barBorderRadius: [0, 8, 8, 0], }, }, emphasis: { itemStyle: { color: specialColor, }, }, }, ], }