摘要:大部分的原生绘制图形或图像的一般是这样的例如就是。这类绘制大部分被封装在的类中,它们有一个共同的特点名字都是以开始,例如。基础图形实例的作用是提供一个修改图形接口。如果从嵌套的维度来说与的关系是等基础图形其实,完全不需要这么实现。
在原生 Canvas 中,其实并没有 DisplayObject 的概念,它只有绘制图像的概念。
大部分的原生绘制图形或图像的 API 一般是这样的:
api(x, y, ...)
例如 rect 就是:ctx.rect(x, y, width, height)。
这类绘制 API 大部分被封装在 CreateJS 的 Graphics 类中,它们有一个共同的特点 ---- 名字都是以 draw 开始,例如:drawRect / drawCircle 。
为什么说是大部分绘制的API被封装在 Grahpics 类中呢?
很简单,Graphics 类处理的是图形绘制,所以也可以说所有的图形绘制 API 被封装在 Graphics 类中。绘制API还有另一个功能 ------ 绘制图像,这个功能被封装在 Bitmap 类中。
我曾经这样觉得:「graphics.draw*(x, y, ...) 的参数
var rect = new createjs.Shape(); rect.graphics.drawRect(50, 50, 100 100); stage.addChild(rect); console.log(rect.x, rect.y);Graphics 的工作原理
来分析 Graphics 的 drawRect API 源码:
https://www.createjs.com/docs...
https://www.createjs.com/docs...
https://www.createjs.com/docs...
https://www.createjs.com/docs...
代码很简单,如下:
创建一个「Rect 实例」;
「Rect 构造函数」将 drawRect 的实现代码挂载在 prototype.exec 下
将「Rect 实例」append 到数组 _activeInstructions中(第四张截图);
返回「Graphics」实例
为什么需要一个数组(_activeInstructions)来存储原生指令?
对于矩形、圆形和圆角矩形来说,确实不需要数组来存储指令;但是梯形、三角形等图形没有对应的原生API,此时需要使用绘制线段或孤线(ctx.moveTo/ctx.lineTo/ctx.arc)来组合产生,而数组 _activeInstructions 就是来处理组合图形产生的。
Rect实例有什么作用?
Rect实例是 drawRect 返回的实例,Graphics 里还有其它的 draw* API,它们会返回各自图形的实例,所以可以把 Rect实例和其它实例统称为「基础图形实例」。「基础图形实例」的作用是提供一个修改图形接口。通过第四张截图,可以看到「基础图形实例」最终被挂载在「Graphics 实例」的 command 属性下,也就是说通过「Graphics实例」的 command 可以访问到最新的「基础图形实例」,写一个测试代码如下:
var gcircle = circle.graphics.beginFill("00ff00").drawCircle(0, 0, 10); circle.x = circle.y = 100; stage.addChild(circle); stage.update(); setTimeout(function() { gcircle.command.radius = 50; stage.update(); }, 1000);
这个特性在动态绘制图形上是很有用的,不过,它有一个短板:通过 command 属性只能访问到最近的「基础图形实例」。也就是说自定义的组合图形,如果需要访问到对应的「基础图形实例」就需要把绘制过程拆散,举个例子:
// 三角形 var threeangle = new createjs.Shape(); threeangle.graphics.beginFill("00ff00").moveTo(50, 0).lineTo(0, 50).lineTo(100, 50).closePath(); stage.addChild(threeangle); stage.update();
如果底部两个端点要做动画:
// 三角形 var threeangle = new createjs.Shape(); threeangle.graphics.beginFill("00ff00").moveTo(50, 0); var p1 = threeangle.graphics.lineTo(0, 50).command; var p2 = threeangle.graphics.lineTo(100, 50).command; threeangle.graphics.closePath(); stage.addChild(threeangle); stage.update(); setTimeout(function() { p1.y = 100; stage.update(); }, 1000); setTimeout(function() { p2.y = 200; stage.update(); }, 2000);Shape 的工作原理
https://www.createjs.com/docs...
Shape 极简单,就是生成一个 DisplayObject 实例,然后在这个实例中挂载一个 Graphics 实例。而它的工作原理(即它的渲染)如下:
https://www.createjs.com/docs...
也就是 Shape 实例的 draw 方法其实是直接调用 Graphics 实例的 draw 方法。
DisplayObject 的工作原理DisplayObject 的核心功能是处理 DisplayObject 实例的「矩阵转换」(即位移与形变),如下:
https://www.createjs.com/docs...
我在 聊聊 Container 的实现 中介绍了使用原生 Canvas 实现 Container 的原理。其实,Shape 实例也是一个Container,只是 CreateJS 限制了 shape 只能放 Graphics 实例,而且 shape 只能存放一个 Graphics 实例(即shape 下的 graphics 属性),Graphics 实例下存放多个「基础图形实例」。
**如果从嵌套的维度来说 Graphics 与 DisplayObject 的关系是:
Container > Shape > Graphics > Rect/Circle/RoundRect等基础图形**
其实,CreateJS 完全不需要这么实现。像 PIXI 在实现 Graphics 的时候,Graphics 也一个 Container,它可以像一个正常的 DisplayObject 一样被使用,而不用像 CreateJS 一样麻烦。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/89512.html
摘要:首先要指出的是实例的属性与的参数没有关系。同理可得的与在效果上都是。对实例设置了后,实例的位置会发生变化,这是因为执行了。自此以下结论是正确的的最终也会转换成原生的 首先要指出的是:DisplayObject 实例的属性 与 graphics.draw*(x, y, ...) 的参数没有关系。 在原生的 Canvas 中有 的概念,例如:ctx.rect(x, y, width, ...
摘要:类介绍继承自方法把此显示对象写进一个新的隐藏的,然后用于接下来的绘制。缓存好的这个显示对象,可以自由地移动旋转渐消。 类介绍 继承自 EventDispatcher DisplayObject is an abstract class that should not be constructed directly. Instead construct subclasses such a...
摘要:可以这样说,和应用了的元素是两个彼此独立的元素,这也是元素的不跟随元素一起位移或形变的根本原因。结论为什么元素的不跟随元素一起位移或形变答案是元素与是兄弟关系。 之前在做「双十一攻略页」的时候就发现这个细节,但是当时没有太在意,今天又遇到了。 createjs 的代码: var stage = new createjs.Stage(canvas); var container = n...
阅读 1448·2023-04-25 17:18
阅读 1886·2021-10-27 14:18
阅读 2127·2021-09-09 09:33
阅读 1842·2019-08-30 15:55
阅读 2018·2019-08-30 15:53
阅读 3443·2019-08-29 16:17
阅读 3431·2019-08-26 13:57
阅读 1733·2019-08-26 13:46