Why write this article?

  • A I want to study. I like to study.
  • B needs to work, and then I will deal with G6, which is related to wallet.
  • C Sort out the recent articles, with their own text output again, deepen the impression.

The target

I hope that after reading this series of articles, I can have a general understanding of the function distribution and main flow of G6. The focus is on the introduction and main processes of G6, not on the use of specific apis.

What is G6?

The following dimensions explain G6

G6 is a graph visualization engine. It provides diagram rendering, layout, analysis, interaction, animation and other diagram visualization of the basic capabilities. It aims to make relationships transparent and simple. Gives users Insight into relational data.

G6 is a graph visualization brand of ANTV system, which focuses on graph drawing. Antv has other applications, such as G2 and F2, which focus on graph rendering, and L7, which focus on geographic data rendering

G6 is an open source JavaScript graphics library that can support PC, mobile, small programs and multiple platforms.

See diagram visualization engine G6 for more examples of G6 usage

Upstream and downstream of G6

G6 relies on the rendering engine G, which is an Antv open source rendering engine that supports Canvas and SVG rendering across PC and mobile platforms. Graphin is the React library based on G6, which is easier to use by connecting to the React ecology.

Function distribution

Above is a frame diagram of the official V4, which gives a good idea of the basic G6 function distribution.

  • Across PC and mobile platforms
  • Core features: State management, events and interactions, animation, layout;
  • Extension capabilities: plug-ins, custom base types
  • The underlying GPU accelerated computing, G-Base rendering ability, etc.

Engineering structure

G6 is a multi-project repository that uses monorepo ideas to manage projects. Monorepo doesn’t say much. The idea is to manage all related projects in one repository, including development, build, release, and so on. From my own experience, this model does have advantages when developing multiple projects at the same time, avoiding the trouble of managing and linking multiple projects. However, at the beginning stage, I often had doubts and could not confirm which project was the problem. I wanted to build the whole project. G6 uses LERNA to manage all subprojects. The directory structure and introduction are as follows:

G6 | - packages | - core / / G6 core library, realize the most function, main process, animation, interactive, state management | - PC / / extend the core, to provide more interactive, PC events such as mobile / / | - extend the core, // Provide prefabricated custom graph elements (node, edge, Combo) Such as [fisheye effects] (https://g6.antv.vision/zh/examples/tool/fisheye#fisheye) | -...Copy the code

Build projects: NPM install, NPM run bootstrap. See package.json for more instructions

Rendering Engine G

function

Provide rendering capability, provide up

Main process

  1. The top-level abstraction process is a tree of input nodes, traversed and rendered in two steps.
  2. Depth traversal, which is the order in which the nodes are drawn, can be used to control z-index.
  3. G’s render loop trigger is notification trigger, not per-frame render. This processing should save a lot of static drawing costs by triggering the render on the first entry, event, or animation, collecting a wave of updates each time and drawing on the next requestFrame callback. Animations are driven using an additional dependency d3-Timer.
  4. – the game engine will add a render queue between the node tree and the draw interface to facilitate batching optimization of the render queue.

concept

  • Group: Group nodes, organize child nodes, and build a tree structure.
  • Shape: child node, carrying specific drawing capabilities and rendering data, G-Base provides circle, rectangle, line, polygon and other basic capabilities.
  • Detailed data structure of the official document to find shape, see the document. Data structures describe the shapes and states of the types, and data flows and state transitions can track the operation of the entire system, helping to understand and control the system. Various types of shape have some common style structures, such as fill, shadowColor. Each has some special properties, such as the radius of the circle and the width and height of the rectangle.

summary

This section briefly describes the process of G and the input data structure to assist in understanding G6. Some finer points, such as local rendering, shape pickup, collision detection, coordinate systems, etc., are left out for now. As can be seen from the flow chart, G needs a Group tree structure to run, so what G6 needs to do next is to build such a structure and hand it to G for rendering.

G6

Pre-document Description

The core concepts of G6 are described in the official documentation, so we will not repeat them here. We can establish the concepts and basic usage first. A simple example is as follows:

const data = {
  nodes: [
    {
      id: "node1",
      label: "Circle1",
      x: 150,
      y: 150
    },
    {
      id: "node2",
      label: "Circle2",
      x: 400,
      y: 150
    }
  ],
  edges: [
    {
      source: "node1",
      target: "node2"
    }
  ]
};

const graph = new G6.Graph({
  container: "container",
  width: 500,
  height: 500,
});

graph.data(data);
graph.render();

Copy the code

The example is simple, but it basically illustrates the problem. It can be seen that:

  • Use the process: prepare the data and configuration, create the Graph instance, pass in the data, and render
  • Data structure: G6 uses two types, node and edge, to describe the entire graph. Nodes are the nodes of the graph, and edges describe the relationships between the nodes. Node: The relationship between edges is 1:n.

On this basis, there are several functions including behavior, event, state management, animation and layout. The following is in accordance with the execution order of G6, G6 analysis of the basic process and related design.

Graph instance

Once the Graph instance is created, the following singletons are initialized to manage the different functions:

  • graph.cfg.canvas

    The Canvas class instance corresponding to G controls the whole rendering process and connects with G through this singleton

  • graph.cfg.itemController

    Manage Item instances. Item is a g6-wrapped node class. Input edge and node data is organized into an array of Item instances. This module goes through the entire process from data to final rendering. The following sections will focus on the relevant parts of this module.

  • graph.cfg.layoutController

    Control layout related logic, layout algorithm is more complex, G6 unpack a NPM package (@ANTV/Layout) to put the layout related algorithm.

  • graph.cfg.viewController

    Control display related logic. The core logic is to calculate the viewport center, providing coordinate transformation and other functions.

  • graph.cfg.eventController

    Control event-related logic, the core logic is to pick up the event from G, start the user-defined event, and finally feedback to item.

  • graph.cfg.modeController

    Control interactions and manage behaviors.

  • ShapeFactory

    Graph element factory function that manages (CRUD, function call) defined nodes, edges, combo.

Drawing process

The following figure shows the flow state of a node’s data (referring to the node’s data structure in the pre-document example) from input to final rendering, and the process it goes through.

  1. Create graph instance, create G Canvas module instance, input node data.
  2. Call graph. ItemController. AddItem, use the data to create and save in itemController Item instance.
  3. The created item uses factory to find the corresponding drawing node, including the custom node shapeA.
  4. Shapea. drawShape Adds shape to the group to build the render tree.
  5. G Draws the Group tree.

Organization of nodes

After the data is entered, you need to rely on the itemController to create an Item instance to manage it. The Item acts as a bridge between G6 and the render layer and can be examined in detail. The design of the Item class is as follows:

Item

  • Item focuses on the functional support of the G6 layer, the organization and state of diagram elements, etc.
  • Item is divided into three subclasses, Node, Edge, and Combo, which manage different behaviors. For example, Node will have connection points, Edge will have arrows, etc., defined in subclasses. The common logic related to the state and drawing process is the Item class.
  • A subclass of Item and a subfactory of ShapeFactory have an N :1 relationship (see Item init method). The Node class, for example, corresponds to the NodeFactory. If you extend the new ShapeFactory, you need to consider the linkage of Item subclasses.

ShapeFactory

  • By default, there are three sub-factories, NodeFactory, EdgeFactory, and ComboFactory, which correspond to the three graph element types.
  • The responsibility is to manage (add, find) graph elements, which can be understood as a collection of graph element utility classes.
  • Using the abstract factory pattern, you can add new sub-factories or add new types to sub-factories, which is very extensible.

Diagram elements

  • The focus of the Diagram element class is G’s shape, giving G6 support to the drawing capability. Does not hold any state by itself and belongs to the utility class.
  • The relationship between shape and graph element classes is 1:n. You can add new graph element types by combining different shapes.
  • Diagram elements officially define three basic types, node, edge, Combo, the introduction and data structure see the document.
  • A fixed interface in the diagram element class that is called when the program is running. For example, when drawShape or Item is added, this function is called to add shape to the render layer.

Find the diagram element flow

  • A concrete instance of Item, such as Node instance A;
  • Type a.type to find the NodeFactory for ShapeFactory;
  • Type a.cfg. type to NodeFactory to find the registered graph element class;
  • Use diagram elements to draw or perform animations, etc

Other features

I’ve colluded with the drawing process, and I’ve been able to draw it. What else does G6, as a graphical visualization engine, support, and how?

  • Event, interaction, state, this need not say much, only look at the picture can not interaction, the taste is bad
  • Animation, a little buffer effect, visual better
  • Layout, built-in rich layout styles to match a variety of scenarios.
  • . .

The overall idea of this paper is to analyze the relationship between these functions, some internal processes, design and implementation points, so as to basically explain how the whole system runs from large to small.

The overall relationship

The hierarchical relationship of each function is as follows:

The whole G6 is based on these core functions, and the diagram shows the hierarchical relationship between the various functions, so that you can understand the location of the functions. Once you have a sense of the big picture, you can reduce the confusion.

In addition to animation, all of these functions have corresponding controllers, which are encapsulated by Graph and placed on Graph. One of the design features of G6 is that all state related items are placed in the CFG, which should represent the model of this type. CFG in Graph class, CFG in Item class, etc. But it’s a little weird to hang a Controller that’s logically dense.

Event, animation, and Item node management depend directly on G. Interaction, state management, and layout are more based on G6’s own encapsulation.

The event

Official documents have a clear classification of events. There are three types of events: Canvas :mousedown… , node level events (node:click…) , events by timing (afterLayout…) . An event includes an event name and a callback to the event. Event names vary from platform to platform, such as mouse events for PC platforms and Touch events for mobile platforms. For details, see the Events section of the core Concepts section of the documentation.

We’re all familiar with events, observer, publish subscribe, and so on. G6 event is not exceptional also, there is a global event center, graph. CFG. EventController, provide event subscription and release. However, different from what we know about Dom events, G6 may only face one Dom element, Canvas, so it cannot rely on the platform itself to parse the node and event object triggered by the event, it needs to implement and encapsulate by itself.

  • Publish and subscribe for timed events using eventController.
  • Canvases, nodal level events, G and G6 all have partial implementations. G’s tree nodes inherit from @antV /EventEmiter, making each node support event registration and bubbling, similar to dom. G6 takes over all events of the root element of G’s tree node and distributes them uniformly. In the G6 document, we only mention that we can register events through Graph, so we should not touch the behavior of this layer when using G.
  • Take click as an example to illustrate the flow of the following event:
    1. When G6 creates an item, it attaches its own reference to the corresponding group
    2. User triggers click
    3. Triggers a canvas native event
    4. G does shape pickup according to click coordinates, and events bubble
    5. G6 observed the root element event trigger, and got the shape passed, further can do the event distribution, drive interaction function

Shape to pick up

From the previous article, we know that G organizes the drawn nodes into a group tree structure, and shape is the child node of the tree. To determine which shape/group to click on, the obvious idea is to walk through the tree and find the node. The following is the quickHit mode node pickup process, source see G project g-base package in the event. Ts file. (In quickHit mode, the source code mainly ignores the group click detection and only detects leaf nodes, which improves performance.)

  1. Triggers the click
  2. The source event object was obtained. Procedure
  3. Gets the coordinates of the click point
  4. Traverse the Group tree in depth from right to left (render from left to right, render last on top, fire first)
  5. Filter by click coordinates (skip hidden, no-pick, off-canvas tree nodes)
  6. Click to detect that the coordinate point is in the shape, judge to find the shape, and return the shape
  7. If the traversal is not hit, the trigger is not triggered

Each shape type has its own detection method, such as the distance between the point and the center of the circle. Every time an event is triggered it has to go through the whole tree, do click detection, which is a performance point, so G itself does some caching.

The event bubbling

The propagationStopped attribute in the event object is true or reaches the root element. The propagationStopped attribute in the event object is true.

Interactive mode

** Interactive mode solves the problem? ** is used for batch manipulation of user interactions, such as switching between edit and view modes. For details, see the Behavior section in the core concepts section of the documentation. Class design.

Behavior is a factory class that uses an image to store individual Behavior types. Each Behavior subtype defines the desired set of event behaviors and provides the binding and unbinding of events. ModeController, based on the input mode configuration (an array of indexes of the Behavior type), or dynamically switching different Behavior subclass instances.

ModeControler Binding Behavior Process:

The core idea is that the ModeController calls the Behavior factory to create an instance of a subtype that completes the binding process. The trigger is either when the Graph is initialized or when graph.setmode is dynamically called while the system is running.

State management

What problems does state management solve? Triggers an update of the node style or other custom behavior when the interaction is implemented or when the node state changes in the business logic. The state can be hover, active, or running. The response to the state, if it’s just a style change, can be set directly in the node configuration entered when the Graph instance is created. For more complex behavior, such as adding an animation, you need to customize the node and override the default setState method. For details, see the interactive Mode and State sections in the core concepts section of the document.

Class design.

The Graph instantiates the StateController and ItemController, which can be accessed in the Graph instance’s CFG.

StateController currently maintains an array of items in various states and triggers events when the state is updated. It does not affect the entire state process.

Setting status process:

  • Configure styles for different states in the input data
  • Event or process trigger, calling graph.setitemState to update the state
  • Find the style of the state in the configuration
  • Item (node to be updated) to the specific shape, call the setState of shape, and update the style to the G rendering layer

animation

Animation G6 does nothing to deal with the direct use of G’s animation capabilities. According to the usage scenario, it is divided into two parts: global animation and custom node animation. See the basic Animation section in the core Concepts section of the documentation for details. ** Take the root element of the node tree and call animate;

Custom node animation: When customizing the shape element (see the previous section for more information about G6, which is used to connect to G and encapsulates shape), you take the Shape or group node and call animate.

Class design.

  • Element implements the animate interface, and subclasses have animation capabilities.
  • The Animation class does not have a separate file in the source code, but it is distinguished by the TS declaration, which records the detailed configuration of the Animation.
  • The Canvas class is the master class and entry for the G layer. The root node, animation entry, drawing entry, and so on are all on this class.
  • The Timeline class uses Element and Animation to implement the specific Animation algorithm. When used as a singleton hangs on the Canvas instance.

Animation flow:

The core idea is that Element obtains the TimeLine instance in Canvas, passes in the animation data, and gives it to d3-Timer to execute frame by frame, so as to achieve continuous animation effects through interpolation.

Interpolation calculation is aided by d3-ease, d3-interpolate.

Updating to the canvas is Element’s ability.

The process is triggered when global animation or custom animation calls Animate.

layout

Layout is the use of algorithms so that nodes and edges can be distributed in a certain way. It is divided into general diagram layout and tree diagram layout, so far I only see the general diagram layout, just analyze the general diagram layout. For details, see the Diagram Layout section of the core concepts section of the documentation.

Related classes:

The layout is controlled using the LayoutController that is created when the Graph is initialized. The specific layout algorithm comes from the NPM package ** @antv/layout**.

The specific flow of general diagram layout

As you can see, the layout and Graph are decoupled by data. Graph is data-oriented, and if the data is correct, it will render normally. The layout algorithm also focuses only on the production of the data, not on Graph or other systems.

The layout algorithm updates the node coordinates to achieve the purpose of layout, and other data items can also be updated, but the responsibility is not clear, so it is not recommended to update the layout algorithm to other data items.

The process for PC and Mobile platform layout is inconsistent. PC will also support worker layout, which is the layout process in the third column in the figure. The layout is divided into three steps for asynchronous notification.

Trigger the timing of the process is in the initialization data, layout, or switch is in the call Graph render/changeData/updateLayout.

Here is an example of a custom layout that should give you a clearer idea of what a layout algorithm is supposed to do.

summary

Through the hierarchical distribution of each function, and the analysis of the respective implementation process, we should have a general understanding of the G6 implementation idea. If you are interested, you can look at the source code of the process and see the implementation logic for a specific step. After sorting out G6 during this period, I also have a more understanding of G6. Finally, thanks for reading.

The last

Search the official wechat account Eval Studio for more updates.