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
axis
Need to pass throughshowAxis
This variable controls whether or not to display, and if it is JSON, then two JSON descriptions are requiredformatter
There 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