zoukankan      html  css  js  c++  java
  • zrender源码分析4--初始化Painter绘图模块2

    入口2: 渲染

    // zrender_demo.html
    zr.render();
    
    // zrender.js
    /**
     * 渲染
     * 
     * @param {Function} callback  渲染结束后回调函数
     * todo:增加缓动函数
     */
    ZRender.prototype.render = function (callback) {
    	this.painter.render(callback);
    	return this;
    };

    然后我们看看Painter是如何渲染的。(这边的回调是undefined)

    1. 先关闭正在显示的数据加载提示

    // Painter.js
    /**
     * 首次绘图,创建各种dom和context
     * 
     * @param {Function=} callback 绘画结束后的回调函数
     */
    Painter.prototype.render = function (callback) {
    	if (this.isLoading()) {
    		this.hideLoading();
    	}
    
    	//......
    	return this;
    };

    2. 检查_maxZlevel是否变大,如是则同步创建需要的Canvas。这次并不需要更新。

    this._syncMaxZlevelCanvase();
    /**
     * 检查_maxZlevel是否变大,如是则同步创建需要的Canvas
     * 
     * @private
     */
    Painter.prototype._syncMaxZlevelCanvase = function () {
    	var curMaxZlevel = this.storage.getMaxZlevel();
    	if (this._maxZlevel < curMaxZlevel) {
    		//实体
    		for (var i = this._maxZlevel + 1; i <= curMaxZlevel; i++) {
    			var canvasElem = createDom(i, 'canvas', this);
    			this._domList[i] = canvasElem;
    			this._domRoot.insertBefore(canvasElem, this._domList.hover);
    			if (vmlCanvasManager) {
    				vmlCanvasManager.initElement(canvasElem);
    			}
    
    			var canvasCtx = canvasElem.getContext('2d');
    			this._ctxList[i] = canvasCtx;
    			if (devicePixelRatio != 1) { 
    				canvasCtx.scale(devicePixelRatio, devicePixelRatio);
    			}
    		}
    		this._maxZlevel = curMaxZlevel;
    	}
    };

    3. 依然是好习惯,先清空已有内容。这边的clearLayer() API比较复杂,晚点再细究吧。

    //清空已有内容,render默认为首次渲染
    this.clear();
    /**
     * 清除hover层外所有内容
     */
    Painter.prototype.clear = function () {
    	for (var k in this._ctxList) {
    		if (k == 'hover') {
    			continue;
    		}
    
    		this.clearLayer(k);
    	}
    
    	return this;
    };

    this._ctxList的值如下,这边只需要清空非高亮画布

    QQ截图20140926145246

    4. 升序遍历,shape上的zlevel指定绘画图层的z轴层叠

    //升序遍历,shape上的zlevel指定绘画图层的z轴层叠
    this.storage.iterShape(
    	this._brush({ all : true }),
    	{ normal: 'up' }
    );
    /**
     * 遍历迭代器
     * 
     * @param {Function} fun 迭代回调函数,return true终止迭代
     * @param {Object=} option 迭代参数,缺省为仅降序遍历常规形状
     *     hover : true 是否迭代高亮层数据
     *     normal : 'down' | 'up' | 'free' 是否迭代常规数据,迭代时是否指定及z轴顺序
     */
    Storage.prototype.iterShape = function (fun, option) {
    	// ..... 
    	// 设置option默认值,默认降序遍历
    	if (option.hover) {
    		//高亮层数据遍历
    		for (var i = 0, l = this._hoverElements.length; i < l; i++) {
    			if (fun(this._hoverElements[i])) {
    				return this;
    			}
    		}
    	}
    
    	var zlist;
    	var len;
    	if (typeof option.normal != 'undefined') {
    		//z轴遍历: 'down' | 'up' | 'free'
    		switch (option.normal) {
    			case 'down':
    				// 降序遍历,高层优先
    				//......
    				break;
    			case 'up':
    				//升序遍历,底层优先
    				for (var i = 0, l = this._zElements.length; i < l; i++) {
    					zlist = this._zElements[i];
    					if (zlist) {
    						len = zlist.length;
    						for (var k = 0; k < len; k++) {
    							if (fun(zlist[k])) {
    								return this;
    							}
    						}
    					}
    				}
    				break;
    			// case 'free':
    			default:
    				//无序遍历
    				for (var i in this._elements) {
    					if (fun(this._elements[i])) {
    						return this;
    					}
    				}
    				break;
    		}
    	}
    
    	return this;
    };  

    还记得之前初始化Painter时提到的_zElements不,当时说的就是根据zlevel来组织画布,这边就用到了。状态如下:

    QQ截图20140926150044

    遍历中,会对circle进行刷画图像

    QQ截图20140926150510

    function(shape) {
    	if ((changedZlevel.all || changedZlevel[shape.zlevel])
    		&& !shape.invisible
    	) {
    		var ctx = ctxList[shape.zlevel];
    		if (ctx) {
    			if (!shape.onbrush //没有onbrush
    				//有onbrush并且调用执行返回false或undefined则继续粉刷
    				|| (shape.onbrush && !shape.onbrush(ctx, false))
    			) {
    				if (config.catchBrushException) {
    					try {
    						shape.brush(ctx, false, updatePainter);
    					}
    					catch(error) {
    						log(
    							error,
    							'brush error of ' + shape.type,
    							shape
    						);
    					}
    				}
    				else {
    					shape.brush(ctx, false, updatePainter);
    				}
    			}
    		}
    		else {
    			log(
    				'can not find the specific zlevel canvas!'
    			);
    		}
    	}
    };   

    其中shape.brush()暂时不细究。等下一轮吧。

    5. update到最新则清空标志位。Storage中只是清空了_changedZlevel。

    // update到最新则清空标志位
    this.storage.clearChangedZlevel();
    // Storage.js
    Storage.prototype.clearChangedZlevel = function () {
    	this._changedZlevel = {};
    	return this;
    };

    6. callback为undefined,所以下面的不执行。

    /**
     * 首次绘图,创建各种dom和context
     * 
     * @param {Function=} callback 绘画结束后的回调函数
     */
    Painter.prototype.render = function (callback) {
    	// .......
    	// 这部分代码刚才都分析过
    	
    	if (typeof callback == 'function') {
    		callback();
    	}
    
    	return this;
    };

    Painter的初步分析到此为止。接下来分析先Handler,再细究Painter中跳过的部分。

  • 相关阅读:
    关于格林尼治时间(GMT)和DateTime相互转换的分享
    Mybatis多表操作
    Mybatis动态SQL
    Mybatis连接池及事务
    Mybatis基本使用
    Mybatis基本入门搭建
    面试刷题29:mysql事务隔离实现原理?
    面试刷题28:如何写出安全的java代码?
    面试刷题27:程序员如何防护java界的新冠肺炎?
    面试刷题26:新冠攻击人类?什么攻击java平台?
  • 原文地址:https://www.cnblogs.com/leftthen/p/3994971.html
Copyright © 2011-2022 走看看