echarts遇到resize失效问题

1、问题描述

在前端页面中,echarts图形在容器div发生变化时,能够自适应调整大小。注意这里说的是容器div发生变化时,不是浏览器窗口发生变化的时候。实际场景是,在点击菜单的按钮,导致了echarts容器div发生了变化,但echarts没有resize(),导致很丑。

2、解决过程

2.1 项目的现状

在窗口发生变化的时候,触发了resize事件,echarts容器发生变化,调用echarts的resize函数,做了自适应调整。代码实现如下:

            myChart.setOption(option);
            window.addEventListener("resize", function () {
         		 myChart.resize();
        		});

2.2 div自适应解决方案

解决思路:

  1. 侦听div的变化,触发resize
  2. 由于按钮触发echarts的容器div的变化,按钮绑定触发事件

2.2.1 div的变化,触发resize

实现一

	(function ($, window, undefined) {
	    var elems = $([]),//空的数组
	        jq_resize = $.resize = $.extend($.resize, {}),
	        timeout_id,
	        str_setTimeout = 'setTimeout',
	        str_resize = 'resize',
	        str_data = str_resize + '-special-event',
	        str_delay = 'delay',
	        str_throttle = 'throttleWindow';
	    jq_resize[str_delay] = 250;
	    jq_resize[str_throttle] = true;
	    $.event.special[str_resize] = {
	        setup: function () {
	            if (!jq_resize[str_throttle] && this[str_setTimeout]) {
	                return false;
	            }
	            var elem = $(this);
	            elems = elems.add(elem);
	            $.data(this, str_data, {
	                w: elem.width(),
	                h: elem.height()
	            });
	            if (elems.length === 1) {
	                loopy();
	            }
	        },
	        teardown: function () {
	            if (!jq_resize[str_throttle] && this[str_setTimeout]) {
	                return false;
	            }
	            var elem = $(this);
	            elems = elems.not(elem);
	            elem.removeData(str_data);
	            if (!elems.length) {
	                clearTimeout(timeout_id);
	            }
	        },
	        add: function (handleObj) {
	            if (!jq_resize[str_throttle] && this[str_setTimeout]) {
	                return false;
	            }
	            var old_handler;
	 
	            function new_handler(e, w, h) {
	                var elem = $(this),
	                    data = $.data(this, str_data);
	                data.w = w !== undefined ? w : elem.width();
	                data.h = h !== undefined ? h : elem.height();
	                old_handler.apply(this, arguments);
	            }
	 
	            if ($.isFunction(handleObj)) {
	                old_handler = handleObj;
	                return new_handler;
	            } else {
	                old_handler = handleObj.handler;
	                handleObj.handler = new_handler;
	            }
	        }
	    };
	 
	    function loopy() {
	        timeout_id = window[str_setTimeout](function () {
	            elems.each(function () {
	                var elem = $(this),
	                    width = elem.width(),
	                    height = elem.height(),
	                    data = $.data(this, str_data);
	                if (width !== data.w || height !== data.h) {
	                    elem.trigger(str_resize, [data.w = width, data.h = height]);
						//错误代码(直接在这边)  《《《《《《《《《《《《《《代码1》》》》》》》》》》》》》》
	                }
	            });
	            loopy();
	        }, jq_resize[str_delay]);
	    }
	})(jQuery, this);
	//监听div大小变化事件
	$("div").resize(function(){
	    console.log("触发了....");
	})
	

这么一大段代码,看着有点稀里糊涂的,看着网上的文章,说侦听div的变化,当div的变化,触发resize事件。在本地实验可以,的确可以侦听到。如果直接在《代码1》写触发代码,会一直循环,还无法侦听指定div的变化。对jquery的事件绑定,这部分知识欠缺,读这段代码,有点吃力。

实现二(未验证):

2.2.2 触发事件

触发事件,思路比较简单,实现也比较容易,但是容易掉坑里面。

2.2.2.1 探索过程

对定的元素绑定点击事件,触发resise事件,代码如下:

	//b被点击的按钮
	var btn1=$("#hide-menu");
	btn1.on("click",function(){
		var event= new Event("resize");
		window.dispatchEvent(event);
	})

	//echarts的容器
	window.addEventListener("resize",function(){
		mychart.resize();
	})

这个过程简单吧,只是一个触发事件过程和一个监听事件过程。正常场景下,应该可以完美的解决这个问题。但是在项目框架中,就卡住了,虽然运行了,没有达到预期的效果,一度让我有点奔溃了。然后就陷入了一个怪坑,echarts的resize失效。网上找各种这个问题的解决方案,然并卵毫无作用。

说法一:“宽度100%,高度vh,就可以解决了”ECharts的resize失效原因以及使用方法

说法二:“$(“#vid”).css("height",$(vid).height);宽度一样”

扫描二维码关注公众号,回复: 11243817 查看本文章

说法三:“特定版本的问题”

说法四:“样式的影响”

......

2.2.2.2 分析过程
  1. 剥离框架,写一个小程序,验证方法的可行性(实际可行)
  2. 添加样式,依旧可行
  3. 添加打印,对比resize起作用前后的变化。
    1. div容器的宽和高
    2. mycharts的宽和高(echarts对象的方法获取)
    3. 在resize1起作用前,上面两者是不一致的
  4. 回到框架代码,发现触发事件的时候,一直处于一致状态。
    1. 通过我的好眼力,发现resize事件处理领先于div的宽高调整
  5. 进一步发下,这个按钮绑定了其他事件,导致了先resize,然后再调整宽和高。
  6. 在之前绑定的事件的回调函数中,触发新的事件,保证先后顺序。
2.2.2.3 代码实现过程

1、正确的实现的姿势

	var btn1=$("#hide-menu");
	btn1.on("click",function(){
	   //省略
        $navtab
        .stop()
        .animate(opts, 'fast',function(){
        	     var myEvent = new Event("echartDivChange");
					 window.dispatchEvent(myEvent);
        })
	})
	//echarts的容器
	window.addEventListener("echartDivChange",function(){
		mychart.resize();
	})

2、trigger 触发事件,又掉入另外一个坑里面(错误示范)

	var btn1=$("#hide-menu");
	btn1.on("click",function(){
		//........
        $navtab
        .stop()
        .animate(opts, 'fast',function(){        	  
				 $(window).trigger("echartDivChange");//方式1	
 				//$(document).trigger("echartDivChange");//方式2
				//$("#123").trigger("echartDivChange");//方式3
        })
	})
	//echarts的容器(错误示范)
	$("#mycharts").on("echartDivChange",function(){
		mychart.resize();
	})

看框架源码,有的事件是交叉触发和捕获,这种方式应该是错误的。在这种方式中无法捕获,一定要选择对应方式。 例如,$(window)需要用 $(window)去捕获。这里面还有知识点,事件的冒泡机制,理解这个,对事件触发和捕获才能合理利用。

3、知识点提炼

  • resize事件
  • on
  • 自定义event触发和捕获
  • 冒泡机制
  • $.event.special(待学习)

4、总结

在定位这个问题过程中,还是花了很长时间的。在定位过程,掉进坑里面,无法爬出来。原因分为两个方面,一:知识体系不够完善;二:遇到坑的分析解决的方式有问题。

4.1 知识体系不够完善

只能带着积累,学习新的东西。

4.2 遇到问题解决方式

  1. 怀疑开源组件的问题

这个可以将开源组件剥离当前框架,写个小程序直接验证。直接来个demo,这个有时候还是不习惯,或者有点反应慢。

  1. 遇到问题的搜寻顺序
  • 搜索,要是有明确的答案直接用
  • 官方论坛
  • 再搜索
  1. 控制变量法

不确定问题原因的可以验证单个因素的正确性,然后再组合验证。发现是不是组合了才导致问题发生了。

猜你喜欢

转载自www.cnblogs.com/meiguhuaxian/p/12935394.html