The preface
Some time ago, we proposed a risk control department needs, “associated map to implement a platform personnel correlation information display, its purpose is to users than between the hierarchical relationship in multi-dimensional visualization, motivation, so that the personnel can more quickly and accurately find various violation behavior, reducing risk of platform.
In addition to displaying a large amount of associated data, the whole requirement also needs to change the style of corresponding nodes and edges according to the exact association factor or association UID, display data over the mouse and other functions, and there are some special requirements on graphics.
The following is the basic effect of this requirement
At present, echarts and G6 are two mainstream technologies for front-end visualization of relational data. Compared with ECharts, G6 is better in graph editing and analysis, it supports various complex interactions, and focuses more on showing the performance of more nodes and edges. Therefore, I choose G6 to realize the “association graph”. However, in the process of exploration, I found that the use of built-in graphics and interaction still cannot meet the needs, but G6 also provides a strong ability to customize, through this function I perfectly realize the need of “association graph”, and this article will take you to reveal how to use G6 customization function.
Basic concepts to understand
To understand G6 custom features, it’s natural to start with some basic concepts.
The bottom layer of G6 3.0 is actually designed by combining Canvas and SVG. The second layer reflects some capabilities provided by G6 3.0, including graph extension and state management, etc. The third layer is the basic elements of the graph. For the third layer, I have drawn a Graph of the hierarchy. According to this inclusion relation, let’s learn some concepts step by step.
The chart Graph
Graph is the carrier of G6 graphs. All G6 node instance operations, events, and behavior monitoring are performed on the Graph instance, which includes one or more Graph groups.
Graph has five main life cycles: initialize – > load data – > render – > update – > Destroy. Graph, data(data), Render (), changeData(data), clear()
Graph Group
A graphical grouping group is similar to a label in SVG: the element G is a container for combining graphical objects. Adding transformations (such as clipping, rotating, scaling, panning, etc.) to a group applies to all of its children.
In G6, all nodes in an instance of Graph belong to the same group named nodeGroup, and all edges belong to the same group named edgeGroup. Node groups have a higher visual hierarchy (zIndex) than edge groups, that is, all nodes are drawn on top of all edges.
As shown in the figure below, three nodes belong to nodeGroup, and two edges belong to edgeGroup. The nodeGroup level is higher than edgeGroup, and the three nodes are plotted on the upper layer of the three edges.
Elements of the item
The element Item is an abstract class of Node, Edge, Guide, and other diagram items.
There are two most commonly used graph items, node and edge.
The basic structure of a node:
The basic structure of edge:
Shape of the shape
Shape refers to a Shape in G6. It can be a circle, a rectangle, a path, etc. Each type of node or edge in G6 consists of one or more shapes. Built-in nodes are ‘circle’, ‘rect’, ‘ellipse’… ; Built-in edges are ‘line’, ‘Polyline’, ‘Cubic’… ; You can combine several built-in shapes to create a shape that meets your needs.
The figure below is a combination of circle and text shapes.
To customize nodes/edges, you need to understand shape’s lifecycle method and selectively copy its methods.
draw(cfg, group)
: draw, which provides configuration items for drawing (pass through when data is defined) and graphics container (graphics group);update(cfg, n)
: update, configuration items at the time of update (merge of updated fields and original fields) and node objects;afterDraw(cfg, group)
: Operation after drawing- .
The following figure shows the lifecycle methods in several Shapes
Key graph keyShape
Each type of node and edge has a unique key graph —-keyShape. KeyShape is a graph object returned in the draw method of nodes that is used to ** determine nodes’ Bounding boxes ** and thus calculate the joining points of related edges (intersections with related edges).
Register custom graphics
Before we can customize our own graphics we need to register them globally in the G6 instance.
As shown in the figure below, a node named circle-image-node is registered below, using defaultNodeConf to configure the methods that define the node, and is extended based on G6’s built-in image.
You can use custom graphs by configuring Shape in the Graph configuration.
Base – Extends the built-in Shape
While we conclude that the built-in graphics in G6 can’t meet our needs, we also find that the built-in graphics often need to be slightly changed to meet our needs. In this case, we need to copy the built-in graphics in several common ways to extend the built-in shape.
Custom node
Requirement: In the previous requirement of “Association graph”, a red box should be added to the node label to highlight the node label when a field (level) is given in the data on the basis of the original diagram.
We’ll still use ‘circle-image-node’ as an example, but this time we’ll extend circle.
In the life-cycle method that copies Shape, the method is called afterDraw, executed after the draw method, and is often used to extend existing nodes and edges
The following figure shows the source data of the node
You can see that this node is a node with radius 50 and lebal ‘Circle’
The afterDraw method takes two parameters. CFG, the first parameter of afterDraw, takes all the data in the source data and appends all the style configuration. After the data is retrieved, you can add a shape using the group.addShape() method, whose first argument is the shape name and the second argument is the configured property
This is done by adding a recT graph with no padding and red stroke and wrapping text around it.
You can see that the origin is actually at the center of the symmetry of the circle. It only takes a little bit of positioning to realize the function.
The final implementation effect
Even some mapping
Next we add nodes and connect them by edge. The changed data source is shown below
The effect is shown below
Someone asks: “You have an edge connection with a node. What if I have two edge connections? Do edges overlap?”
Let’s add an edge in the opposite direction called edge2.
You can see that the edges connecting the two nodes do overlap if no extra processing is done.
This brings us to the next section on custom edges.
The custom side
The G6 offers a total of nine built-in edges:
- Line: a straight line that does not support control points.
- Polyline: polyline, supporting multiple control points;
- The arc of an arc
- Quadratic: a second-order Bessel curve, which, when not specified by controlPoints, defaults to curve at half of the line;
- Cubic: third-order Bessel curve, controlPoints are not specified, will default line 1/3, 2/3 bending;
- Cubic -vertical: third-order Bezier curve in the vertical direction, regardless of control points passed in from the user externally;
- Cubic – horizontal; Horizontal third-order Bezier curves, regardless of user input from external control points;
- Loop: self-loop.
When edge overlap occurs, if the built-in edge with control points is used, the control points of the edge can be customized to achieve the effect that multiple edges between nodes do not overlap.
This time, we extended the QUADRATIC with one control point. In the case that the source data had two edges in the same direction, we defined an edge named quadratic- curve-edge.
To change the position of the control points, you need to override shape’s getControlPoints(CFG), which returns the control point instance of Shape.
The whole process of copying getControlPoints(CFG) requires you to generate new control points through the util.getControlPoint method and return the new control points.
The Util. GetControlPoint method takes four arguments:
- StartPoint Specifies the starting point of the edge
- The endPoint of the endPoint
- Position Indicates the position of the control point on the edge
- Offset Indicates the distance from the startPoint line along the vertical vector (clockwise) direction of the endPoint
As can be seen from the CFG parameter of the getControlPoints method on the print side, the coordinates of the starting point and the ending point can be obtained from the CFG.
Here a random value of 0-9 is used to generate a level, and the offset of the control point is generated according to certain calculation rules, and position is in the middle of the edge by default. Let’s run it and see what happens.
The Update method
Another tried-and-true trick is to copy the Shape update method.
Requirement: Let’s say I want to click on which edge to turn red.
The first step is to set up the click event listener:
All of G6’s listener events are set on the graph instance. The common events are click, DblClick, MouseEnter, mouseleave…
Use grammar:
graph.on('click', cb);
Copy the code
Of course, by combining the prefixes ‘node’, ‘edge’, ‘group’, and ‘guide’, you can get the desired target faster.
You can get the instance of the clicked edge by getting the item under EV, and then call the Update method to change the edge style.
If I wanted to have multiple sets of styles that could be configured and isolated from each other, I could change the mapping table to implement different style combinations, so it would be our turn to duplicate the update method on the edge.
Suppose I specify that a style map has multiple patterns, and that the pattern is the combination of styles to be configured, so that I can switch between multiple sets of styles simply by changing one of the attributes of the side data.
Type1 is blue with a width of 2px and type2 is red with a width of 4px
Since we have abstracted the style, we need to change the data source
Now it’s time to replicate the update. All we need to do is map the abstract properties in the data to the actual style of the edge and set them synchronously to the edge.
First obtain the type in the source data through CFG and determine the specific style. Then set the corresponding style to the instance through attR method. The result is shown in the following figure.
Once the initial state is OK, the style can be abstracted by simply setting the type property of the edge when clicked. Even if the style changes later, it can be handled perfectly by configuring the mapping table.
Advanced – Fully custom graphics
After all the demos you’ve done, you probably know a little bit about some of the most common lifecycle methods for customizing shapes, but what if you can’t even extend shapes? Then you need to completely customize a graph.
Let’s customize a diamond from scratch:
Note: The draw method is required if you do not extend a new node from any existing node
Path is used to draw a diamond, and SVG’s path drawing method is used to define the path.
There are five common commands
- M moves to the starting point of (moveTo) x and y
- Z Closepath Connects the start and end points of a path with a straight line
- L lineTo the current node to the specified (x,y) node, a straight line connection
- H Horizontal line x keeps the y coordinate of the current point constant, and the X-axis moves to x, forming a horizontal line
- V vertical line y keeps the x-coordinate of the current point constant, and the Y-axis moves to y, forming a vertical line
To getPath, you first need to override the getPath method of shape.
After obtaining the path, we can define shape in Draw.
Replace the original nodes and a new diamond shape appears on the canvas.
When fully customized, the draw method must return a Shape as a keyshape
Compared with the previous built-in prototype node, the label in the data source is not displayed here, because the built-in node has a text to display the label data of the node separately. So all we need to do is add a text graphic to the draw method.
Custom graphics code links: note.youdao.com/noteshare?i…
High level — custom interaction
In addition to customizing graphs within graphs, you can also customize the interaction behavior of graphs. There are two important concepts: Mode and Behavior.
Mode and Behavior are the graph event definition and management mechanisms provided by G6. Mode refers to the event Mode of the current graph. A Mode may contain multiple behaviors. You can switch the behavior of the current event by switching Mode on the graph. Behavior refers to the composite interaction in G6, which generally consists of one or more events listening and processing and a series of actions on the elements in the diagram.
Consider an example that implements a simple graph editor: you can add nodes to the canvas and drag them; You can add edges between nodes.
In order to distinguish different scenarios, we divide the whole function into three modes, namely addNode addNode, addEdge addEdge, and default mode default;
Simply add modes to the global configuration:
In the figure, both drag-node and click-select are built-in behaviors that implement dragable nodes and selectable functions respectively, so we only need to define click-Add-node and click-Add-edge behaviors.
Register a behavior API: G6. RegisterBehavior, which takes two parameters, one for the name of the behavior and one for the method to be copied.
First we register the click-Add-Node behavior
GetEvents is the required method, which returns a mapping of method names, as shown in the figure. Since this only involves listening events when the canvas is clicked, map the onclick method to the Canvas: click method.
This will trigger your onclick method when canvas: click is triggered.
Add a node with graph.addItem (where the ID is defined by the number of nodes added).
The second part defines the click-Add-edge behavior and analyzes the following events that need to be listened for
- Node :click: To add an edge between two points, first determine which two points of the point
- Mousemove: New lines move with the mouse
- Edge: Click on the space to cancel the edge
Click to generate an edge and set the source or target of the edge.
There’s an addingEdge state that indicates whether you’re setting target or source. And use edge to temporarily store edge data when not fully set
After the first click, the target property of the edge is dynamically updated to achieve the effect of the edge moving with the mouse.
What if we want to cancel generating half of the edges? As a result of dynamically setting the target of edge, the event listening of clicking edge will be triggered at this time. Therefore, it only needs to remove the temporary edge instance just added at this time, empty the temporary edge data and reset the addingEdge state.
After implementing the behavior, we only need the final step —- to switch modes. Use graph.setMode(modeName) to switch.
Here, a drop down box is used to select different values to achieve the switch mode, which is used to isolate the interaction of multiple behaviors.
The final result is shown below:
Custom actions demo code links as follows: note.youdao.com/noteshare?i…
added
- In a force-oriented layout, if there are loose nodes (no connected edges) and they are not set in the position of the canvas (X,Y of the nodes), the problem of the position span of the nodes will occur (especially if the canvas itself is large), after all, it “has no fixed place”.
- The G6 does not support the react method for writing customized side tooltips, but since the G6 can listen for mouse events, it is possible to use mouseEnter and mouseleave events to control the position of a React component to create a customized tooltip.
- The method of using level to adjust control points described in this paper had better count the repeated edges between nodes and set the level value according to the count.
conclusion
This article focuses on G6 custom graphics and custom behavior.
Before customizing, you need to register your custom content with registerNode, registerEdge, and registerBehavior to use in the corresponding Graph configuration.
When customizing shapes, you need to clone several of Shape’s lifecycle methods. The most common is the afterDraw method, which extends the built-in shapes.
To customize an interaction, you need to implement your own event-listening methods and map them to timed events using the return value of the getEvents method. If you want multiple behaviors to affect each other in isolation, you need to use them in conjunction with mode, and switch modes with graph.setmode.
The end of the
After all this talk, you’ve already got a glimpse of the G6’s custom features. In fact, in addition to the graphics and behavior, pattern customization, there are many places worth DIY, like guidance, groups, and even animation can be customized. If you need to implement a relational data visualization map, have unconventional graphical display, or need to perform complex operations such as CRUD on the map, then the G6 custom features described in this article will certainly help you to complete the development quickly.
Reference for this article:
The official document: g6. Antv. Vision/useful/docs/man…
Documentation: www.yuque.com/antv/g6
AntV architecture evolution – G6 article: www.yuque.com/antv/blog/b…