Start with graph syntax

Graph Grammar is the core theory of F2 data visualization, and the core of graph Grammar is to describe arbitrary statistical charts through a set of abstract syntax. According to the book, the definition of statistical charts depends on the following basic syntax:

The statement describe
DATA Generate visually encoded data operations from data sets
TRANS Variable conversion (e.g. Rank)
SCALE Metric conversion (e.g., log)
COORD Define coordinate systems (e.g., polar coordinates)
ELEMENT Graphics (e.g., dots) and their aesthetic properties (e.g., color)
GUIDE Auxiliary elements (e.g., Axis, Legend)

If we use a data structure to express, it can be abstracted into the following data structure

{
  data: [
    {"category": 1, "value": 4},
    {"category": 2, "value": 6},
    {"category": 3, "value": 10},
    {"category": 4, "value": 3},
    {"category": 5, "value": 7},
    {"category": 6, "value": 8}
  ],
  trans: {
    value: 'rank',
  },
  scale: {
    value: 'linear',
  },
  coord: 'polar',
  element: {
    "theta": {"field": "category"},
    "radius": {"field": "value"},
    "color": {"field": "category"}
  },
  guide: {
    axis: {
     value: {},
    }
  }   
}
Copy the code

Let’s look at an imperative description of the F2.x API

chart.data([
  {"category": 1, "value": 4},
  {"category": 2, "value": 6},
  {"category": 3, "value": 10},
  {"category": 4, "value": 3},
  {"category": 5, "value": 7},
  {"category": 6, "value": 8}
]);
chart.scale({
  value: 'linear',
});
chart.coord('polar');
chart.interval('category*value').color('category');
chart.axis({
  value: {},
});
chart.render();
Copy the code

In terms of type, we can classify the previous JSON description as “declarative” and the API call as “imperative.” Although there is not much difference in the final result, the following API imperative is much more flexible than the JSON declarative. Because we can add a lot of logical code in the process of calling API to meet our personalized business needs, this is also one of the reasons why F2 did not directly use JSON in the first place.

Although F2 appears to be imperative, internally we also build a structure object to hold the description object of the graph syntax, but externally we provide the API imperative programming pattern, which means that our ultimate goal is to construct the structure description of the graph syntax

Before answering the question of why JSX is now being adopted rather than the previous API imperative, let’s take a look at JSX and its features.

What is the JSX

JSX allows you to easily create data structures that have nothing to do with React. We simply define our own constructor through the Babel JSX Transform

Here’s an example:

Suppose we define the following constructor and JSX structure

export function jsx(type, config, key? : string) { return { key, type, ... config, }; }Copy the code
<chart
  data={[
    {"category": 1, "value": 4},
    {"category": 2, "value": 6},
    {"category": 3, "value": 10},
    {"category": 4, "value": 3},
    {"category": 5, "value": 7},
    {"category": 6, "value": 8}
  ]}
  scale={{
    value: 'linear',
  }}
  coord='polar'
>
  <interval position="x*y" />
  <axis field="x" />
</chart>
Copy the code

Then the transformed code will become

import { jsx as _jsx } from "./jsx-runtime";

_jsx('chart', {
  data: [],
  coord: 'polar',
  children: [
    _jsx('interval', {
      position: "x*y",
    }),
    _jsx("axis", {
      field: "x",
    }),
  ],
});
Copy the code

After execution, the following structure should be obtained

{
  type: "chart",
  data: [],
  coord: "polar",
  children: [
    { type: "interval", position: "x*y" },
    { type: "axis",  field: "x" }
  ]
}
Copy the code

We also get a similar data structure through JSX, so we can also use JSX to generate the structure description we need, so what are the advantages of JSX compared to that, let’s look at the advantages of JSX

The advantage of the JSX

As I have seen before, our ultimate goal is to get the final graph syntax structure description, whether JSON, API imperative, or JSX is to generate this structure, so what are the advantages of JSX in comparison

1. Programmability

JSX makes it easy to embed expressions in structures, something JSON doesn’t have

For example

<chart data={[ {"category": 1, "value": 4}, {"category": 2, "value": 6}, {"category": 3, "value": 10}, {"category": 4, "value": 3}, {"category": 5, "value": 7}, {"category": 6, "value": 8} ]} scale={{ value: 'Linear ',}} coord='polar' > <interval position="x*y" /> <axis field="x" formatter={v => v.toFixed(2)}/> : null } </chart>Copy the code

From the example above we see 2 points

  1. axisNeed to pass throughshowAxisThis variable controls whether or not to display, and if it is JSON, then two JSON descriptions are required
  2. formatterThere are custom formatting appeals, and JSON cannot hold methods

2. Stronger ability to expand

JSON requires a Runtime to process the JSON structure. If JSON needs to be extended, the Runtime needs to be upgraded synchronously. This brings huge cost in changing business scenarios, and JSX can be easily implemented by extending tag types

Example:

import { Custom } from './custom'; <chart data={[ {"category": 1, "value": 4}, {"category": 2, "value": 6}, {"category": 3, "value": 10}, {"category": 4, "value": 3}, {"category": 5, "value": 7}, {"category": 6, "value": 8} ]} scale={{ value: 'Linear ',}} coord='polar' > <interval position="x*y" /> <axis field="x" /> {/* Custom tag extension */} <Custom... /> </chart>Copy the code

JSX has a default rule that uses lowercase for built-in tags and uppercase for external references. If you specify a Custom interface (Component in React), you can expand indefinitely. However, there is a problem with this. That is, the generated structure can no longer be serialized, transported and stored, which we will discuss later.

3. More stable tree structure

Understanding this requires a deeper understanding of the structures JSX generates, which I’ll briefly mention for those interested in studying the JSX compilation rules

The structure tree returned by JSX is stable no matter how the external parameters change

Example:

<chart
  data={[
    {"category": 1, "value": 4},
    {"category": 2, "value": 6},
    {"category": 3, "value": 10},
    {"category": 4, "value": 3},
    {"category": 5, "value": 7},
    {"category": 6, "value": 8}
  ]}
  scale={{
    value: 'linear',
  }}
  coord='polar'
  >
  <interval position="x*y" />
  {
    showAxis ? <axis field="x" /> : null
  }
</chart>
Copy the code

For example, if showAxis is true and false, the generated structure objects are as follows. The structure of the two trees is the same and does not differ depending on the argument.

{
  type: "chart",
  data: [],
  coord: "polar",
  children: [
    { type: "interval", position: "x*y" },
    { type: "axis",  field: "x" }
  ]
}
Copy the code
{ type: "chart", data: [], coord: "polar", children: [ { type: "interval", position: "X *y"}, null, // tree nodes will still be null]}Copy the code

4. Complete structure description

JSX retains the structural nature of JSON, which API imperatives do not. Imperatives require the execution of the entire code to achieve a complete structure, and JSX can be easily converted to JSON through conversion functions. JSON is definitely the best form for future-oriented Nocode, Lowcode, and even smart scenarios, and JSON machine friendly.

5. Mature tools

Both Babel and TypeScript have full-fledged JSX compiler plugins that are easy to configure. See jsX-Transform for more information

6. Summary

JSX retains the characteristics of STRUCTURED description of JSON, but is more flexible and programmable than JSON, which is very important when we are faced with complex business scenarios. However, due to its flexibility, the structure of JSX cannot be serialized, transmitted and stored, which is also the limitation of JSX. However, this limitation can be encapsulated and solved by further domain solutions from the upper level

Jsonization under JSX

As mentioned earlier, JSON has very good machine-friendliness, especially for construction and intelligent scenarios, which require cross-terminal or even cross-platform transmission and storage. Therefore, JSX should be jsonized from the machine-friendliness perspective. As mentioned earlier, The serialization transport and storage problem is solved by the upper level solution, so how do we solve the jsonization problem

Let’s take the formatter of the example above

<chart data={[ {"category": 1, "value": 4}, {"category": 2, "value": 6}, {"category": 3, "value": 10}, {"category": 4, "value": 3}, {"category": 5, "value": 7}, {"category": 6, "value": 8} ]} scale={{ value: 'Linear ',}} coord='polar' > <interval position="x*y" /> <axis field="x" formatter={v => v.toFixed(2)} /> : null } </chart>Copy the code

This case, when we face to all the business scenario the formatter format is various, such as after the decimal point 0 – n, percentage, plus or minus, date format and so on, because we cannot be exhaustive, so through the function, but also because of using the function, this structure can not be serialized, This is also the reason we mentioned earlier that JSX cannot be serialized

But when we put the business scenario is limited to a particular field, the characteristics and demands of the scene can be enumerated, so when we face to a particular field, the format of the formatter is also likely to be enumerated, such as a scene point unity 2 digits, need percentage, date processing, etc. These detailed rules, This time we can define the type of the formatter for ‘toFixed’ | ‘percent’ | ‘date’, etc

Once enumerable, then we can express it as follows

<chart
  data={[
    {"category": 1, "value": 4},
    {"category": 2, "value": 6},
    {"category": 3, "value": 10},
    {"category": 4, "value": 3},
    {"category": 5, "value": 7},
    {"category": 6, "value": 8}
  ]}
  scale={{
    value: 'linear',
  }}
  coord='polar'
  >
  <interval position="x*y" />
  <customAxis visible={ true } field="x" formatter="toFixed" />
</chart>
Copy the code

This structure can be described in JSON below

{
  type: "chart",
  data: [],
  coord: "polar",
  children: [
    { type: "interval", position: "x*y" },
    { type: "customAxis",  field: "x", visible: true, formatter: 'toFixed' }
  ]
}
Copy the code

This JSON can be serialized completely, and this transformation is only a re-encapsulation of Axis in the code, which is also the ability we provide to the business so that the business can do the secondary encapsulation of the domain. The secondary encapsulation of the business can also bring convenience to the business.

Therefore, JSX can not only have a clear structure description, but also good programming ability and scalability, and through secondary encapsulation, we can also serialize JSON, so the form of JSX is undoubtedly the best choice at present.


Domain Solutions

Let’s talk about domain solutions. We’re looking at data visualization scenarios for the entire mobile end, and because of the versatility and flexibility, usability is often not enough. Again, using the Formatter we mentioned earlier, formatting can be very different for a specific domain. For example, financial stock and fund scenarios: The formatter need to format Numbers, not only need according to the number of positive, negative and zero to display a different color (commonly known as the red rose green fell flat color), and U.S. stocks color also need instead (green red fall), if the business in these uniform rules to repeated processing, the estimate is crazy, so you need to field solutions to solve these problems

Here again revealed the plot: by the way, in the near future, we will be in F2 and F6, mainly from the point of view of the ease of use, and bring more simple and easy to use the mobile terminal of the visualization solutions FCharts, let ordinary scenes using simple at the same time, also let field solutions become more convenient and easy to use, stay tuned.

The last

To sum up, we choose JSX because of its programmability, expansibility, complete structure description and mature matching. It is not only for programming friendliness and business complexity at present, but also for building and intelligent friendly JSON in the future, which is a good choice.

Finally, if you want to know more details, please welcome star to our GitHub and our official website

  • F2 lot: github.com/antvis/F2
  • F2.antv.vision f2.antv.vision
  • F6 lot: github.com/antvis/F6
  • F6 official website: F6.antv. vision