先展现一个echarts,并配置dataZoom,每页最多10条数据,超出滚动
<div class="echartsBox" id="echartsBox"></div>
onMounted(() => {nextTick(() => {var chartDom = document.getElementById('echartsBox');myChart = echarts.init(chartDom);option = {grid: {left: '0px', // 图表左边距right: '50px', // 图表右边距top: '50px', // 图表上边距bottom: '0px', // 图表下边距containLabel: true // 包含坐标轴标签在内},graphic: [{type: 'text',left: '15', // 根据需要调整位置top: '20', // 根据需要调整位置z: 100, // 设置 z 轴数值较高,确保文本显示在最前面style: {text: '课程内容', // 指定要显示的文本fill: '#666666', // 文本颜色fontSize: '14px',}}],yAxis: {// name: '课程内容',type: 'category',data: ['A1', 'A2', 'A3', 'A4', 'A5', 'A6', 'A7', 'A8', 'A9', 'A10', 'A11', 'A12', 'A13', 'A14', 'A15', 'A16', 'A17', 'A18', 'A19', 'A20', 'A21', 'A22', 'A23', 'A24', 'A25'],inverse: true,},xAxis: {name: '得分',type: 'value',min: 5,max: 0,axisLabel: {formatter: function (value: any) {return Math.floor(value); // 取整数部分}},},dataZoom: [{type: "slider",realtime: true, // 拖动时,是否实时更新系列的视图// show:false, // 是否展示滚动条根据数据判断startValue: 0,endValue: 9, // 最多10条 超出滚动width: 5,height: "75%",top: "12.5%",right: 0,brushSelect: false,yAxisIndex: [0, 1], // 控制y轴滚动fillerColor: "#0093ff", // 滚动条颜色borderColor: "rgba(17, 100, 210, 0.12)",backgroundColor: "#cfcfcf", //两边未选中的滑动条区域的颜色handleSize: 0, // 两边手柄尺寸showDataShadow: false, //是否显示数据阴影 默认autoshowDetail: false, // 拖拽时是否展示滚动条两侧的文字zoomLock: true,moveHandleStyle: {opacity: 0,},},{type: "inside",startValue: 0,endValue: 10,minValueSpan: 10,yAxisIndex: [0],zoomOnMouseWheel: false, // 关闭滚轮缩放moveOnMouseWheel: true, // 开启滚轮平移moveOnMouseMove: true, // 鼠标移动能触发数据窗口平移},],series: [{data: [5, 0, 3, 2, 1, 5, 4, 3, 2, 1, 5, 4, 3, 2, 1, 5, 4, 3, 2, 1, 5, 4, 3, 2, 1],type: 'bar',label: {show: true,position: 'right',formatter: '{c}分', // 显示数值textStyle: {color: '#333',fontSize: 14}},itemStyle: {color: function (params: any) {// 根据数据值取整后选择颜色var value = Math.round(params.data);var colors = ['#A6A6A6', '#FF7F2D', '#FCC946', '#A2C081', '#619C8A', '#016B25'];return colors[value];}},}]};option && myChart.setOption(option);})
})
效果:
调用echarts中getDataURL获取图表的数据 URL
// 下载echarts
const downloadBtn = (() => {nextTick(() => {const loading = ElLoading.service({lock: true,text: '图表生成中',background: 'rgba(0, 0, 0, 0.7)',})// 需要3s左右生成setTimeout(() => {loading.close()// 获取图表的数据 URLvar dataURL = myChart.getDataURL({type: 'png', // 可以根据需要修改为其他格式,如 'jpeg'pixelRatio: 2, // 图片分辨率,根据需要进行调整backgroundColor: '#fff' // 图片背景色,根据需要进行调整});// 创建一个虚拟的下载链接并模拟点击下载var link = document.createElement('a');link.href = dataURL;link.download = 'echarts_image.png'; // 下载的文件名,可以根据需要修改link.style.display = 'none';document.body.appendChild(link);link.click();document.body.removeChild(link);}, 3000)})
})
问题来了:如数据不分页则可以下载全数据,如数据分页了则只能下载出可视区内容,如何解决?
解决思路:echarts最终生成了canvas,canvas的宽高就是当前可视区的宽高,那么是否可以动态计算高度???
解决:
新增一个容器,这个容器为动态计算高度后导出使用
<!-- 导出echarts使用 --><div id="newEchartsBox" style="display:none;"></div>
// 下载echarts
const downloadBtn = (() => {// 获取完整的数据const fullData = myChart.getOption();let newOption = fullDatanewOption.dataZoom = []// var chartDom: any = document.getElementById('newEchartsBox');chartDom.style.width = '600px'chartDom.style.height = 50 * fullData.series[0].data.length + 'px'// newMyChart = echarts.init(chartDom);// newOption && newMyChart.setOption(newOption);// nextTick(() => {const loading = ElLoading.service({lock: true,text: '图表生成中',background: 'rgba(0, 0, 0, 0.7)',})// 需要3s左右生成setTimeout(() => {loading.close()// 获取图表的数据 URLvar dataURL = newMyChart.getDataURL({type: 'png', // 可以根据需要修改为其他格式,如 'jpeg'pixelRatio: 2, // 图片分辨率,根据需要进行调整backgroundColor: '#fff' // 图片背景色,根据需要进行调整});// 创建一个虚拟的下载链接并模拟点击下载var link = document.createElement('a');link.href = dataURL;link.download = 'echarts_image.png'; // 下载的文件名,可以根据需要修改link.style.display = 'none';document.body.appendChild(link);link.click();document.body.removeChild(link);}, 3000)})
});
通过getOption获取echarts数据,根据数据长度动态设置新容器的高度,并赋值,赋值时把dataZoom清空,这里就不需要分页了,因为不做回显。
然后通过新容器调用echarts导出图片,问题完美解决。
源码如下:
<template><div class="kcnrzt"><div class="left"><div class="l">已选<br />课程内容</div><div class="r"><el-scrollbar><div class="list"><div class="item">11111111111111111111111111111111111111111111111111111111111111111</div><div class="item">11111111111111111111111111111111111111111111111111111111111111111</div><div class="item">11111111111111111111111111111111111111111111111111111111111111111</div><div class="item">11111111111111111111111111111111111111111111111111111111111111111</div><div class="item">11111111111111111111111111111111111111111111111111111111111111111</div><div class="item">11111111111111111111111111111111111111111111111111111111111111111</div></div></el-scrollbar></div></div><div class="right"><div class="exportBtn" @click="downloadBtn">导出报告</div><div class="echartsBox" id="echartsBox"></div></div></div><!-- 导出echarts使用 --><div id="newEchartsBox" style="display:none;"></div>
</template><script setup lang="ts">
import { ElLoading } from 'element-plus'
import { watch, onMounted, onBeforeUnmount, nextTick } from 'vue'
import { dataStore } from '@/store'
let store = dataStore()
import * as echarts from 'echarts';//
var myChart: any = null
var option: any = null
// 导出专用
var newMyChart: any = nullonMounted(() => {nextTick(() => {var chartDom = document.getElementById('echartsBox');myChart = echarts.init(chartDom);option = {grid: {left: '0px', // 图表左边距right: '50px', // 图表右边距top: '50px', // 图表上边距bottom: '0px', // 图表下边距containLabel: true // 包含坐标轴标签在内},graphic: [{type: 'text',left: '15', // 根据需要调整位置top: '20', // 根据需要调整位置z: 100, // 设置 z 轴数值较高,确保文本显示在最前面style: {text: '课程内容', // 指定要显示的文本fill: '#666666', // 文本颜色fontSize: '14px',}}],yAxis: {// name: '课程内容',type: 'category',data: ['A1', 'A2', 'A3', 'A4', 'A5', 'A6', 'A7', 'A8', 'A9', 'A10', 'A11', 'A12', 'A13', 'A14', 'A15', 'A16', 'A17', 'A18', 'A19', 'A20', 'A21', 'A22', 'A23', 'A24', 'A25'],inverse: true,},xAxis: {name: '得分',type: 'value',min: 5,max: 0,axisLabel: {formatter: function (value: any) {return Math.floor(value); // 取整数部分}},},dataZoom: [{type: "slider",realtime: true, // 拖动时,是否实时更新系列的视图// show:false, // 是否展示滚动条根据数据判断startValue: 0,endValue: 9, // 最多10条 超出滚动width: 5,height: "75%",top: "12.5%",right: 0,brushSelect: false,yAxisIndex: [0, 1], // 控制y轴滚动fillerColor: "#0093ff", // 滚动条颜色borderColor: "rgba(17, 100, 210, 0.12)",backgroundColor: "#cfcfcf", //两边未选中的滑动条区域的颜色handleSize: 0, // 两边手柄尺寸showDataShadow: false, //是否显示数据阴影 默认autoshowDetail: false, // 拖拽时是否展示滚动条两侧的文字zoomLock: true,moveHandleStyle: {opacity: 0,},},{type: "inside",startValue: 0,endValue: 10,minValueSpan: 10,yAxisIndex: [0],zoomOnMouseWheel: false, // 关闭滚轮缩放moveOnMouseWheel: true, // 开启滚轮平移moveOnMouseMove: true, // 鼠标移动能触发数据窗口平移},],series: [{data: [5, 0, 3, 2, 1, 5, 4, 3, 2, 1, 5, 4, 3, 2, 1, 5, 4, 3, 2, 1, 5, 4, 3, 2, 1],type: 'bar',label: {show: true,position: 'right',formatter: '{c}分', // 显示数值textStyle: {color: '#333',fontSize: 14}},itemStyle: {color: function (params: any) {// 根据数据值取整后选择颜色var value = Math.round(params.data);var colors = ['#A6A6A6', '#FF7F2D', '#FCC946', '#A2C081', '#619C8A', '#016B25'];return colors[value];}},}]};option && myChart.setOption(option);})// window.addEventListener('resize', updateEcharts);
})
//
onBeforeUnmount(() => {myChart.dispose();// window.removeEventListener('resize', updateEcharts);
})
//
const updateEcharts = (() => {nextTick(() => {myChart.resize();})
})
//
watch(() => store.isCollapse,() => {setTimeout(() => { updateEcharts() }, 300);},{immediate: false, // 是否初始化立即执行一次, 默认是falsedeep: true // 是否是深度监视, 默认是false}
)// 下载echarts
const downloadBtn = (() => {// 获取完整的数据const fullData = myChart.getOption();let newOption = fullDatanewOption.dataZoom = []// var chartDom: any = document.getElementById('newEchartsBox');chartDom.style.width = '600px'chartDom.style.height = 50 * fullData.series[0].data.length + 'px'// newMyChart = echarts.init(chartDom);// newOption && newMyChart.setOption(newOption);// nextTick(() => {const loading = ElLoading.service({lock: true,text: '图表生成中',background: 'rgba(0, 0, 0, 0.7)',})// 需要3s左右生成setTimeout(() => {loading.close()// 获取图表的数据 URLvar dataURL = newMyChart.getDataURL({type: 'png', // 可以根据需要修改为其他格式,如 'jpeg'pixelRatio: 2, // 图片分辨率,根据需要进行调整backgroundColor: '#fff' // 图片背景色,根据需要进行调整});// 创建一个虚拟的下载链接并模拟点击下载var link = document.createElement('a');link.href = dataURL;link.download = 'echarts_image.png'; // 下载的文件名,可以根据需要修改link.style.display = 'none';document.body.appendChild(link);link.click();document.body.removeChild(link);}, 3000)})
});
</script><style scoped lang="scss">
.kcnrzt {flex: 1;display: flex;justify-content: space-between;overflow: hidden;margin: 20px 15px;.left {width: 50%;height: 100%;border: 1px solid #DEDEDE;display: flex;overflow: hidden;margin-right: 20px;.l {width: 87px;border-right: 1px solid #DEDEDE;display: flex;align-items: center;justify-content: center;text-align: center;overflow: hidden;}.r {flex: 1;overflow: hidden;.list {.item {padding: 10px;font-size: 14px;font-family: Microsoft YaHei;font-weight: 400;color: #333333;line-height: 22px;border-bottom: 1px solid #DEDEDE;}}}}.right {width: 50%;height: 100%;position: relative;margin-left: 20px;.exportBtn {width: 81px;height: 30px;background: #FFB100;border-radius: 6px;font-size: 14px;font-family: Microsoft YaHei;font-weight: 400;color: #FFFFFF;line-height: 30px;text-align: center;cursor: pointer;position: absolute;top: 0;right: 0;z-index: 999;}.echartsBox {width: 100%;height: 100%;}}
}
</style>