入口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的值如下,这边只需要清空非高亮画布

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来组织画布,这边就用到了。状态如下:

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

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中跳过的部分。

zrender源码分析4--初始化Painter绘图模块2的更多相关文章

  1. ZRender源码分析5:Shape绘图详解

    回顾 上一篇说到:ZRender源码分析4:Painter(View层)-中,这次,来补充一下具体的shape 关于热区的边框 以圆形为例: document.addEventListener('DO ...

  2. ZRender源码分析4:Painter(View层)-中

    回顾 上一篇说到:ZRender源码分析3:Painter(View层)-上,接上篇,开始Shape对象 总体理解 先回到上次的Painter的render方法 /** * 首次绘图,创建各种dom和 ...

  3. ZRender源码分析3:Painter(View层)-上

    回顾 上一篇说到:ZRender源码分析2:Storage(Model层),这次咱看来看看Painter-View层 总体理解 Painter这个类主要负责MVC中的V(View)层,负责将Stora ...

  4. zrender源码分析3--初始化Painter绘图模块

    接上次分析到初始化ZRender的源码,这次关注绘图模块Painter的初始化 入口1:new Painter(dom, this.storage); // zrender.js /** * ZRen ...

  5. ZRender源码分析2:Storage(Model层)

    回顾 上一篇请移步:zrender源码分析1:总体结构 本篇进行ZRender的MVC结构中的M进行分析 总体理解 上篇说到,Storage负责MVC层中的Model,也就是模型,对于zrender来 ...

  6. SpringMVC源码分析--容器初始化(五)DispatcherServlet

    上一篇博客SpringMVC源码分析--容器初始化(四)FrameworkServlet我们已经了解到了SpringMVC容器的初始化,SpringMVC对容器初始化后会进行一系列的其他属性的初始化操 ...

  7. SpringMVC源码分析--容器初始化(四)FrameworkServlet

    在上一篇博客SpringMVC源码分析--容器初始化(三)HttpServletBean我们介绍了HttpServletBean的init函数,其主要作用是初始化了一下SpringMVC配置文件的地址 ...

  8. SpringMVC源码分析--容器初始化(三)HttpServletBean

    在上一篇博客springMVC源码分析--容器初始化(二)DispatcherServlet中,我们队SpringMVC整体生命周期有一个简单的说明,并没有进行详细的源码分析,接下来我们会根据博客中提 ...

  9. springMVC源码分析--容器初始化(二)DispatcherServlet

    在上一篇博客springMVC源码分析--容器初始化(一)中我们介绍了spring web初始化IOC容器的过程,springMVC作为spring项目中的子项目,其可以和spring web容器很好 ...

  10. k8s client-go源码分析 informer源码分析(2)-初始化与启动分析

    k8s client-go源码分析 informer源码分析(2)-初始化与启动分析 前面一篇文章对k8s informer做了概要分析,本篇文章将对informer的初始化与启动进行分析. info ...

随机推荐

  1. python学习 (三十一) python中的class

    1 python的类:   Python类都继承自object. __init__: 构造函数,如果不写,有一个默认的. __init__: 这个构造函数只能有一个,Python中不能有多个构造函数. ...

  2. 使用wifi网卡笔记5---AP模式

    使用WIFI网卡的AP功能 1.下载源码 hostapd: http://w1.fi/hostapd/ 2.编译.安装(hostapd依赖于libnl库,需要编译.安装此库) tar xzf host ...

  3. scp 远程复制

    1. 上传本地文件到远程机器指定目录 命令: scp /opt/soft/nginx-0.5.38.tar.gz root@192.168.120.204:/opt/soft/scptest 上传本地 ...

  4. A start job is running for /etc/rc.d/rc.local ... ... no limit

    /etc/rc.d/rc.local文件中配置了redis随机启动但是没有设置redis启动为守护进程(daemonize yes)导致redis启动后阻塞

  5. 0CTF题中的神奇宝贝WP

    前言: 今天被尘少拉去做题 然后做到一个脑洞打开的题..... 神奇宝贝!?!? 正文: 一开始来到这=-= 弱密码猜测:admin admin 验证码用calc去算 然后成功进入 第一次去做神奇宝贝 ...

  6. Latex编译后Yap查看报错Not all fonts could be loaded

    在用Latex写中文大论文时,编译后,用Yap查看DVI文件,打开时,Yap报错: "Not all fonts could be loaded. See 'File->Documen ...

  7. WampServer之php、mysql环境安装

    WampServer之php.mysql环境安装 WampServer介绍: WampServer是一款由法国人开发的Apache Web服务器.PHP解释器以及MySQL数据库的整合软件包.免去了开 ...

  8. python十个博客

    1.首先第一个肯定是毋庸置疑的Planet Python这是最出名的python博客其中之一,快去看看,我希望你能找到对你有用的东西,昨天它还更新了呢! 2.第二个博客是lucumr,博主是flask ...

  9. Python 小练习三 发邮件

    import smtplib,os from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipar ...

  10. ConcurrentHashMap源码分析(JDK8版本<转载>)

    注:本文源码是JDK8的版本,与之前的版本有较大差异 转载地址:http://blog.csdn.net/u010723709/article/details/48007881 ConcurrentH ...