乐趣区

Echarts中如何分辨datazoom回调来自拖拽还是滚轮

需求

使用 echarts 绘制一周每小时数据的曲线,并要求可以滚轮缩放,未放大时横坐标仅显示日(每隔一天显示),放大到一定程度要显示完整日期,也就是 yyyy-mm-dd hh-mm-ss 这个格式。

效果

曲线未放大时?

曲线放大到某个程度时?

解决

这个需求的坑在哪里呢,本来是从始至终只显示日,但是 echarts 在放大到某个程度时横坐标和数据对不上了,去掉 formatter 查看发现,本来是规律的 2020-05-27 00:00:00,2020-05-28 00:00:00(formatter 之后就是 27,28,对应零点的数据……)……但是放大之后 echarts 自动给我改成了 2020-05-27 00:04:00,2020-05-28 00:06:00(formatter 之后仍然是 27,28……但是对应不上零点数据了)……总而言之,言而总之,如果 formatter 的话,自然是看不到时分秒的变化的,所以也就发生了数据对不上的情况。

解决提出问题的人后,需求妥协成了放大后显示完整时间,但是当上手时,才发现没这么容易,问题出在 datazoom 的监听上,正常来说,echarts 监听 datazoom 是这样的:

this['echart' + this.id].on('datazoom', function (params) {// ……});

但是虽然 echarts 给了 datazoom 的 params,但是没有提供缩放系数(?)这我不是很懂,仔细寻找一番,发现真的没有给系数,查询了一下别人是怎么解决的,但是并没有找到。

经过一番痛苦的思考,于是准备通过缩放的 end-start 来判断:

let start = params.batch[0].start;
    let end = params.batch[0].end;
    let diff = end - start;
    // diff 小于 50,算作‘缩放到一定程度’if(diff < 50) {let option = $this['echart' + $this.id].getOption();
        delete option.xAxis[0].axisLabel.formatter;
        $this['echart' + $this.id].clear();
        $this['echart' + $this.id].setOption(option, true);
    }
    if(diff >= 50) {let option = $this['echart' + $this.id].getOption();
        option.xAxis[0].axisLabel.formatter = function (value, index) {let str = (value.split(' '))[0];
            str = (str.split('-'))[2];
            return str;
        };
        $this['echart' + $this.id].clear();
        $this['echart' + $this.id].setOption(option, true);
    }

本以为这样就解决了,谁能想到,放上去之后,曲线放大后不能拖动了???

经过一番痛苦的思考和测试,发现了 echarts 一个让人很看不懂的设计(这就去提 issue!)拖拽曲线也会触发 datazoom 回调!不知道一开始这样设计的初衷是什么,只知道因为它我又掉了很多头发……拖拽曲线也触发了回调,导致不停地 setOption,自然也就没空处理拖动了。

最后的解决方案

没办法,又掉了一把头发之后,终于发现拖拽和放大的 params 的区别:start 和 end 的改变区间很小,基本能维持在 0 - 1 之间,也就是说,只要记录上次的 diff,与这次的 diff,再计算差值的绝对值,如果 >1,就可以算作是缩放触发,上代码:

let lastdiff = 0;
this['echart' + this.id].on('datazoom', function (params) {let start = params.batch[0].start;
    let end = params.batch[0].end;
    let diff = end - start;
    // mircodiff > 1,说明是放大而不是拖拽
    let mircodiff = Math.abs(diff - lastdiff);
    if(diff < 50 && mircodiff > 1) {// 放大之后的操作}
    if(diff >= 50 && mircodiff > 1) {// 缩小回去的操作}
    lastdiff = diff;
});

总结

echarts 坑还是很多的,网上又找不到答案,希望有和我类似问题的同学看到这篇文章能够快速解决这个问题,继续开发下一个需求,而不是经过漫长的查询而一无所获 ^ ^。

退出移动版