vue3中多组件Echarts适应元素尺寸变化
vue
vuejs/vue: 是一个用于构建用户界面的 JavaScript 框架,具有简洁的语法和丰富的组件库,可以用于开发单页面应用程序和多页面应用程序。
项目地址:https://gitcode.com/gh_mirrors/vu/vue
免费下载资源
·
文章目录
导读
多组件适应元素尺寸变化的核心代码是,实例中
resize.js
中的代码,调用方式参照lineChart.vue
中的代码。
1.下载 echarts
npm i -s echarts
2.在main.js中引入
import { createApp } from 'vue'
import App from './App.vue'
// 引入 echarts
import * as echarts from 'echarts'
const app = createApp(App)
// 全局挂载 echarts
app.config.globalProperties.$echarts = echarts
app.mount('#app')
3.实例:结合 ResizeObserver
适应元素尺寸变化
以若依为例
效果图
文件结构
├── src
├── views
├── dashboard
├── mixins
├── resize.js
├── BarChart.vue
├── LineChart.vue
├── PanelGroup.vue
├── PieChart.vue
└── RaddarChart.vue
├── index.vue
详细代码
resize.js
(核心)
/**
* @desc 函数节流
* @param fn 函数
* @param wait 延迟执行毫秒数
*/
const throttle = function (fn, wait) {
let timer = null;
return function () {
let context = this;
let args = arguments;
if (!timer) {
// 当延迟时间结束后,执行函数
timer = setTimeout(() => {
timer = null;
fn.apply(context, args);
}, wait)
}
}
};
let ro = null;
let charts = [];
// 创建并返回一个新的 ResizeObserver 对象
const newRO = function (callback) {
// ResizeObserver 接口监视 Element 内容盒或边框盒或者 SVGElement 边界尺寸的变化。
!ro && (ro = new ResizeObserver(callback));
};
/**
*
* @param {Object} chartVal 初始化的echarts实例
* @param {Object} domElement 被监听尺寸变化的dom元素
*/
function resize(chartVal, domElement) {
charts.push(chartVal);
const throttledFun = throttle(() => {
charts.forEach((item) => {
item.resize(); // 调整echarts尺寸
});
}, 1000, false);
newRO(throttledFun);
// 添加监听事件
function initListener() {
ro.observe(domElement); // 观察一个或多个元素
}
// 调用函数添加监听事件:
initListener();
}
// 移除观察者对某一个元素的监听
function destroyListener(chartVal, domElement) {
charts = charts.filter((item) => item !== chartVal);
ro.unobserve(domElement); // 取消特定观察者目标上所有对 Element 的监听。
}
export {resize, destroyListener};
lineChart.vue
(其他同级chart组件类似)
<template>
<div ref="container" :class="props.className" :style="{ width: props.width, height: props.height }" />
</template>
<script setup>
import { ref, onMounted, onBeforeUnmount, onActivated, onDeactivated, watch } from 'vue';
import { resize, destroyListener } from "./mixins/resize"
const { proxy } = getCurrentInstance();
let echarts = proxy.$echarts;
const props = defineProps({
className: { type: String, default: 'chart', required: false },
width: { type: String, default: '100%', required: false },
height: { type: String, default: '350px', required: false },
autoResize: { type: Boolean, default: true, required: false },
chartData: { type: Object, required: true },
})
let chart = null;
const container = ref(null); // echarts图表的容器元素
watch(
() => props.chartData, (newValue, oldValue) => {
setOptions(newValue);
},
{ deep: true }
)
onMounted(() => {
initChart();
})
onActivated(() => resize(chart, container.value))
onDeactivated(() => destroyListener(chart, container.value))
onBeforeUnmount(() => {
if (!chart) {
return;
}
chart.dispose(); // 销毁图表
chart = null;
})
const initChart = function () {
chart = echarts.init(container.value, 'macarons')
// 监听 echarts 的 finished 事件
let resizeObserverAdded = false;
chart.on('finished', function () {
if (!resizeObserverAdded) {
resize(chart, container.value);
}
resizeObserverAdded = true;
});
setOptions(props.chartData);
}
const setOptions = function ({ expectedData, actualData } = {}) {
chart.setOption({
xAxis: {
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
boundaryGap: false,
axisTick: {
show: false
}
},
grid: {
left: 10,
right: 10,
bottom: 20,
top: 30,
containLabel: true,
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross',
},
padding: [5, 10],
},
yAxis: {
axisTick: {
show: false,
}
},
legend: {
data: ['expected', 'actual']
},
series: [{
name: 'expected', lineStyle: {
color: '#FF005A',
lineStyle: {
color: '#FF005A',
width: 2,
}
},
smooth: true,
type: 'line',
data: expectedData,
animationDuration: 2800,
animationEasing: 'cubicInOut',
},
{
name: 'actual',
smooth: true,
type: 'line',
lineStyle: {
color: '#3888fa',
lineStyle: {
color: '#3888fa',
width: 2,
},
areaStyle: {
color: '#f3f8ff',
}
},
data: actualData,
animationDuration: 2800,
animationEasing: 'quadraticOut',
}]
})
}
</script>
index.vue
<template>
<div class="dashboard-editor-container">
<panel-group @handleSetLineChartData="handleSetLineChartData" />
<el-row style="background: #fff; padding: 16px 16px 0; margin-bottom: 20px">
<line-chart :chart-data="lineChartData" />
</el-row>
<el-row :gutter="20">
<el-col :xs="24" :sm="24" :lg="8">
<div class="chart-wrapper">
<raddar-chart />
</div>
</el-col>
<el-col :xs="24" :sm="24" :lg="8">
<div class="chart-wrapper">
<pie-chart />
</div>
</el-col>
<el-col :xs="24" :sm="24" :lg="8">
<div class="chart-wrapper">
<bar-chart />
</div>
</el-col>
</el-row>
</div>
</template>
<script setup name="Index">
import PanelGroup from './dashboard/PanelGroup'
import LineChart from './dashboard/LineChart'
import RaddarChart from './dashboard/RaddarChart'
import PieChart from './dashboard/PieChart'
import BarChart from './dashboard/BarChart'
const staticLineChartData = {
newVisitis: {
expectedData: [100, 120, 161, 134, 105, 160, 165],
actualData: [120, 82, 91, 154, 162, 140, 145]
},
messages: {
expectedData: [200, 192, 120, 144, 160, 130, 140],
actualData: [180, 160, 151, 106, 145, 150, 130]
},
purchases: {
expectedData: [80, 100, 121, 104, 105, 90, 100],
actualData: [120, 90, 100, 138, 142, 130, 130]
},
shoppings: {
expectedData: [130, 140, 141, 142, 145, 150, 160],
actualData: [120, 82, 91, 154, 162, 140, 130]
}
}
const lineChartData = ref(staticLineChartData.newVisitis)
const handleSetLineChartData = (type) => {
lineChartData.value = staticLineChartData[type]
}
</script>
<style lang="scss" scoped>
.dashboard-editor-container {
background-color: rgb(240, 242, 245);
position: relative;
.chart-wrapper {
background: #fff;
padding: 16px 16px 0;
margin-bottom: 32px;
}
}
@media (max-width: 1024px) {
.chart-wrapper {
padding: 8px;
}
}
</style>
GitHub 加速计划 / vu / vue
207.55 K
33.66 K
下载
vuejs/vue: 是一个用于构建用户界面的 JavaScript 框架,具有简洁的语法和丰富的组件库,可以用于开发单页面应用程序和多页面应用程序。
最近提交(Master分支:3 个月前 )
73486cb5
* chore: fix link broken
Signed-off-by: snoppy <michaleli@foxmail.com>
* Update packages/template-compiler/README.md [skip ci]
---------
Signed-off-by: snoppy <michaleli@foxmail.com>
Co-authored-by: Eduardo San Martin Morote <posva@users.noreply.github.com> 5 个月前
e428d891
Updated Browser Compatibility reference. The previous currently returns HTTP 404. 6 个月前
更多推荐
已为社区贡献3条内容
所有评论(0)