zoukankan      html  css  js  c++  java
  • Graphics 与 DisplayObject 的关系

    在原生 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, ...) 的参数 <x, y> 就是 displayObject 的属性 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...
    图片描述

    代码很简单,如下:

    1. 创建一个「Rect 实例」;

    2. 「Rect 构造函数」将 drawRect 的实现代码挂载在 prototype.exec

    3. 将「Rect 实例」append 到数组 _activeInstructions中(第四张截图);

    4. 返回「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 一样麻烦。

  • 相关阅读:
    Atitit  atiMail atiDns新特性 v2  q39
    Atitit  atiMail atiDns新特性 v2  q39
    Atitit.aticmd v4  新特性q39 添加定时器释放功能
    Atitit.aticmd v4  新特性q39 添加定时器释放功能
    Atitit. Atiposter 发帖机 新特性 poster new feature   v7 q39
    Atitit. Atiposter 发帖机 新特性 poster new feature   v7 q39
    Atitit.编程语言and 自然语言的比较and 编程语言未来的发展
    Atitit.编程语言and 自然语言的比较and 编程语言未来的发展
    atitit.解决struts2 SpringObjectFactory.getClassInstance NullPointerException  v2 q31
    知也atitit.解决struts2 SpringObjectFactory.getClassInstance NullPointerException  v2 q31无涯 - I
  • 原文地址:https://www.cnblogs.com/10manongit/p/12852573.html
Copyright © 2011-2022 走看看