一.先看效果:
大家好呀,⭐⭐⭐⭐⭐,秉着分享快乐的原则,我又来啦~
echarts不就是去官网复制然后粘贴吗,为什么要封装?
1.减少代码量,每次只要传宽度,高度与option配置项便能快速生成图表。
2.原先的echarts并不能自适应屏幕大小变化。
3.原先的echarts并不能自适应父盒子大小变化。
原先自适应存在问题(重):
1.当屏幕改变,图表不会重新动态改变并渲染:
2.当图表标签的父盒子大小改变时,图表不会重新动态改变并渲染:
3.当屏幕改变,图表不会重新动态改变并渲染 (解决后) :
4. 当图表标签的父盒子大小改变时,图表不会重新动态改变并渲染 (解决后) :
二.详细实现:
1. 组件要传的值:
先分析需求,比如组件名字为my-echarts,一般传个width(宽)、height(高)、option(配置项)这三个就可以了,如:
<my-echarts
:width="'80%'"
:height="'20vw'"
:option="option1"
></my-echarts>
2. 实现组件代码:
在一个vue脚手架工程里,可以在components目录下新建一个 MyEcharts.vue 文件,具体功能代码看注释:
<template>
<!-- 定义标签 -->
<div
:id="id"
:style="{
width: width,
height: height,
}"
></div>
</template>
<script>
import * as echarts from "echarts";
// 2.生成一个 id 值给标签,目的是为了当多次使用组件防止id重复
const uid = function () {
return new Date().getTime();
};
export default {
//1.获取传过来的值
props: {
width: {
typeof: String,
},
height: {
typeof: String,
},
option: {
typeof: Object,
default() {
return null;
},
},
},
data() {
return {
//3.在这定义 id 与 myChart图表实例 , 方便管理
id: null,
myChart: null,
};
},
created() {
// 4.id赋值
this.id = uid();
},
mounted() {
// 5. 创建echarts图表实例
this.myChart = echarts.init(document.getElementById(this.id));
// 指定图表的配置项和数据
var option = this.option;
// 使用刚指定的配置项和数据显示图表。
this.myChart.setOption(option);
},
};
</script>
3. 基本使用:
此时便可以在其它地方使用my-echarts组件,比如我在 App.vue使用该组件:
导入:
import MyEcharts from "./components/MyEcharts.vue";
注册:
components: {
MyEcharts,
},
定义option数据,(可以随便去echarts官网复制一个):
data() {
return {
//三角形柱状图
option1: {
tooltip: {
trigger: "axis",
formatter: `{b}<br/>
{a}: {c} 千人`,
},
//图表的内边距
grid: {
left: "3%",
top: "20%",
right: "3%",
bottom: "1%",
show: true,
borderColor: "rgb(47,32,71)",
containLabel: true,
},
xAxis: {
data: ["衬衫", "羊毛衫", "雪纺衫", "裤子"],
type: "category",
axisLabel: {
show: true,
color: "rgb(142,175,220)",
},
axisTick: {
//不显示刻度线
show: false,
},
axisLine: {
show: true,
lineStyle: {
width: 1,
color: "rgba(47,32,71)",
},
},
// 区域分割线
splitLine: {
show: false,
lineStyle: {
color: "rgba(204, 204, 204,0.3)",
},
},
},
yAxis: {
name: "单位:千人",
nameTextStyle: {
color: "rgb(142,175,220)",
},
// 区域分割线
splitLine: {
lineStyle: {
color: "rgba(47,32,71)",
},
},
axisTick: {
show: false,
},
axisLabel: {
show: true,
color: "rgb(142,175,220)",
},
axisLine: {
lineStyle: {
show: true, //是否显示坐标轴轴线,
color: "white", //y轴轴线的颜色
width: 0.5, //x轴粗细
},
},
},
series: [
{
name: "销量",
//三角形柱状图
type: "pictorialBar",
barCategoryGap: "30",
symbol:
"path://M0,10 L10,10 C5.5,10 5.5,5 5,0 C4.5,5 4.5,10 0,10 z",
//渐变色
itemStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: "#188df0" },
{ offset: 0.5, color: "#188df0" },
{ offset: 1, color: "#83bff6" },
]),
},
data: [5, 20, 36, 10],
},
],
},
};
},
定义标签:
<my-echarts
:width="'80%'"
:height="'20vw'"
:option="option1"
></my-echarts>
4. 当屏幕改变,图表重新动态改变并渲染(重点):
echarts自带一个resize()方法能重新渲染绘制图表,但是要手动调用它,那么我们用window.onresize事件方法,当屏幕大小改变就调用echarts的resize()方法。
在 MyEcharts.vue 组件文件里添加:
。。。略
mounted() {
// 当屏幕改变,图表重新动态改变并渲染
var that = this;
window.onresize = function () {
that.myChart.resize();
};
},
。。。略
此时便可以:
5. 当图表标签的父盒子大小改变时,图表重新渲染(重):
这个方法我们新建一个mixin.js文件写,随意地方建,到时导入路径写对就行,然后在MyEcharts.vue里通过混入mixin.js文件,能更方便复用,代码实现详细看注释:
// echarts 自适应父盒子变化大小
const myMixin = {
methods: {
resize() {
// 当宽高变化时就会执行
//执行某些操作 重新改变图表, 同时传参,设置动画效果
this.myChart.resize({animation: {duration:1000}});
},
},
//自定义指令,图表的宽度采用百分比,父盒子宽度变化,那图表盒子大小也变化了,但是图表不会重新绘制
//原理:判断盒子本身宽度改变了,再调用echarts的resize方法重新绘制
directives: {
// 使用局部注册指令的方式
resize: {
// 指令的名称
bind(el, binding) {
// el为绑定的元素,binding为绑定给指令的对象
let width = "",
height = "";
function isReize() {
//这个方法可以获取元素的css样式对象
const style = document.defaultView.getComputedStyle(el);
//对比跟上次宽度是否改变,如果改变了
if (width !== style.width || height !== style.height) {
//调用resize方法
binding.value(); // 关键
}
//记录当前宽高
width = style.width;
height = style.height;
}
//设置监听器,每隔一段时间对比看看
el.__vueSetInterval__ = setInterval(isReize, 300);
},
//只调用一次,指令与元素解绑时调用
unbind(el) {
//清除定时器
clearInterval(el.__vueSetInterval__);
},
},
},
}
export {myMixin};
在MyEcharts.vue 混入:
先定义自定义指令:
<div
v-resize="resize"
:id="id"
:style="{
width: width,
height: height,
}"
></div>
然后在混入mixin.js:
import { myMixin } from "../assets/mixins/mixin.js";
export default {
mixins: [myMixin],
//.....略
}
此时便实现如下:
6. 题外话:
第五步,说到底,是监听dom元素变化,我用的是定时器每隔一段时间监听一次,其实并不好,浪费性能。而 ResizeObserver API 这个新特性就可以帮助我们监听一个DOM节点的变化。但是这是一个实验中的功能,有兴趣可以自行查阅看看。我也可以专门出一篇文章,需要的话,哈哈~
三.总结:
上面就是全部功能实现啦,是比较简单的,有不明白的可以评论区留言呀~😆😆😆
下次见,拜拜~ ┏(^0^)┛
推荐一部电影给你们- - -小森林(超治愈~)
我的哔哩哔哩空间
Gitee仓库地址:全部特效源码
Q群聊(欢迎):629596039
其它文章:
~关注我看更多简单创意特效:
文字烟雾效果 html+css+js
环绕倒影加载特效 html+css
气泡浮动背景特效 html+css
简约时钟特效 html+css+js
赛博朋克风格按钮 html+css
仿网易云官网轮播图 html+css+js
水波加载动画 html+css
导航栏滚动渐变效果 html+css+js
书本翻页 html+css
3D立体相册 html+css
霓虹灯绘画板效果 html+css+js
记一些css属性总结(一)
Sass总结笔记
…等等
进我主页看更多~