接上次分析到初始化ZRender的源码,这次关注绘图模块Painter的初始化

入口1:new Painter(dom, this.storage);

// zrender.js
/**
* 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();
}

初始化Painter时,传入绘图区域dom、内容仓库实例storage。并立即备份。

// Painter.js
/**
* 绘图类 (V)
*
* @param {HTMLElement} root 绘图区域
* @param {storage} storage Storage实例
*/
function Painter(root, storage) {
this.root = root;
this.storage = storage;
//......
}

这时的storage还是全空的。

还是好习惯,绘图前清空画布

// Painter.js  Painter
root.innerHTML = '';
this._width = this._getWidth(); // 宽,缓存记录
this._height = this._getHeight(); // 高,缓存记录

解决获取宽、高的浏览器兼容问题:

Painter.prototype._getHeight = function () {
var root = this.root;
var stl = root.currentStyle
|| document.defaultView.getComputedStyle(root);
return ((root.clientHeight || parseInt(stl.height, 10))
- parseInt(stl.paddingTop, 10) // 请原谅我这比较粗暴
- parseInt(stl.paddingBottom, 10)).toFixed(0) - 0;
};

新建DIV,设置默认属性并拼接

 var domRoot = document.createElement('div');
this._domRoot = domRoot;
domRoot.style.position = 'relative';
domRoot.style.overflow = 'hidden';
domRoot.style.width = this._width + 'px';
domRoot.style.height = this._height + 'px';
root.appendChild(domRoot);

这时看dom。容器中,已经添加了包裹的div:

然后开始初始化缓存dom、画布的容器:

 this._domList = {};       //canvas dom元素,都缓存到这里
this._ctxList = {}; //canvas 2D context对象,与domList对应
this._domListBack = {};
this._ctxListBack = {}; this._zLevelConfig = {}; // 每个zLevel 的配置,@config clearColor

通过storage获取最大的zlevel

 this._maxZlevel = storage.getMaxZlevel(); //最大zlevel,缓存记录

初始化图形加载效果,这边是全空的(参数是空的,方法也是空的),没什么好看

this._loadingEffect = new BaseLoadingEffect({});
 // loadingEffect/Base.js
/**
* @constructor
*
* @param {Object} options 选项
* @param {color} options.backgroundColor 背景颜色
* @param {Object} options.textStyle 文字样式,同shape/text.style
* @param {number=} options.progress 进度参数,部分特效有用
* @param {Object=} options.effect 特效参数,部分特效有用
*
* textStyle:{
* textFont: 'normal 20px Arial' || {textFont}, //文本字体
* color: {color}
* }
* }
*/
function Base(options) {
this.setOptions(options);
}
Base.prototype.setOptions = function (options) {
this.options = options || {};
};

图形另存为图片方法。很高端的样子,晚点再看吧

this.shapeToImage = this._createShapeToImageProcessor();
Painter.prototype._createShapeToImageProcessor = function () {
if (vmlCanvasManager) {
return doNothing;
}
var painter = this;
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
var devicePixelRatio = window.devicePixelRatio || 1; return function (id, e, width, height) {
return painter._shapeToImage(
id, e, width, height,
canvas, ctx, devicePixelRatio
);
};
};

准备工作做完了,开始创建各层canvas

首先创建背景

this._domList.bg = createDom('bg', 'div', this);
domRoot.appendChild(this._domList.bg);

先看下html dom中的情况吧,背景图层已经添加上去了:

再看看创建dom元素的createDom方法吧,高宽取决于父容器

/**
* 创建dom
*
* @inner
* @param {string} id dom id 待用
* @param {string} type dom type,such as canvas, div etc.
* @param {Painter} painter painter instance
*/
function createDom(id, type, painter) {
var newDom = document.createElement(type);
var width = painter._width;
var height = painter._height;
// 没append呢,请原谅我这样写,清晰~
newDom.style.position = 'absolute';
newDom.style.left = 0;
newDom.style.top = 0;
newDom.style.width = width + 'px';
newDom.style.height = height + 'px';
newDom.setAttribute('width', width * devicePixelRatio);
newDom.setAttribute('height', height * devicePixelRatio);
// id不作为索引用,避免可能造成的重名,定义为私有属性
newDom.setAttribute('data-zr-dom-id', id);
return newDom;
}

循环创建各层canvas,vmlCanvasManager是啥,得晚点细究,应该是IE下用的,这边一直为false。

这边_maxZlevel为0,只需要添加zlevel: 0画布就行(同时进行了缓存)。

var canvasElem;
var canvasCtx;
// 实体
for (var i = 0; i <= this._maxZlevel; i++) {
canvasElem = createDom(i, 'canvas', this);
domRoot.appendChild(canvasElem);
this._domList[i] = canvasElem;
vmlCanvasManager && vmlCanvasManager.initElement(canvasElem);
this._ctxList[i] = canvasCtx = canvasElem.getContext('2d');
if (devicePixelRatio != 1) {
canvasCtx.scale(devicePixelRatio, devicePixelRatio);
}
}

创建用于高亮的canvas,照样缓存。

canvasElem = createDom('hover', 'canvas', this);
canvasElem.id = '_zrender_hover_';
domRoot.appendChild(canvasElem);
this._domList.hover = canvasElem;
vmlCanvasManager && vmlCanvasManager.initElement(canvasElem);
this._domList.hover.onselectstart = returnFalse;
this._ctxList.hover = canvasCtx = canvasElem.getContext('2d');
if (devicePixelRatio != 1) {
canvasCtx.scale(devicePixelRatio, devicePixelRatio);
}

照例先看html dom吧:

我们来看看创建好的Painter实例

未完,待续:

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

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

  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源码分析2:Storage(Model层)

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

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. Web api help page error CS0012: Type "System.Collections.Generic.Dictionary'2错误

    1.在asp.net Boilerplate项目中,Abp.0.12.0.2,.net framework4.5.2.下载后添加了webApi的helpPage功能,调试出现错误. dubug : a ...

  2. 给深度学习入门者的Python快速教程

    给深度学习入门者的Python快速教程 基础篇 numpy和Matplotlib篇 本篇部分代码的下载地址: https://github.com/frombeijingwithlove/dlcv_f ...

  3. 关于Python安装官方whl包和tar.gz包的方法详解

    Windows环境: 安装whl包:pip install wheel -> pip install **.whl 安装tar.gz包:cd到解压后路径,python setup.py inst ...

  4. CentOS7.6安装Maven

    官网下载地址:http://maven.apache.org/download.cgi 第一步:软件下载安装 进行安装目录:cd /opt/software (如果目录不存在,请先创建目录) 下载二进 ...

  5. Mysql进行复杂查询

    1.查询“生物”课程比“物理”课程成绩高的所有学生的学号: 思路: (1)获取所有选了 生物 课程的学生的成绩(学号,成绩) --临时表     (2)获取所有选了 物理 课程的学生的成绩(学号,成绩 ...

  6. new及placememt new 异同点

    new与定位new 区别如下: 简单概括: new 分配的内存地址空间来自于heap堆,用完需使用delete 释放内存 定位new 使用的不是heap堆内存,因此不需要使用delete 释放 定位n ...

  7. 3.Redis 数据类型

    转自:http://www.runoob.com/redis/redis-tutorial.html Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集 ...

  8. 禁止xfce4黑屏

    我在ubuntu server上安装了xfce,可是每隔十分钟电脑就会黑屏.安装了xfce自带的电源管理程序.貌似不起作用.后来从网上找到如下方法: 修改/etc/X11/xorg.conf配置文件, ...

  9. sha1sum校验下载的文件

    [root@mhc1 test]# sha1sum Percona-XtraBackup-2.4.8-r97330f7-jessie-x86_64-bundle.tara9c6b1c7cb3bf98b ...

  10. Android和Unity混合开发——解决方案

    按这篇文章来做 http://blog.csdn.net/a369414641/article/details/53436477 要注意的地方 1.app是Android Libray,否则无法打包出 ...