前言
很多项目都会用到echarts,特别是做统计项目的时候,图表展现数据的形式确实更直接,echarts在很多时候能满足我们的需求,里面超级多的api,配置非常的灵活自由,但是不熟悉的时候容易不知道怎么配置,最近正好做了一个,来总结一下,大家有需要参考!
使用
项目框架
我们用的nuxt框架 vue3+nuxt3
nuxt框架 引入包的写法都是一样的
版本号
"nuxt": "3.0.0-rc.12"
"echarts": "5.1.2"
代码部分
1.下载包(如果不指定版本号就是最新版本的包)
npm install echarts@5.1.2 --save
2.plugins文件夹创建echarts.ts文件,内容如下
import * as echarts from 'echarts/core'
import { GridComponent } from 'echarts/components'
import { LineChart } from 'echarts/charts'
import { CanvasRenderer } from 'echarts/renderers'
echarts.use([GridComponent, LineChart, CanvasRenderer])
export default defineNuxtPlugin(nuxtApp => {
return {
provide: {
echarts: echarts
}
}
})
3.在nuxt.config.js中配置插件(根据项目自身 不需要可不引入)
特别注意:nuxt3以上版本应该是不需要引入了,根据项目情况而定
plugins: [
{ src: "~/plugins/echarts.ts", ssr: false },
],
4.页面上使用
仅写了web的样式 h5需要的自己可以微调 图中切换M的时候颜色有点暗 可能看不太清
这个是由于两边渐变色值导致的 可以换
<template>
<div class="echarts-container">
<div class="echarts-content-box">
<div class="echarts-tab">
<div
:class="echartVal == 'D' ? 'title-active title-day' : 'title-day'"
@click="changeEchart('D')"
>D
</div>
<div
:class="echartVal == 'W' ? 'title-active title-week' : 'title-week'"
@click="changeEchart('W')"
>W</div>
<div
:class="echartVal == 'M' ? 'title-active title-mouth' : 'title-mouth'"
@click="changeEchart('M')"
>M</div>
</div>
<div class="echarts-content">
<div class="left">
<span>24H</span><p>${{ Number(leftShowNum) == 0 ? 0 : leftShowNum }}</p>
</div><div id="echartsBox" class="right"></div>
</div>
</div>
</div>
</template>
<script lang="ts">
import * as echarts from 'echarts'
import { defineComponent, computed, onMounted, ref } from 'vue'
export default defineComponent({
setup() {
//左侧展示的value值
const leftShowNum = ref('')
//日周月变量
const echartVal = ref('D')
//图表数据对象
const echartDateObj: any = ref({})
//判断是h5还是web
function windowWidth() {
var de = document.documentElement
return self.innerWidth || (de && de.offsetWidth) || document.body.offsetWidth
}
onMounted(() => {
setTimeout(() => {
// if (windowWidth() < 750) {
//h5
// }else{}
getEchartDate(40, 100, 16, 'vol', 'day')
}, 100)
})
const changeEchart = val => {
echartVal.value = val
if (val == 'D') {
getEchartDate(40, 100, 16, 'vol', 'day')
} else if (val == 'W') {
getEchartDate(30, 100, 30, 'vol', 'wek')
} else if (val == 'M') {
getEchartDate(20, 100, 40, 'vol', 'mon')
}
}
const getEchartDate = async (val, num, width, title, date) => {
// const { data } = await fetch('数据接口')
let list :any
if (date=='day') {
list = [{ 'num': '1', 'date': '2023-01-12T00:00:00Z' },
{ 'num': '12', 'date': '2023-01-13T00:00:00Z' },
{ 'num': '3', 'date': '2023-01-14T00:00:00Z' },
{ 'num': '24', 'date': '2023-01-15T00:00:00Z' },
{ 'num': '15', 'date': '2023-01-16T00:00:00Z' },
{ 'num': '46', 'date': '2023-01-17T00:00:00Z' },
{ 'num': '27', 'date': '2023-01-18T00:00:00Z' },
{ 'num': '8', 'date': '2023-01-19T00:00:00Z' },
{ 'num': '19', 'date': '2023-01-20T00:00:00Z' },
{ 'num': '10', 'date': '2023-01-21T00:00:00Z' },
{ 'num': '11', 'date': '2023-01-22T00:00:00Z' },
{ 'num': '22', 'date': '2023-01-23T00:00:00Z' },
{ 'num': '13', 'date': '2023-01-24T00:00:00Z' },
{ 'num': '14', 'date': '2023-01-25T00:00:00Z' },
{ 'num': '16', 'date': '2023-01-26T00:00:00Z' },
{ 'num': '19', 'date': '2023-01-27T00:00:00Z' },
{ 'num': '20', 'date': '2023-01-28T00:00:00Z' },
{ 'num': '27.335291', 'date': '2023-01-29T00:00:00Z' },
{ 'num': '30', 'date': '2023-01-30T00:00:00Z' },
{ 'num': '27.52708', 'date': '2023-01-31T00:00:00Z' },
{ 'num': '42.431682', 'date': '2023-02-01T00:00:00Z' },
{ 'num': '29.000345', 'date': '2023-02-02T00:00:00Z' },
{ 'num': '30.295383', 'date': '2023-02-03T00:00:00Z' },
{ 'num': '20', 'date': '2023-02-04T00:00:00Z' },
{ 'num': '40', 'date': '2023-02-05T00:00:00Z' },
{ 'num': '20', 'date': '2023-02-06T00:00:00Z' },
{ 'num': '10', 'date': '2023-02-07T00:00:00Z' },
{ 'num': '25.947509', 'date': '2023-02-08T00:00:00Z' },
{ 'num': '24.002308', 'date': '2023-02-09T00:00:00Z' },
{ 'num': '10.800104', 'date': '2023-02-10T00:00:00Z' },
{ 'num': '9', 'date': '2023-02-11T00:00:00Z' },
{ 'num': '8', 'date': '2023-02-12T00:00:00Z' },
{ 'num': '7', 'date': '2023-02-13T00:00:00Z' },
{ 'num': '10.871253', 'date': '2023-02-14T00:00:00Z' },
{ 'num': '6.067091', 'date': '2023-02-15T00:00:00Z' },
{ 'num': '8.266358', 'date': '2023-02-16T00:00:00Z' },
{ 'num': '11.452223', 'date': '2023-02-17T00:00:00Z' },
{ 'num': '10', 'date': '2023-02-18T00:00:00Z' },
{ 'num': '3', 'date': '2023-02-19T00:00:00Z' },
{ 'num': '2.257111', 'date': '2023-02-20T00:00:00Z' },
{ 'num': '1', 'date': '2023-02-21T00:00:00Z' }]
}else if (date=='wek') {
list = [{ 'num': '1', 'date': '2023-01-12T00:00:00Z' },
{ 'num': '8', 'date': '2023-01-19T00:00:00Z' },
{ 'num': '16', 'date': '2023-01-26T00:00:00Z' },
{ 'num': '29.000345', 'date': '2023-02-02T00:00:00Z' },
{ 'num': '24.002308', 'date': '2023-02-09T00:00:00Z' },
{ 'num': '8.266358', 'date': '2023-02-16T00:00:00Z' }]
}else{
list = [{ 'num': '1', 'date': '2023-01-12T00:00:00Z' },
{ 'num': '8.266358', 'date': '2023-02-16T00:00:00Z' }]
}
const result: any = {
//每一项数据的日期
categoryData: [],
//每一项数据的value值
valueData: []
}
if (list) {
list.forEach(item => {
result.categoryData.push(item.date.slice(0, 10))
result.valueData.push(item.num)
})
}
echartDateObj.value = result
initialize(num, width)
}
const volTime = ref({ day: '', month: '', year: '', current: '' })
const mouthEn = months => {
return months == 1
? 'Jan'
: months == 2
? 'Feb'
: months == 3
? 'Mar'
: months == 4
? 'Apr'
: months == 5
? 'May'
: months == 6
? 'Jun'
: months == 7
? 'Jul'
: months == 8
? 'Aug'
: months == 9
? 'Sep'
: months == 10
? 'Oct'
: months == 11
? 'Nov'
: 'Dec'
}
const initialize = (val, wid) => {
const chartpillar: any = document.getElementById('echartsBox')
const myPillar = echarts.init(chartpillar)
//用来做图上渐变色
const colorList = [
'#182025',
'#181E23',
'#192832',
'#1B2B38',
'#1C2F3E',
'#1F3444',
'#1E3545',
'#213B4F',
'#254156',
'#26455A',
'#294961',
'#2D4E67',
'#2E536C',
'#335772',
'#365C78',
'#3B6380',
'#3F6886',
'#406987',
'#45708E',
'#487393',
'#4F7B9C',
'#5580A3',
'#5886A9',
'#5F8BAF',
'#6390B4',
'#6390B4',
'#5F8BAF',
'#5886A9',
'#5580A3',
'#4F7B9C',
'#487393',
'#45708E',
'#406987',
'#3F6886',
'#3B6380',
'#365C78',
'#335772',
'#2E536C',
'#2D4E67',
'#294961',
'#26455A',
'#254156',
'#213B4F',
'#1E3545',
'#1F3444',
'#1C2F3E',
'#1B2B38',
'#192832',
'#181E23',
'#182025'
]
let optionPillar: any = {
tooltip: {
trigger: 'axis',
//显示框始终固定在图形顶部
position: function (point, params, dom, rect, size) {
console.log(point,'point')
//返回鼠标x、y(横向、纵向)两个点的位置
return [point[0] - 50, '10%']
},
backgroundColor: '#3B6380',
borderColor: 'transparent',
extraCssText: 'height:24px;',
formatter: function (params) {
let months = params[0].axisValue.slice(5, 7)
let value = mouthEn(months)
const day = params[0].axisValue.slice(8, 10)
const month = value
const year = params[0].axisValue.slice(0, 4)
volTime.value = {
day: day,
month: month,
year: year,
current: ''
}
console.log(params[0].value, 'params[0].value')
leftShowNum.value = params[0].value
return ' '
+ day + ' ' + month + ' ' + year + ' '
},
textStyle: {
color: '#909DB4',
innerHeight: '24',
lineHeight: '24' // 行高
},
padding: 0,
axisPointer: {
type: 'line',
lineStyle: {
width: 4,
type: 'solid',
color: 'blue'
}
}
},
xAxis: {
max: echartDateObj.value.categoryData.length > 40
? 40 : echartDateObj.value.categoryData.length - 1,
type: 'category',
axisTick: {
show: false
},
axisLine: {
show: false
},
splitLine: {
show: false
},
splitArea: {
show: false
},
data: echartDateObj.value.categoryData,
axisLabel: {
formatter: (val, index) => {
let showdata: any
let months = val.slice(5, 7)
let mValue = mouthEn(months)
if (echartVal.value == 'M') {
showdata = mValue
} else {
showdata = val.slice(8, 10)
}
return `${showdata}`
}
}
},
yAxis: {
show: false,
max: function (value) {
return value.max
},
splitArea: { show: false }
},
dataZoom: [
{
type: 'inside',
start: 0,
end: val,
zoomLock: true
}
],
series: [
{
data: echartDateObj.value.valueData,
type: 'bar',
itemStyle: {
normal: {
barBorderRadius: 1,
color: params => {
return colorList[params.dataIndex]
}
}
},
barWidth: wid //柱图宽度
}
],
grid: {
left: 0,
top: 0,
// bottom: 0,
right: 24
}
}
if (document.body.clientWidth < 750) {
optionPillar.grid = {
// bottom: 20,
left: 4,
top: 0,
bottom: 20,
right: 24
}
}
optionPillar.tooltip.backgroundColor = '#3B6380'
// 对实例对象进行设置配置
optionPillar && myPillar.setOption(optionPillar)
myPillar.on('globalout', params => {
volTime.value = { day: '', month: '', year: '', current: '' }
leftShowNum.value = ''
})
}
return {
changeEchart,
echartVal,
volTime,
leftShowNum
}
}
})
</script>
<style lang="less" scoped>
@import '../assets/css/base.less';
.echarts-container {
width:920px;
padding: 0 2px;
.echarts-content-box {
margin: 200px 0;
padding-top: 16px;
display: flex;
flex-direction: column;
align-items: flex-end;
position: relative;
.echarts-tab {
padding-right: 20px;
display: flex;
align-items: center;
z-index: 99999;
margin-bottom: 8px;
p {
color: @textActive;
margin-bottom: 0 !important;
margin-right: 10px;
}
> div {
cursor: pointer;
width: 24px;
height: 24px;
background: @cardEmphasize;
border: 1px solid transparent;
text-align: center;
line-height: 24px;
color: @textDefault;
&:hover {
color: @textActive;
}
}
.title-active {
color: @textActive;
border: 1px solid @borderDefault;
background: @buttonDetailDefault;
}
}
.echarts-content {
width: 100%;
height: 300px;
padding: 20px 0px 10px 0px;
display: flex;
justify-content: space-between;
.left {
position: absolute;
top: 16px;
left: 0;
span {
font-size: 14px;
color: @textDefaultStats;
}
p {
margin-bottom: 0 !important;
color: blue;
font-size: 20px;
font-weight: 800;
}
}
.right {
margin-bottom: 100px ;
width: 100%;
height: 316px;
padding: 0px;
z-index: 9999;
}
}
}
}
</style>
代码贴上了,如果效果类似,可直接粘贴到项目里面调,现在拆开看下属性
代码梳理--api讲解
代码有点多,都贴进去了,看起来感觉是一团乱麻,但是拆开来看就比较好理解了。
页面上的代码使用的四个方法
首先页面上我们用到了四个方法changeEchart(),getEchartDate(),mouthEn(),initialize()。
1.changeEchart方法
- 传了1个val参数,用来根据日周月来重新获取图表数据的,点击日或者周或者月,我们就可以重新调取接口,获取我们想要的日或者周或者月的数据
2.getEchartDate方法
- 传了5个参数,里面大多是获取接口数据时用到的,但是案例中没有接口,我直接把数据写死了
valtitledate这三个是接口需要的,不多说了numwidth这两个是初始化图表用的,num用来表示数据窗口范围的结束百分比,width是表示柱状图一根多宽
- 有接口时我们可以将获取的数据处理成我们想要的样子放到echartDateObj对象中,一般回来的都是数组的形式,数组里面是一个一个的对象,对象里面是日期和value值,但是我们需要把日期和value值分开重新放到两个数组里面用,所以上面把日期放到了echartDateObj对象的categoryData中,把value值放到了valueDate中
3.mouthEn方法
- 主要是用来处理数据的,把月份转为英文的月份,需求需要
4.initialize方法
- initialize我们就比较熟悉了,初始化图表。具体说下api
echarts -- api
一.tooltip:鼠标移到图表上面显示x,y轴具体信息
1.trigger:
- tooltip可以显示x,y轴的相关数据的
- 默认值
item,可选值item、axis - 当trigger为
item时只会显示该点的数据,为axis时显示该列下所有坐标轴所对应的数据。
2.position:
- tooltip的位置设置,五个参数,tooltip默认是根据鼠标的移动而移动,视觉焦点始终是与鼠标保持一致,但我们可以根据需求对tooltip的位置做特殊处理,让其固定在图形顶部。详细设置可以参考www.shulanxt.com/visualizati… ,实在是有点多,然后找了一篇相对详细的博客,可以看下(如侵权可删除)
point: 鼠标位置,是一个数组,如 [20, 50]params: Object|Array. 是需要的数据集dom: tooltip 的 dom 对象。 rect:一个对象,只有鼠标在图形上时有效,是一个用 x, y, width, height 四个属性表达的图形包围盒。size: 一个对象,包括 dom 的尺寸和 echarts 容器的当前尺寸,例如:{contentSize: [width, height], viewSize: [width, height]}size中有两个属性: viewSize为外层div的大小,contentSize为tooltip提示框的大小
3.backgroundColor:
- tooltip背景颜色,效果等同
optionPillar.tooltip.backgroundColor = '#色值'
4.borderColor:
- tooltip边框颜色,效果等同
optionPillar.tooltip.borderColor = '#色值'
5.extraCssText:
- tooltip---设置css,比如案例中
extraCssText: 'height:64px;'
6.formatter:
- 打印了下params参数,可以参考,有比较全的x轴和y轴的各种信息,或者到时候你们打印自己项目里的,可以根据需求和params来组织tooltip
7.textStyle:
- tooltip---文本的css设置,比如案例中颜色行高等
8.axisPointer:
- 是坐标轴指示器,默认是 x 轴
- 其实也可以改变为 y 轴,如下:
tooltip.axisPointer.axis = 'y',
xAxis.axisPointer.lineStyle.color = "#f00";
yAxis.axisPointer.lineStyle.color = "#0f0";
此时会发现十字相交线的竖线是红色,横线是绿色line: 鼠标移上去,所在值出现一条指示线,默认针对 x 轴,即竖线shadow: 鼠标移上去,所在值出现一条指示阴影(类似于一个小矩形),默认针对 x 轴cross: 鼠标移上去,所在值出现纵横交叉的指示线none: 鼠标移上去,无指示
二.xAxis: x坐标轴相关属性
更多详细配置可查看juejin.cn/post/709933… ,这个是掘金上其他博主总结的,我看着很详细,有需要可以参考(如侵权可删除)
1. max: x轴最多显示数据条数
2. type: 坐标轴类型
value: 数值轴,适用于连续数据category: 类目轴,适用于离散的类目数据,为该类型时必须通过 data 设置类目数据time: 时间轴,适用于连续的时序数据,与数值轴相比时间轴带有时间的格式化,在刻度计算上也有所不同,例如会根据跨度的范围来决定使用月,星期,日还是小时范围的刻度log: 对数轴,适用于对数数据
3.axisTick: 坐标轴刻度相关配置
show: Boolean,默认值true,是否显示坐标轴刻度
4.axisLine: 坐标轴轴线相关配置
show: Boolean,默认true, 是否显示坐标轴轴线
5.splitLine: 坐标轴在 grid 区域中的分隔线
show: Boolean,是否显示分隔线。默认数值轴显示,类目轴不显示
6.splitArea: 坐标轴在 grid 区域中的分隔区域,默认不显示
show: Boolean ,默认true, 是否显示分隔区域
7.date: Array 类目数据,x轴数据数组,也就是我们上述中的日期数组
- Array 类目数据,在类目轴(type: 'category')中有效
- 如果没有设置 type,但是设置了 axis.data,则认为 type 是 'category'
- 如果设置了 type 是 'category',但没有设置 axis.data,则 axis.data 的内容会自动从 series.data 中获取
- 注意,axis.data 指明的是 'category' 轴的取值范围
- 如果不指定而是从 series.data 中获取,那么只能获取到 series.data 中出现的值
- 如果series.data 为空时,就什么也获取不到
8.axisLabel: 坐标轴刻度标签的相关设置 (刻度对应的文本)
formatter: String/Function 刻度标签的内容格式器 ,x轴刻度上显示的文案- 支持模板字符串和回调函数两种形式
- 使用模板字符串,模板变量为刻度默认标签 {value}
- 使用函数模板,函数参数分别为刻度数值(类目),刻度的索引
三.yAxis: y坐标轴相关属性
1. show: 是否显示y轴刻度
2. max: y轴刻度的最大值设置
四.dataZoom: 用于区域缩放
1. type:
- 两个值,第一个就是slider,有单独的滑动条,用户在滑动条上进行缩放或漫游
- 另一个值是inside,内置于坐标系中,使用户可以在坐标系上通过鼠标拖拽、鼠标滚轮、手指滑动(触屏上)来缩放或漫游坐标系。
2. start: 窗口初始显示数据的范围
3. end: 窗口范围结束的百分比
4. zoomLock: 是否锁定视图,或者说限制窗口的大小
五.series: 系列图标配置,图表类型
1. date: 图表数据,这里的数据是y轴数据,所以我们写的对应日期的value值
2. type: 图表类型
bar:柱状/条形图line:折线/面积图pie:饼图scatter:散点(气泡)图effectScatter:带有涟漪特效动画的散点(气泡)radar:雷达图tree:树型图treemap:树型图sunburst:旭日图boxplot:箱形图candlestick:K线图heatmap:热力图map:地图parallel:平行坐标系的系列lines:线图graph:关系图sankey:桑基图funnel:漏斗图gauge:仪表盘pictorialBar:象形柱图themeRiver:主题河流custom:自定义系列
3. itemStyle: 单个数据项样式
六.grid: 图标离容器的距离
1. show: Boolean,是否显示直角坐标系网格
2. left: 图表离容器左侧的距离
3. top: 图表离容器顶部的距离
4. right: 图表离容器右侧的距离
5. bottom: 图表离容器底部的距离
6. backgroundColor: 网格背景色,rgba或#000
7. borderColor: 网格的边框颜色,rgba或#000
8. borderWidth: 网格的边框线宽,number
总结
echats的api真的超级超级多,我们的需求大多时候它都是可以满足的,但是这个api是真的不好找,本文也就仅仅是写了一部分用到的api,补充的不多,想找完整的还是得按照单个api查详细的说明,但是如果有ui跟这个很类似的那就比较好了,直接拿去用~记得想看哪个属性的话用目录找,文章太长了,不好查。