本文为稀土掘金技术社区首发签约文章,14天内禁止转载,14天后未获授权禁止转载,侵权必究!
📖阅读本文,你将
- 了解 配置驱动 的思想
- 理解
Echarts
基本概念 - 了解
graphic
和动画基本玩法
。 - 了解
Echarts
基底组件的封装的思路
一、不是标题党!Echarts
,简历上人均 “熟练”?
公司最近在招外包,而因为目前大屏的需求比较多,所以我就稍微关注了一下候选人们简历上对于 Echarts
的熟悉程度。
不看不知道,一看下一跳,Echarts
属实已经是业内人均 “熟练” 的基本技能了。
以上是短短几篇简历中摘选的自我描述,可以看出,Echarts
在大众研发的心中,已经是和 Antd
、ElementUI
、Bootstrap
相当的常用第三方库了。
所以,我就开始在面试中加入了关于 Echarts 使用的相关问题,想看看 熟练 到底是什么意思。
但是一轮问题问下来,大家好像又对它很陌生。
难道,所谓 熟练,就是能在社区里找到 Demo
,然后把配置项 Copy
到项目之中?
问:“现在你找到
Demo
了,但是Demo
没有显示图例(也就是那些彩色小方块小圆圈,表示各类数据颜色的东西),你应该查文档的什么关键词?”
答:“一时说不出来,但我肯定能试出来…”
问:“我想把UI出的一张图片放在饼图的背面,作为背景,应该怎么弄?”
答:“先去社区找找
Demo
吧…”
问:“这种
Demo
可能不太好找吧…而且有些场景,Demo
涉及的也不多,比如需要在某个特定位置放一些字,做一些动画,应该怎么办?”
答:……
虽然我的习惯和大家是一样的,遇到需求,先去社区里找一个相似度最高的 Demo
再说,但是开发大屏,怎么可能不遇到 “特异化、定制化” 的诉求呢?
当 Demo
帮不了你的时候,你是否可以熟练地通过文档,找到合适的解决之道呢?
如果 找DEMO 就是 熟练,那我建议咱还是先忘记 “万事求DEMO” 的这种熟练方式,重头捋一捋 Echarts
这个框架,先力求 入门 。
这就是标题所谓的,从 熟练 到 入门 的意思。
二、大屏图表,为什么我选 Echarts
?
在问出这个问题之前,我觉得还是先问一问:为什么不选Echarts
呢?
大屏的本质是什么?是讲故事,是给客户 量身定做 的讲故事!因此,大屏需求,更多的情况就是 做项目,而不是 做产品。
做项目,什么最重要?
六个字:成本低、效率高。
老板:你说复用、优雅?我都觉得好笑。
-
成本低
软件项目最大的成本,就是人的成本,现在哪怕是培训班刚出来的小萌新,哪怕他压根不知道g2plot
是什么,但简历上大概率会写上 熟练使用Echarts
。如果招到那种五六年的前端老兵,那Echarts
的API
熟练度只会更高。花更低的钱,能招来直接做项目的人,这就是成本低。
-
效率高
为什么Echarts
效率更高,因为它的社区实在太成熟,各种样式风格Demo
的沉淀实在太多。 比如:早期的Echarts gallery
(已被关闭)、又比如:www.isqqw.com/在这些社区里,你可以快速找到各类你想要的风格和实现,从而低成本改造成
UI
想要的样子。
Echarts
通常被拿来和 AntV
进行横向对比,关于孰优孰劣,某乎上的争论也比较大,但大家似乎都能达成一种共识:
社区方面,
Echarts
完胜。
社区完胜,效率就完胜,这是很容易推导的结果;毕竟,大多数时候,大家的开发模式就是 社区找相似度高的DEMO 。
另外,Echarts
早已经是 Apache
基金会在托管了,没有面向 KPI
的压力。(你懂我的意思吧?)
三、认识 Echarts
一个基于 JavaScript 的开源可视化图表库。 ——官网
一个看似什么都说了,却什么都没说的客观发言。
但是作为开发者,我们却需要通过阅读文档,自行去摸索一些更为核心的内容,以了解:“Echarts
能做什么? Echarts
擅长做什么? Echarts
有哪些特性? ”
- 它能开发图表、地图、做图形渲染
- 它擅长做图表开发
至于特性?
我虽然也只是 Echarts
入门使用者,我冒昧而经验地认为它的三个核心特性是:
- 1、配置驱动
- 2、事件驱动
- 3、图形能力
理解以上三点,我认为大概就能做到 “入门Echarts” 这个常用前端工具了。但本文还是会把重点放在 配置驱动 这个最为核心的能力讲解上。
3.1 什么是配置驱动
什么是 配置驱动?
这其实是很好理解的一个定义:
我只需要修改配置,就能让它显示的画面完成更新。
在使用 Echarts
的过程中,最重要的 API
一定是 Echarts.setOption
。
伪代码如下:
// 让图表显示状态A
chart.setOption(optionA)
// 让图表更新状态到B
chart.setOption(optionB)
对,这就是 配置驱动。
稍微改动官方示例:
<template>
<div class="chart" ref="chartEl"></div>
</template>
<script setup> const chartEl = ref(null); let chart = null const categories = ['老包', '老南', '老君'] const genDataArr = () => { return categories.map(t => { return Math.ceil(Math.random() * 100) }) } onMounted(() => { // 指定图表的配置项和数据 const chart = echarts.init(chartEl.value); const option = { tooltip: {}, legend: { data: ['黑子程度'] }, xAxis: { data: categories }, yAxis: {}, series: [ { name: '销量', type: 'bar', data: genDataArr() } ] }; chart.setOption(option) setInterval(() => { chart.setOption({ series: [ { data: genDataArr() } ] }) }, 1000) }) </script>
通过修改配置项中某一项的值,我们可以清晰看到呈现出的动态变化:
如果你无法看到上述 码上掘金 内容的变化,那有可能是因为网络原因,无妨,其 gif
效果如下:
配置驱动 就是这么直观,且易于理解。
它最大的优点就在于:
当我们希望图表从”状态A”进化到”状态B”时,我们其实无需关注当前的状态到底是什么样,我们只需要组装好”状态B”的配置,并将它交付给
Echarts
即可。
基本上,你可以利用 配置项 完成绝大多数工作上你遇到的各种需求。鲜明而无状态的 API
设计,也是它如此受到大家喜爱的根本原因。
本文,我们先专注于 配置驱动 封装一个能应对前端 90% 业务开发场景的基础 Vue3
基底组件。
3.2 配置项基本概念
配置项固然简单,但你首先需要知道 “我要实现某个能力实,应该去寻找什么样的配置” 。
对此,最快去了解各种概念的办法是看官方文档的 常用组件说明。
如果你觉得看文档不如看图片,我也单独整理了一份简图:
通过图中相关对照,我们可以在官方文档的配置项手册 中快速浏览相关内容的支持选项及用法。
3.3 轻度自定义的神器:graphic
以上配置项中,大多数能力都是 “Echarts
预设好,我们直接拿来用” 模式的,但难免会遇到产品经理或者 UI
同学突发奇想,增加一些特殊的文本或者图案,比如:
这种就属于,乍一眼看上去很容易,然后一琢磨:不对啊,DEMO
里找不到可以直接拿来用 的类型了。
怎么办?
‘graphic’ 可能是个不错的选择。
graphic
配置提供了以下节点能力的渲染配置:
- 图片
- 文本
- 元素组(可包含子节点,对子节点进行整体缩放、旋转等)
- 以及 其他各种图形,例如(圆形、扇形、环形、多边形、折线、矩形、直线、贝塞尔曲线、圆弧)
其中,我认为最常用的两种:
- 图片
- 文本
让我们先通过一个例子认识 图片 及 文本 的用法,核心代码如下:
option = {
...// 省略其他,
graphic: [
{
type: 'image',
style: {
image: 'https://pic.zhangshichun.top/pic/circle.png',
width: 150,
height: 150
},
top: 'middle',
left: 'center',
},
{
type: 'text',
style: {
x: 100,
y: 150,
text: `鸡你太美`,
fill: '#fff',
stroke: '#fff',
textAlign: 'center',
fontSize: 14
}
},
{
type: 'text',
style: {
x: 100,
y: 180,
text: `唱跳rap`,
fill: '#fff',
stroke: '#fff',
textAlign: 'center',
fontSize: 14
}
},
]
}
码上掘金相关片段,赶紧亲自试试:
效果图:
3.4 配置化与动画
细心的同学想必已经发现了,我并没有声明和动画相关的东西,但我上面的示例里已经有了最基本的 补间动画,这是因为 echarts
内置了一部分默认动画逻辑。
但实际上,你也拥有配置动画的能力
-
关键帧效果,以及循环动画
尝试在
type: 'image'
的元素上添加以下代码:{ // ... 其他配置暂且省略 transition: 'rotation', originX: 75, originY: 75, keyframeAnimation: { duration: 3000, loop: true, keyframes: [{ percent: 0.5, easing: 'linear', rotation: Math.PI }, { percent: 1, easing: 'linear', rotation: Math.PI * 2 }] } }
而你会看到如下效果:
鸡哥的篮球背景的圆环永远地滚动了起来。这个效果正是借助了
Echarts
提供的关键帧动画能力,指定时长、以及不同进度上元素应该表现的配置状态,驱使它完成了页面的渲染。 -
进入/离开/更新动画
关键帧动画更倾向于按照 编码者指定的方式 进行运转,而 “进入/离开/更新动画” 则适用于 更新数据状态时,自动获取动画 的能力。
看代码:// 移除上面 keyframeAnimation 这一段代码 // 增加以下代码: setInterval(() => { const rotation = Math.random() * 2 * Math.PI chart.setOption({ graphic: [ { rotation } ] }) }, 500)
效果如下:
鸡哥的篮球背景的圆环rap
起来了。
学会以上动画能力,也基本算可以称得上在 Echarts
使用上入门了,可以应对大多数 UI
和产品的奇思妙想了。
四、 基底组件的能力?
我对 基底组件 的期望,其实很简单:
- 它能自适应容器的宽高,并让自身的图表自适应容器宽高的变化
这当然是痛点了,我不止一次,不止在一个项目里,发现大屏进行布局调整、或者是浏览器页面大小调整后,图表的大小变得不适宜。依靠研发在紧张工期下,依然保持严谨的防御性代码编写习惯,是一种奢望。
- 它能具备基础的主题能力
大屏通常有自己的主题色,自带 “主题色” 的
Echarts
组件,可以让研发节省大量时间。 - 当数据为空时,它能智能的显示 “空值缺省”
试想,哪个客户希望对着一个空空如也的折线图猜测用意呢?此时,一句简简单单的 暂无数据 是多么的贴心。
- 它应该给我最大限度的 自定义 的能力
永远不要失去能力,封装的意义在于 增强,而不是 阉割。
基于以上诉求,我们可以开始设计自己的 Echarts 基底组件 的API。
src/components/BaseECharts/index.vue
// 提供 props 属性 empty,让组件稳定感知当前是否是空数据
defineProps({
empty: {
type: Boolean,
default: false
}
})
// 向外弹射事件 'resize'
const emits = defineEmits(['resize'])
defineExpose(
{
// 向父组件暴露方法:获得ECharts实例
getChart: () => {
},
// 向父组件暴露方法:更新ECharts配置
setOption: (v) => {
}
}
)
五、如何实现动态适配容器宽高
先了解一个 API
: ResizeObserver
。 (MDN相关参考)
通过 ResizeObserver
,我们可以从容地监听某个元素的尺寸变化。
既然这个 API
这么优秀,那我们直接用它?你们可以随便用,但本老年 vue-coder
选择逻辑完备的 Hooks
: useElementSize,一行代码解决元素尺寸监听的问题:
const el = ref(null)
const { width, height } = useElementSize(el) // width和 height 都是响应式的 `ref` 对象
然后再监听相关变化,适时地调用 chart.resize()
方法即可:
watchEffect(() => {
if (width.value && height.value) {
emits('resize', { width: width.value, height: height.value })
chartRef.value?.resize();
}
})
这样,当视窗大小变化后,相关的图表也会重新根据新视窗的大小调整尺寸。
而在 @resize
事件里,用户因为得到了 {width, height}
,对于一些依赖绝对尺寸的场景,也可以从容更新 option
,保证 resize
后尺寸不会出现问题。
比如,在父组件中,我们可以这样写:
<template>
<BaseECharts @resize="size => onResize(size)" ref="chartRef"></BaseECharts>
</template>
<script setup>
import BaseECharts from '@/components/BaseECharts'
const chartRef = ref(null)
const genOption = ({ width, height }) => {
const minSideLength = Math.min(width, height)
return {
series: [
// ...其他选项省略
{
radius: [0.3 * minSideLength, 0.4 * minSideLength],
center: [minSideLength / 2, minSideLength / 2],
type: 'pie',
}
]
}
}
const onResize = (size) => {
const option = genOption(size)
chartRef.value.setOption(option)
}
</script>
从而实现 “像素级” 的尺寸操控(当然,能用百分比解决的就用百分比,但某些场景不支持百分比,那就必须上像素了);
六、如何具备内置的主题色?
首先,ECharts
是支持自定义主题的,访问: echarts.apache.org/zh/theme-bu…
可以通过左侧的操作栏,让 UI
同学快速定制一套适合你们系统的主题色,然后导出主题 json
配置文件,并将它存在 ‘@/theme/echarts-dark.json’ 文件中。
在 src/main.js
中写如下带代码:
import * as ECharts from "echarts";
import theme from '@/theme/echarts-dark.json'
ECharts.registerTheme('dark', theme)
完成对主题的注册,(写在 main.js
是为了避免重复注册),当然,如果要充分组件化的话,此处应该有 vue-plugin
。
然后,在基底组件中如此写:
onMounted(() => {
const chart = Echarts.init(chartEl.value, 'dark');
})
完成对主题的初始化。
七、空值缺省
这一步,其实不太涉及到 Echarts
本身的内容,只需要通过判断 empty
属性,通过 v-show
切换展示内容。
为什么用
v-show
不用v-if
? 为了降低echarts
实例周期管理的复杂度。
src/components/BaseECharts/index.vue
<template>
<div class="chart">
<div v-show="!empty" class="chart__el" ref="chartEl"></div>
<NoData v-show="empty" class="chart__empty"></NoData>
</div>
</template>
八、总结
通过:
- 学习配置驱动的思想
- 理解
Echarts
基本概念 - 学习
graphic
和动画基本玩法
。 - 完成基底组件的封装
你已经可以胜任简单大屏项目图表的快速开发和迭代了,此时,如果在简历上写上 入门 Echarts
使用,应该就不会再出现尴尬的场景了吧。
面对面试官高深场景的问题,也可以理直气壮地回答一句:
我就入门水平,你还想怎样?
今天的文章大屏图表,ECharts 从“熟练”到入门分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/21676.html