先看下,本次例子做的效果
然后开始代码:
调用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; };