先看下,本次例子做的效果
然后开始代码:
调用init接口初始化
// zrender_demo.html
var zr = zrender.init(document.getElementById('main'));
进入init方法,发现做2件事情:A、初始化ZRender;B、将其存入ZRender实例map索引
// zrender.js
/**
* 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 || {});// guid()生成zrender唯一id
_instances[zi.id] = zi;
return zi;
};
进入ZRender接口类,这边体现官网提到的“MVC核心封装实现图形仓库、视图渲染和交互控制”
Stroage(M) : shape数据CURD管理
Painter(V) : canvas元素生命周期管理,视图渲染,绘画,更新控制
Handler(C) : 事件交互处理,实现完整dom事件模拟封装
// 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(); //shape数据CURD管理
this.painter = new Painter(dom, this.storage); //canvase元素生命周期管理,视图渲染,绘画,更新控制
this.handler = new Handler(dom, this.storage, this.painter);//事件交互处理,实现完整dom事件模拟封装
// 动画控制
this.animatingShapes = [];
this.animation = new Animation({
stage : {
update : getAnimationUpdater(this)
}
});
this.animation.start();
}
这边Storage、Painter、Handler的初始化暂时不细究跳过
好习惯是每次绘图前,都清空画布
// zrender_demo.html
zr.clear();
zrender执行清空时,清空storage后,再执行painter的clear()方法
// zrender.js
/**
* 清除当前ZRender下所有类图的数据和显示,clear后MVC和已绑定事件均还存在在,ZRender可用
*/
ZRender.prototype.clear = function () {
this.storage.del();
this.painter.clear();
return this;
};
同样暂不细究storage、painter的清除机制
接下来开始绘图,添加一个圆形
// zrender_demo.html
var color = require('zrender/tool/color');
var colorIdx = 0;
var width = Math.ceil(zr.getWidth()); // 视图宽度
var height = Math.ceil(zr.getHeight()); // 视图高度
F11查看getWidth(),调用painter的方法。getHeight类似实现
// zrender.js
/**
* 获取视图宽度
*/
ZRender.prototype.getWidth = function() {
return this.painter.getWidth();
};
// zrender_demo.html
// 初始化圆形
var circle = new CircleShape({
style : {
x : 100,
y : 100,
r : 50,
brushType : 'both',
color : 'rgba(220, 20, 60, 0.8)', // rgba supported
strokeColor : color.getColor(colorIdx++), // getColor from default palette
lineWidth : 5,
text :'circle',
textPosition :'inside'
},
hoverable : true, // default true
draggable : true, // default false
clickable : true, // default false
// 可自带任何有效自定义属性
_name : 'Hello~',
onclick: function(params){
alert(params.target._name);
},
// 响应事件并动态修改图形元素
onmousewheel: function(params){
var eventTool = require('zrender/tool/event');
var delta = eventTool.getDelta(params.event);
var r = params.target.style.r;
r += (delta > 0 ? 1 : -1) * 10;
if (r < 10) {
r = 10;
};
zr.modShape(params.target.id, {style: {r: r}})
zr.refresh();
eventTool.stop(params.event);
}
});
初始化圆Circle,直接调用基类
// shape/circle.js
function Circle(options) {
Base.call(this, options);
}
base中先对各属性进行默认值初始化,而后使用传入值覆盖
// shape/base.js
function Base( options ) {
this.id = options.id || guid();
this.zlevel = 0;
this.draggable = false;
this.clickable = false;
this.hoverable = true;
this.position = [0, 0];
this.rotation = [0, 0, 0];
this.scale = [1, 1, 0, 0];
for ( var key in options ) {
this[ key ] = options[ key ];
}
this.style = this.style || {};
}
往storage中添加图形形状
// zrender_demo.html
zr.addShape(circle);
// zrender.js
/**
* 添加图形形状
*
* @param {Object} shape 形状对象,可用属性全集,详见各shape
*/
ZRender.prototype.addShape = function (shape) {
this.storage.add(shape);
return this;
};
执行绘图
// zrender_demo.html
zr.render();
zrender直接调用painter接口渲染
// zrender.js
/**
* 渲染
*
* @param {Function} callback 渲染结束后回调函数
* todo:增加缓动函数
*/
ZRender.prototype.render = function (callback) {
this.painter.render(callback);
return this;
};