解决echarts配置滚动(dataZoom)后导出图片数据不全问题
先展现一个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>
相关文章:
解决echarts配置滚动(dataZoom)后导出图片数据不全问题
先展现一个echarts,并配置dataZoom,每页最多10条数据,超出滚动 <div class"echartsBox" id"echartsBox"></div>onMounted(() > {nextTick(() > {var chartDom document.getElementById(echartsBox);…...
【vue3+ts】项目初始化
1、winr呼出cmd,输入构建命令 //用vite构建 npm init vitelatest//用cli脚手架构建 npm init vurlatest2、设置vscode插件 搜索volar,安装前面两个 如果安装了vue2的插件vetur,要禁用掉,否则插件会冲突...
c++视觉图像----扩充边界
图像扩充边界 #include <opencv2/opencv.hpp> #include <opencv2/highgui/highgui.hpp>int main() {// 读取图像cv::Mat image cv::imread("1.jpg", cv::IMREAD_COLOR);if (image.empty()) {std::cerr << "Could not open or find the imag…...
邮政编码,格式校验:@ZipCode(自定义注解)
目标 自定义一个用于校验邮政编码格式的注解ZipCode,能够和现有的 Validation 兼容,使用方式和其他校验注解保持一致(使用 Valid 注解接口参数)。 校验逻辑 有效格式 不能包含空格;应为6位数字; 不校验…...
Appium自动化测试框架:关键字驱动+数据驱动
1. 关键字驱动框架简介 原理及特点 关键字驱动测试是数据驱动测试的一种改进类型,它也被称为表格驱动测试或者基于动作字的测试。主要关键字包括三类:被操作对象(Item)、操作行为(Operation)和操作值&…...
简单多状态dp【动态规划】
目录 一、按摩师 二、打家劫舍 三、删除并获得点数 四、粉刷房子 五、买卖股票的最佳时机 六、买卖股票的最佳时机(含手续费) 七、买卖股票的最佳时机III 八、买卖股票的最佳时机IV 一、按摩师 class Solution { public:int massage(vector<int>…...
OpenCV中initUndistortRectifyMap ()函数与十四讲中去畸变公式的区别探究
文章目录 1.十四讲中的去畸变公式2. OpenCV中的去畸变公式3. 4个参数和8个参数之间的区别4.initUndistortRectifyMap()函数源码 最近在使用OpenCV对鱼眼相机图像去畸变时发现一个问题,基于针孔模型去畸变时所使用的参数和之前十四讲以及视觉SLAM中的畸变系数有一点不…...
【C++】C++11——智能指针、内存泄漏、智能指针的使用和原理、RAII、auto_ptr、unique_ptr、shared_ptr、weak_ptr
文章目录 C117.智能指针7.1内存泄漏7.2智能指针的概念7.3智能指针的使用7.3.1 auto_ptr7.3.2 unique_ptr7.3.3 shared_ptr7.3.4 weak_ptr C11 7.智能指针 7.1内存泄漏 什么是内存泄漏: 内存泄漏指因为疏忽或错误造成程序未能释放已经不再使用的内存的情况。内存泄漏…...
EDUSRC-记某擎未授权与sql注入
目录 360天擎 - 未授权与sql注入 信息收集 FOFA语法 鹰图搜索 360天擎未授权访问 - 数据库信息泄露 漏洞复现 修复方案 360天擎终端安全管理系统ccid处SQL注入 漏洞复现 手动测试方法 修复方案 360天擎 - 未授权与sql注入 通常访问的页面如下,存在登录框…...
1688拍立淘API接口分享
拍立淘接口,顾名思义,就是通过图片搜索到相关商品列表。通过此接口,可以实现图片搜索爆款商品等功能。 接口地址:1688.item_search_img 公共参数 名称类型必须描述keyString是调用key(必须以GET方式拼接在URL中&…...
昇腾910使用记录
一. 压缩文件和解压文件 1. 压缩文件 tar -czvf UNITE-main.tar.gz ./UNITE-main/2. 解压文件 tar -xvf ./UNITE-main/二. CUDA更改为NPU data[label] data[label].cuda() data[instance] data[instance].cuda() data[image] data[image].cuda()更改为 data[label] da…...
从一部iPhone手机看芯片的分类
目录 问题 iPhone X 手机处理器:A11 iPhone X 的两大存储芯片 数字 IC CPU:计算设备的运算核心和控制核心 GPU:图形处理器 ASIC:为解决特定应用问题而定制设计的集成电路 存储芯片:DRAM 和 NAND Flash iPhone…...
arm day 7
完成字符串收发函数的封装并且验证现象,一个字符串发送接受后会有‘\n’ \r src/uart.c #include"uart.h"void uart4_init() {//设置UART4的RCc时钟使能//RCC_MP_APB1ENSETR[16]->1RCC->MP_APB1ENSETR | (0x1<<16);//设置GPIOB和GPIOG的时钟…...
Java基础面试-面向对象
什么是面向对象? 对比面向过程,是两种不同的处理问题角度 面向过程更注重事情的每一个步骤及顺序,面向对象更注重事情有哪些参与者(对象),及各自需要做什么 比如洗衣机洗衣服 面向过程会将任务拆解成一系…...
GCC vs. G++:C 与 C++ 编译器的差异和比较
本文将介绍 GCC(GNU Compiler Collection)和 G 编译器的区别,并对它们在 C 和 C 程序开发中的特性和用法进行比较和总结。 引言 在 C 和 C 程序开发中,选择合适的编译器是至关重要的。GCC(GNU Compiler Collection&a…...
MAC m系列docker login报错
错误:ERROR: failed to solve: XXX error getting credentials - err: exit status 1, out: 解决: vi ~/.docker/config.jsonzsxzsx [15时55分55秒] [~] { {"auths": {"harbor-g42c.corp.matrx.team": {"auth": "…...
Redis通用指令和五大基本数据类型常用指令总结
通用指令 keys parttern 查询key (parttern即通配符,不是正则表达式,例如 keys a? 匹配以a开头的长度为2的key) del key 删除key exists key 获取key是否存在 type key 获取key的类型 expire key seconds 为指定key设置有效期,单位秒 …...
uCharts常用图表组件demo
带渐变阴影的曲线图 <view class"charts-box"><qiun-data-charts type"area" :opts"opts" :chartData"chartData" :ontouch"true":background"rgba(256,256,256,0)" /> </view>data(){return{…...
VNC:Timed out waiting for a response from the computer
VNC的服务端使用的是TigerVNC,客户端使用的是RealVNC TigerVNC按其他博客配好后,防火墙ip什么的都配了,vnc客户端怎么连都是超时。 这里建议大家可以尝试一下重启服务器。我的是CentOS的 shutdown -r now 配了2天,最后服务器重启…...
Kotlin 协程 知识点
Android 上的 Kotlin 协程 | Android Developers (google.cn) 官方网址 1.什么是协程? 我觉得协程就是kotlin中一种优雅的实现异步请求 协程(Coroutines)是一种轻量级的并发编程概念,旨在简化异步编程和并发任务的处理。它是…...
装饰模式(Decorator Pattern)重构java邮件发奖系统实战
前言 现在我们有个如下的需求,设计一个邮件发奖的小系统, 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其…...
大话软工笔记—需求分析概述
需求分析,就是要对需求调研收集到的资料信息逐个地进行拆分、研究,从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要,后续设计的依据主要来自于需求分析的成果,包括: 项目的目的…...
《通信之道——从微积分到 5G》读书总结
第1章 绪 论 1.1 这是一本什么样的书 通信技术,说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号(调制) 把信息从信号中抽取出来&am…...
c#开发AI模型对话
AI模型 前面已经介绍了一般AI模型本地部署,直接调用现成的模型数据。这里主要讲述讲接口集成到我们自己的程序中使用方式。 微软提供了ML.NET来开发和使用AI模型,但是目前国内可能使用不多,至少实践例子很少看见。开发训练模型就不介绍了&am…...
OpenLayers 分屏对比(地图联动)
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能,和卷帘图层不一样的是,分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...
ArcGIS Pro制作水平横向图例+多级标注
今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作:ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等(ArcGIS出图图例8大技巧),那这次我们看看ArcGIS Pro如何更加快捷的操作。…...
云原生安全实战:API网关Kong的鉴权与限流详解
🔥「炎码工坊」技术弹药已装填! 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、基础概念 1. API网关(API Gateway) API网关是微服务架构中的核心组件,负责统一管理所有API的流量入口。它像一座…...
android13 app的触摸问题定位分析流程
一、知识点 一般来说,触摸问题都是app层面出问题,我们可以在ViewRootImpl.java添加log的方式定位;如果是touchableRegion的计算问题,就会相对比较麻烦了,需要通过adb shell dumpsys input > input.log指令,且通过打印堆栈的方式,逐步定位问题,并找到修改方案。 问题…...
Visual Studio Code 扩展
Visual Studio Code 扩展 change-case 大小写转换EmmyLua for VSCode 调试插件Bookmarks 书签 change-case 大小写转换 https://marketplace.visualstudio.com/items?itemNamewmaurer.change-case 选中单词后,命令 changeCase.commands 可预览转换效果 EmmyLua…...
【51单片机】4. 模块化编程与LCD1602Debug
1. 什么是模块化编程 传统编程会将所有函数放在main.c中,如果使用的模块多,一个文件内会有很多代码,不利于组织和管理 模块化编程则是将各个模块的代码放在不同的.c文件里,在.h文件里提供外部可调用函数声明,其他.c文…...
