zrender源码分析1:总体结构

开始

zrender(Zlevel Render) 是一个轻量级的Canvas类库,这里是GitHub的网址 点我, 类似的类库有Kinetic.JSEaselJS。 但貌似都没有zrender好用(可能是更加符合国人的习惯),强大的图表工具echarts就是在zrender基础上建立, 用zrender和echarts做了两个关于canvas的两个可视化项目之后,忍不住看了下zrender的项目代码(也有需要修改源代码的缘故), 但是翻开之后,代码的结构比较清晰,注释也都是中文,比较容易读懂。最大的感想就是,沒有像jQuery之类的对于代码极(bian)度(tai)的精简追求,各种意图一看便知。 如果对于zrender的api不熟悉,请移步github上,这里只对源码进行了一些详(qian)细(xian)的分析。

总体结构

关于总体结构,最贴切的描述恐怕也没这一张图来的爽:从github将项目clone下来之后,打开src/zrender.js之后,有如下发现:

 var _instances = {};    //ZRender实例map索引

var zrender = {};
zrender.version = ‘2.0.0‘;

/**
 * zrender初始化
 * 不让外部直接new ZRender实例,为啥?
 * 不为啥,提供全局可控同时减少全局污染和降低命名冲突的风险!
 *
 * @param {HTMLElement} dom dom对象,不帮你做document.getElementById了
 * @param {Object=} params 个性化参数,如自定义shape集合,带进来就好
 *
 * @return {ZRender} ZRender实例
 */
zrender.init = function(dom, params) {
    var zi = new ZRender(guid(), dom, params || {});
    _instances[zi.id] = zi;
    return zi;
}; 

我想这里已经很明显,用zrender.init(dom)初始化的时候,直接new一个内部的ZRender对象进行返回,原因我想作者已经写的很明白了(提供全局可控同时减少全局污染和降低命名冲突的风险!) 总比每次new ZRender()好多了,最起码看起来是这样,并且把每个实例就行保存,便于维护。 至于周围的其他的三个方法,dispose,getInstance,delInstance 就没什么可说的了,不过在项目中,也怎么用得上。

 /**
 * zrender实例销毁,记在_instances里的索引也会删除了
 * 管生就得管死,可以通过zrender.dispose(zi)销毁指定ZRender实例
 * 当然也可以直接zi.dispose()自己销毁
 *
 * @param {ZRender=} zi ZRender对象,不传则销毁全部
 */
zrender.dispose = function (zi) {
    if (zi) {
        zi.dispose();
    }
    else {
        for (var key in _instances) {
            _instances[key].dispose();
        }
        _instances = {};
    }

    return zrender;
};

/**
 * 获取zrender实例
 *
 * @param {string} id ZRender对象索引
 */
zrender.getInstance = function (id) {
    return _instances[id];
};

/**
 * 删除zrender实例,ZRender实例dispose时会调用,
 * 删除后getInstance则返回undefined
 * ps: 仅是删除,删除的实例不代表已经dispose了~~
 *     这是一个摆脱全局zrender.dispose()自动销毁的后门,
 *     take care of yourself~
 *
 * @param {string} id ZRender对象索引
 */
zrender.delInstance = function (id) {
    delete _instances[id];
    return zrender;
}; 

接下来就是核心的ZRender构造函数,这里可以很清晰的看到M(Storage)V(Painter)C(Handler)的结构.

 /**
 * ZRender接口类,对外可用的所有接口都在这里!!
 * storage(M)、painter(V)、handler(C)为内部私有类,外部接口不可见
 * 非get接口统一返回支持链式调用~
 *
 * @param {string} id 唯一标识
 * @param {HTMLElement} dom dom对象,不帮你做document.getElementById
 *
 * @return {ZRender} ZRender实例
 */
function ZRender(id, dom) {
    this.id = id;
    this.env = require(‘./tool/env‘);

    this.storage = new Storage();
    this.painter = new Painter(dom, this.storage);
    this.handler = new Handler(dom, this.storage, this.painter);

    // 动画控制
    this.animatingShapes = [];
    this.animation = new Animation({
        stage : {
            update : getAnimationUpdater(this)
        }
    });
    this.animation.start();
} 

  • Storage只是JS对象级别的对于Shape图形的增(add/addHover)删(del,delHover)改(mod)查(get/iterShape/getMaxZlevel等),更像一个数据结构的东西
  • Painter负责真正的绘图操作,这里是比较繁重的部分
    • 1.负责canvas及其周边DOM元素的创建与处理
    • 2.负责调用各个Shape(预定义好的)进行绘制
    • 3.提供基本的操作方法,渲染(render)、刷新(refresh)、尺寸变化(resize)、擦除(clear)等
  • Handler负责事件处理,解决基础的浏览器兼容问题、进行事件的注册与转发、拖动

至于附加在ZRender的prototype的其他方法,除了关于动画部分的,其他的都是调用的Storage、Painter、Handler,这里就不再赘述了。

结尾

能力有限,尽力而为,接下来,再详尽分析各个小模块吧。 大家也可以观摩经过我加工过的更加详细注释的代码 通往我的GitHub

时间: 2024-10-17 14:04:54

zrender源码分析1:总体结构的相关文章

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

回顾 上一篇请移步:zrender源码分析1:总体结构 本篇进行ZRender的MVC结构中的M进行分析 总体理解 上篇说到,Storage负责MVC层中的Model,也就是模型,对于zrender来说,这个model就是shape对象,在1.x表现的还不强烈,到了2.x, 在zr.addShape()的时候,传入的参数就必须是new出来的对象了详情请看这里 2.x相比1.x的变化,关于这个变化多说点吧,那就是从1.x升级到2.x的时候,因为方式变了,总不能改掉所有的代码,总不能像ext一样,

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

回顾 上一篇说到:ZRender源码分析2:Storage(Model层),这次咱看来看看Painter-View层 总体理解 Painter这个类主要负责MVC中的V(View)层,负责将Storage中的shape对象绘制到canvas中,包括了:更新.渲染.变化大小.导出.修改等操作. Painter这个类还是很明显的构造函数,然后把方法赋值到Painter.prototype上,无新奇之处,下面为示例代码.只有在Painter.js末尾有一个内部的createDom函数, 很明显,传入i

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

回顾 上一篇说到:ZRender源码分析3:Painter(View层)-上,接上篇,开始Shape对象 总体理解 先回到上次的Painter的render方法 /** * 首次绘图,创建各种dom和context * 核心方法,zr.render() --> painter.render * * render和refersh的区别:render是clear所有,refresh是清除已经改变的layer * * @param {Function=} callback 绘画结束后的回调函数 */

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

回顾 上一篇说到:ZRender源码分析4:Painter(View层)-中,这次,来补充一下具体的shape 关于热区的边框 以圆形为例: document.addEventListener('DOMContentLoaded', function () { var canvasDom = document.getElementById('canvasId'), context = canvasDom.getContext('2d'); context.lineWidth = 50; cont

jQuery源码分析-01总体架构

1. 总体架构 1.1自调用匿名函数 self-invoking anonymous function 打开jQuery源码,首先你会看到这样的代码结构: (function( window, undefined ) { // jquery code })(window); 1.这是一个自调用匿名函数.在第一个括号内,创建一个匿名函数:第二个括号,立即执行 2.为什么要创建这样一个“自调用匿名函数”呢? 通过定义一个匿名函数,创建了一个“私有”的命名空间,该命名空间的变量和方法,不会破坏全局的命

MySQL系列:innodb源码分析之page结构解析

在表空间结构分析当中,我们知道innodb的最小物理存储分配单位是page页,在MySQL-3.23版本的源码中,页只有两种页,一种是index page,一种是undo page.其类型值定义在fil0fil.h当中. FIL_PAGE_INDEX                         数据索引页,在表空间的inode page和xdes page都是属于这类. FIL_PAGE_UNDO_LOG                事务回滚日志页. 在这里我们主要分析的是 index p

nginx源码分析—内存池结构ngx_pool_t及内存管理

Content 0. 序 1. 内存池结构 1.1 ngx_pool_t结构 1.2 其他相关结构 1.3 ngx_pool_t的逻辑结构 2. 内存池操作 2.1 创建内存池 2.2 销毁内存池 2.3 重置内存池 2.4 分配内存 2.4.1 ngx_palloc()函数分析 2.4.2 ngx_palloc_block()函数分析 2.5 释放内存 2.6 注册cleanup 2.7 内存池的物理结构 3. 一个例子 3.1 代码 3.2 如何编译 3.3 运行结果 4. 小结 5. 致谢

ZRender源码分析6:Shape对象详解之路径

开始 说到这里,就不得不提SVG的路径操作了,因为ZRender完全的模拟了SVG原生的path元素的用法,很是强大. 关于SVG的Path,请看这里: Path (英文版) 或者 [MDN]SVG教程(5) 路径 [译] (中文版), 很明显的是canvas中的路径没有SVG的用着舒服,那到底ZRender是如何实现的呢,让我给你娓娓道来(不过要想继续进行下去,上面的SVG的PATH必须了解.). 示例 打开API,shape.path,可以看到,path的配置有MLHVCSQTZ等字母组成的

Android4.0 Launcher 源码分析3——WorkSpace结构

3.WorkSpace结构 桌面的左右滑动功能主要是在PagedView类中实现的,而WorkSpace是PagedView类的子类,所以会继承PagedView中的方法.当我们的手指点击WorkSpace时,首先就会触发PageView中的onInterceptTouchEvent()方法,会根据相应的条件来判断是否对Touch事件进行拦截,如果onInterceptTouchEvent()方法返回为true,则会对Touch事件进行拦截,PageView类的onTouch方法会进行响应从而得