解决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, //是否显示数据阴影 默认auto
                    showDetail: 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()
            // 获取图表的数据 URL
            var 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 = fullData
    newOption.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()
            // 获取图表的数据 URL
            var 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 = null

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, //是否显示数据阴影 默认auto
                    showDetail: 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,  // 是否初始化立即执行一次, 默认是false
        deep: true // 是否是深度监视, 默认是false
    }
)

// 下载echarts
const downloadBtn = (() => {
    // 获取完整的数据
    const fullData = myChart.getOption();
    let newOption = fullData
    newOption.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()
            // 获取图表的数据 URL
            var 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>
  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
根据引用,echarts折线图中的dataZoom是通过监听来实现的。通常的做法是使用echarts的on方法,将监听函数绑定到dataZoom事件上。在监听函数中可以编写逻辑代码来处理dataZoom的变化。 根据引用,在实现拖拽的核心部分中,使用了echarts的graphic组件来实现拖拽功能。通过设置type为circle和draggable属性为'vertical',可以让图形元素变为可拖拽的圆形。通过ondrag事件处理函数可以监听到拖拽的过程,进行相应的处理。 而根据引用,可以根据缩放的end-start值来判断dataZoom的缩放程度。如果缩放程度小于40,可以通过修改option中的axisLabel.rotate属性来调整字体的倾斜角度。当缩放程度大于等于40时,可以通过修改axisLabel.rotate属性来让字体开始倾斜。 因此,echarts折线图的dataZoom功能可以通过监听dataZoom事件来实现,同时可以根据缩放程度来调整字体的倾斜角度。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [echarts折线图监听缩放事件回调](https://blog.csdn.net/HeXinT/article/details/124857556)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] - *2* [【Echarts折线图拐点拖拽功能实现+解决datazoom设置startValue,endValue引发的拖拽点位置不对问题】](https://blog.csdn.net/qq_35703552/article/details/131916694)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值