G4.0源码解析(一)

本文详细介绍了AntVG库中的Canvas组件、不同渲染器的使用,以及图形对象的DisplayObject基类。重点阐述了Canvas的初始化过程,包括渲染器的选择、图形渲染插件的管理以及图形执行的生命周期管理。
摘要由CSDN通过智能技术生成

顶层对象

G的初始化是通过创建一块Canvas画布,将创建的基础图形挂载到画布下,如下示例:

// 引入 G 核心中的画布、各种 2D/3D 图形
import { Canvas, Circle } from '@antv/g';
// 选择一个或多个 Renderer
import { Renderer } from '@antv/g-canvas';

// 使用 World API 描述场景
const canvas = new Canvas({ renderer: new Renderer() });
const circle = new Circle({ attrs: { r: 20 } });
canvas.appendChild(circle);

Canvas类似其他库中的Stage,作为入口。

Renderer则为渲染时所使用的渲染器,如2d/3d/svg,渲染器负责执行拾取、DOM事件、核心渲染过程等

基础图形

G的图形对象基类是DisplayObject,同pixi、fabric、zrender等,与konva不同的是,其他图形对象例如 Group Circle Text 等都会继承它

而G为了兼容 DOM Element API,使用下面的继承机制:

DisplayObject -> Element -> Node-> EventTarget -> EventEmitter

这个图形基类的继承设计并没有下面pixi的直观:

DisplayObject -> EventEmitter

Canvas执行机制

g-lite/src/Canvas.ts

class Canvas {
  constructor() {
    // ...
    this.initRenderer(renderer);
    // ...
  }
  initRenderer(renderer) {
    // reset
    this.inited = false;
    this.readyPromise = undefined;
    
    // 初始化rBush树,用法参考:https://www.5axxw.com/wiki/content/7wjc4t
    this.context.rBushRoot = new RBush<RBushNodeAABB>();

    // 装载四种插件,插件内apply方法中的逻辑会注册到tapable的各个生命周期中
    this.context.renderingPlugins = [];
    this.context.renderingPlugins.push(
      new EventPlugin(),
      new PrepareRendererPlugin(),
      new DirtyCheckPlugin(),
      new CullingPlugin([new FrustumCullingStrategy()]),
    );

    // 调用三种渲染器其中一种的init方法,这里最终会调用到g-plugin-canvas-renderer/src/index.ts下的init方法
    // 到g-plugin-canvas-renderer之前的流程进本方法查看
    this.loadRendererContainerModule(renderer);

    // 创建canvas元素并初始化context上下文
    // 最终会调用到g-canvas/src/Canvas2DContextService.ts下
    // 调用过程:
    // 由于上面的loadRendererContainerModule方法会先执行g-canvas/src/index.ts
    // 这个文件中的this.registerPlugin(new ContextRegisterPlugin())会定位到Canvas2DContextService西安
    this.context.contextService = new this.context.ContextService({
      ...runtime,
      ...this.context,
    });

    // 实例化渲染服务,最终执行到g-lite/src/service/RenderingService.ts
    // RenderingService负责实例化并存储tapable的生命周期
    // tapable:为webpack使用的生命周期库, .tap()等方法为注册一个周期, .call()/.promise()方法为执行注册的周期
    this.context.renderingService = new RenderingService(runtime, this.context);

    // 初始化DOM事件服务,最终执行到g-lite/src/service/EventService.ts下的init方法
    this.context.eventService = new EventService(runtime, this.context);
    this.context.eventService.init();

    // 执行g-canvas/src/Canvas2DContextService.ts下的init方法
    await this.context.contextService.init();
    // 执行g-lite/src/service/RenderingService.ts下的init方法
    await this.context.renderingService.init();

    this.inited = true;

    // getRoot方法中获取的this.document.documentElement类似konva中Stage下挂载的children
    // 将根下挂载所有节点的渲染包围盒、几何包围盒、图形本身的脏标记置为true
    // 这里重置的是渲染包围盒、几何包围盒的全局边界脏标记
    this.getRoot().forEach((node) => {
      const renderable = (node as Element).renderable;
      if (renderable) {
        renderable.renderBoundsDirty = true;
        renderable.boundsDirty = true;
        renderable.dirty = true;
      }
    });

    // 触发mount生命周期
    this.mountChildren(this.getRoot());

    // 若配置开启自动渲染,执行首次渲染流程(在Canvas::render中会执行renderingService.render)
    // renderingService.render是每一次渲染流程的汇入口,有点类似konva的_requestDraw
    if (renderer.getConfig().enableAutoRendering) {
      this.run();
    }
  }

  

  private loadRendererContainerModule(renderer: IRenderer) {
    /**
     * import { Renderer } from '@antv/g-canvas';
     * const canvas = new Canvas({ renderer: new Renderer() });
     * 执行过程如上
     传入的renderer参数即g-canvas/src/index.ts暴露出的CanvasRenderer类,代码如下:
     * export * as CanvasRenderer from '@antv/g-plugin-canvas-renderer';
     * 随后执行CanvasRenderer的init方法
     * 这个init方法负责派发执行具体图形对象的样式绘制过程(填充、描边、阴影等)
     */
    const plugins = renderer.getPlugins();
    plugins.forEach((plugin) => {
      plugin.context = this.context;
      plugin.init();
    });
  }
}

流程图

  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值