From d1e99fea0eff36fe4aa240330a8b81750a1a65d8 Mon Sep 17 00:00:00 2001 From: Zhizhi <119661535+Zhizhi-2986@users.noreply.github.com> Date: Fri, 10 Nov 2023 14:05:03 +0800 Subject: [PATCH] docs(Transform): Translate transform to En (#5759) * translate * translate * Translate others * fix: Detailed modification --- site/docs/manual/core/animation.en.md | 197 ++++++++++++++- site/docs/manual/core/animation.zh.md | 2 +- site/docs/manual/core/coordinate.en.md | 337 ++++++++++++++++++++++++- site/docs/manual/core/label.en.md | 240 +++++++++++++++++- site/docs/manual/core/layout.en.md | 19 +- site/docs/manual/core/layout.zh.md | 2 +- site/docs/manual/core/state.en.md | 90 ++++++- site/docs/manual/core/style.en.md | 161 +++++++++++- site/docs/manual/core/title.en.md | 41 ++- site/docs/manual/core/transform.en.md | 292 ++++++++++++++++++++- site/docs/manual/core/transform.zh.md | 6 +- 11 files changed, 1364 insertions(+), 23 deletions(-) diff --git a/site/docs/manual/core/animation.en.md b/site/docs/manual/core/animation.en.md index cd43ea7e03..357e5332e1 100644 --- a/site/docs/manual/core/animation.en.md +++ b/site/docs/manual/core/animation.en.md @@ -1,6 +1,197 @@ --- -title: Animation -order: 7 +title: 动画(Animate) +order: 6.8 --- - \ No newline at end of file +Animate in G2 is an important part of visualization and can improve the expressiveness of visualization. Animate can be declared at the level of mark: + +```js +({ + type: 'interval', + animate: { + enter: { + type: 'scaleInX', + duration: 100, + delay: 10, + }, + update: { + type: 'morphing', + }, + }, +}); +``` + +```js +// API +// First way +chart + .interval() + .animate('enter', { type: 'scaleInX', duration: 100, delay: 10 }) + .animate('update', { type: 'morphing' }); + +// Second way +chart.interval().animate({ + enter: { + type: 'scaleInX', + duration: 100, + delay: 10, + }, + update: { + type: 'morphing', + }, +}); +``` + +## Animate Properties + +Mark specifies animation properties through `mark.animate`, there are three parts of animation that can be specified: + +- **enter**- New graphics +- **update**- Updated graphics +- **exit**- deleted graphics + +Each part of the animation has the following properties: + +- **type** +- **duration** +- **delay** +- **easing** + +```js | ob +(() => { + const chart = new G2.Chart(); + + chart + .interval() + .data([ + { genre: 'Sports', sold: 275 }, + { genre: 'Strategy', sold: 115 }, + { genre: 'Action', sold: 120 }, + { genre: 'Shooter', sold: 350 }, + { genre: 'Other', sold: 150 }, + ]) + .encode('x', 'genre') + .encode('y', 'sold') + .encode('color', 'genre') + .animate('enter', { + type: 'scaleInY', // Specify the type of entry animation + duration: 1000, // Specify the execution time of the entrance animation + }); + + chart.render(); + + return chart.getContainer(); +})(); +``` + +## Animation coding + +Animation properties can be used as a channel in G2, and can also encode data. For example, in the gantt chart below, the appearance and duration of each bar are linearly related to the data. + +```js | ob +(() => { + const chart = new G2.Chart(); + + chart + .interval() + .coordinate({ transform: [{ type: 'transpose' }] }) + .data([ + { name: 'event planning', startTime: 1, endTime: 4 }, + { name: 'layout logistics', startTime: 3, endTime: 13 }, + { name: 'select vendors', startTime: 5, endTime: 8 }, + { name: 'hire venue', startTime: 9, endTime: 13 }, + { name: 'hire caterer', startTime: 10, endTime: 14 }, + { name: 'hire event decorators', startTime: 12, endTime: 17 }, + { name: 'rehearsal', startTime: 14, endTime: 16 }, + { name: 'event celebration', startTime: 17, endTime: 18 }, + ]) + .encode('x', 'name') + .encode('y', ['endTime', 'startTime']) + .encode('color', 'name') + .encode('enterDuration', (d) => d.endTime - d.startTime) // Calculate the duration and encode + .encode('enterDelay', 'startTime'); // Specify the time of occurrence and encode + + chart.render(); + + return chart.getContainer(); +})(); +``` + +## Group animation + +G2 also provides the StackEnter mark transform to implement group animation. This mark transform will first group graphics, and then stack their appearance time and duration in space to achieve the effect of appearing sequentially. + +```js | ob +(() => { + const chart = new G2.Chart(); + + chart + .interval() + .data([ + { type: 'Apple', year: '2001', value: 260 }, + { type: 'Orange', year: '2001', value: 100 }, + { type: 'Banana', year: '2001', value: 90 }, + { type: 'Apple', year: '2002', value: 210 }, + { type: 'Orange', year: '2002', value: 150 }, + { type: 'Banana', year: '2002', value: 30 }, + ]) + //Group by color and appear in order + .transform({ type: 'stackEnter', groupBy: 'color' }) + .encode('x', 'year') + .encode('y', 'value') + .encode('color', 'type') + .encode('series', 'type') + .encode('enterDuration', 1000); // The duration of each group is 1000 + + chart.render(); + + return chart.getContainer(); +})(); +``` + +## Keyframe Animation + +The animations above are all excessive animations and do not involve data updates. G2 also provides the ability to create keyframe animations. use `chart.timingKeyframe` to create a time container that holds a series of views and applies smooth transitions to related graphical elements within those views. The corresponding relationship is specified by two channels, **key** and **groupKey**. + +```js | ob +(async () => { + const data = await fetch( + 'https://gw.alipayobjects.com/os/antvdemo/assets/data/scatter.json', + ).then((res) => res.json()); + + const chart = new G2.Chart(); + + // Refer to the description of css animation + const keyframe = chart + .timingKeyframe() // Create container + .attr('iterationCount', 2) // Number of iterations + .attr('direction', 'alternate') // Direction + .attr('duration', 1000); // Duration + + keyframe + .interval() + .transform({ type: 'groupX', y: 'mean' }) + .data(data) + .encode('x', 'gender') + .encode('y', 'weight') + .encode('color', 'gender') + .encode('key', 'gender'); // Specify key + + keyframe + .point() + .data(data) + .encode('x', 'height') + .encode('y', 'weight') + .encode('color', 'gender') + .encode('shape', 'point') + .encode('groupKey', 'gender'); // Specify groupKey + + chart.render(); + + return chart.getContainer(); +})(); +``` + +## Time Series Animation + +**TimingSequence** is still under development, please stay tuned. diff --git a/site/docs/manual/core/animation.zh.md b/site/docs/manual/core/animation.zh.md index 56f5052480..07e51b7126 100644 --- a/site/docs/manual/core/animation.zh.md +++ b/site/docs/manual/core/animation.zh.md @@ -86,7 +86,7 @@ chart.interval().animate({ ## 动画编码 -在 G2 中动画属性也可以作为一种通道,也可以编码数据。比如下面甘特图中,每个条的出现和持续时间是和数据线性相关的。 +在 G2 中动画属性可以作为一种通道,也可以编码数据。比如下面甘特图中,每个条的出现和持续时间是和数据线性相关的。 ```js | ob (() => { diff --git a/site/docs/manual/core/coordinate.en.md b/site/docs/manual/core/coordinate.en.md index 68c04ffe27..ddd5ab1162 100644 --- a/site/docs/manual/core/coordinate.en.md +++ b/site/docs/manual/core/coordinate.en.md @@ -1,6 +1,337 @@ --- -title: Coordinate -order: 8 +title: 坐标系(Coordinate) +order: 6.5 --- - \ No newline at end of file +**The Coordinate System** in G2 will perform a series of point transform. In G2, the mark's position channels x and y will be mapped to the range [0,1] through a scale mapping, after that, the coordinate system is used to transform points into canvas coordinates, thereby changing the spatial display of the mark. + +The coordinate system be configured at the level of view: + +```js +({ + type: 'view', + coordinate: { type: 'polar' }, +}); +``` + +```js +// API +chart.coordinate({ type: 'polar' }); +``` + +It can also be configured at the level of mark: + +```js +({ + type: 'interval', + coordinate: { type: 'polar' }, +}); +``` + +```js +// API +chart.interval().coordinate({ type: 'polar' }); +``` + +## View Coordinate System + +Each view can only have one coordinate system. In addition to its own attributes, the coordinate system also contains a series of **Coordinate Transform**。 + +```js +({ + type: 'polar', // type + innerRadius: 0.6, // its own properties + outerRadius: 0.8, + transform: [{ type: 'transpose' }], // Coordinate transform +}); +``` + +## Mark Coordinate System + +The coordinate system of the level of mark has bubbling properties. The coordinate system of the level of mark will be merged with the coordinate system of the view, and the coordinate system of the first mark has the highest priority. + +```js +chart.coordinate({ type: 'theta' }); +chart.line().coordinate({ type: 'polar' }); +chart.area().coordinate({ type: 'radial' }); +``` + +Equivalent to the following situation: + +```js +chart.coordinate({ type: 'polar' }); +chart.line(); +chart.area(): +``` + +This feature is conducive to encapsulation and coordinate-related composite mark, such as pie charts: + +```js | ob +(() => { + function Pie({ encode = {}, ...rest } = {}) { + const { value, ...restEncode } = encode; + return { + ...rest, + type: 'interval', + coordinate: { type: 'theta' }, // Encapsulation coordinate system + transform: [{ type: 'stackY' }], + encode: { + ...restEncode, + y: value, + }, + }; + } + + const chart = new G2.Chart(); + + chart.options({ + type: Pie, // Use this compound mark + data: [ + { genre: 'Sports', sold: 275 }, + { genre: 'Strategy', sold: 115 }, + { genre: 'Action', sold: 120 }, + { genre: 'Shooter', sold: 350 }, + { genre: 'Other', sold: 150 }, + ], + encode: { value: 'sold', color: 'genre' }, + }); + + chart.render(); + + return chart.getContainer(); +})(); +``` + +## Common Coordinate Systems + +The default coordinate system is the Cartesian coordinate system. In addition, there is also a kind of coordinate system that transforms charts to polar coordinate systems and is used to draw a series of "circle" charts. This type of coordinate system is called **Radial Coordinate**。 + +### Polar + +For example, you can use interval mark and polar coordinate transform to draw rose charts. + +```js | ob +(() => { + const chart = new G2.Chart(); + + chart + .interval() + .coordinate({ type: 'polar' }) + .data([ + { genre: 'Sports', sold: 275 }, + { genre: 'Strategy', sold: 115 }, + { genre: 'Action', sold: 120 }, + { genre: 'Shooter', sold: 350 }, + { genre: 'Other', sold: 150 }, + ]) + .encode('x', 'genre') + .encode('y', 'sold') + .encode('color', 'genre') + .axis('y', false); + + chart.render(); + + return chart.getContainer(); +})(); +``` + +### Theta + +You can also use interval mark and theta coordinate system to draw pie charts. + +```js | ob +(() => { + const chart = new G2.Chart(); + + chart + .interval() + .coordinate({ type: 'theta' }) + .transform({ type: 'stackY' }) + .data([ + { genre: 'Sports', sold: 275 }, + { genre: 'Strategy', sold: 115 }, + { genre: 'Action', sold: 120 }, + { genre: 'Shooter', sold: 350 }, + { genre: 'Other', sold: 150 }, + ]) + .encode('y', 'sold') + .encode('color', 'genre'); + + chart.render(); + + return chart.getContainer(); +})(); +``` + +### Radial + +You can also use interval mark and radial coordinate systems to draw radial charts. + +```js | ob +(() => { + const chart = new G2.Chart(); + + chart + .interval() + .coordinate({ type: 'radial', endAngle: Math.PI }) + .data([ + { genre: 'Strategy', sold: 115 }, + { genre: 'Action', sold: 120 }, + { genre: 'Other', sold: 150 }, + { genre: 'Sports', sold: 275 }, + { genre: 'Shooter', sold: 350 }, + ]) + .encode('x', 'genre') + .encode('y', 'sold') + .encode('color', 'genre') + .axis('y', false) + .legend('color', false) + .axis('x', { title: null }); + + chart.render(); + + return chart.getContainer(); +})(); +``` + +### Parallel + +In addition to the previous relatively basic coordinate transform, there are also some slightly more complex coordinate transform, such as parallel coordinate system. + +```js | ob +(() => { + const axis = { + zIndex: 1, + titlePosition: 'right', + line: true, + labelStroke: '#fff', + labelStrokeWidth: 5, + labelFontSize: 10, + labelStrokeLineJoin: 'round', + titleStroke: '#fff', + titleFontSize: 10, + titleStrokeWidth: 5, + titleStrokeLineJoin: 'round', + titleTransform: 'translate(-50%, 0) rotate(-90)', + lineStroke: 'black', + tickStroke: 'black', + lineStrokeWidth: 1, + }; + + const chart = new G2.Chart(); + + chart + .line() + .data({ + type: 'fetch', + value: 'https://assets.antv.antgroup.com/g2/cars3.json', + }) + .coordinate({ type: 'parallel' }) // Specify parallel coordinate transform + //Specify the data dimension of concern + //Each data dimension corresponds to an axis + .encode('position', [ + 'economy (mpg)', + 'cylinders', + 'displacement (cc)', + 'power (hp)', + 'weight (lb)', + '0-60 mph (s)', + 'year', + ]) + .encode('color', 'weight (lb)') + .style('strokeWidth', 1.5) + .style('strokeOpacity', 0.4) + .scale('color', { + type: 'sequential', + palette: 'brBG', + offset: (t) => 1 - t, + }) + .legend({ + color: { length: 400 }, + }) + .axis('position', axis) + .axis('position1', axis) + .axis('position2', axis) + .axis('position3', axis) + .axis('position4', axis) + .axis('position5', axis) + .axis('position6', axis) + .axis('position7', axis) + .interaction('tooltip', { series: false }); + + chart.render(); + + return chart.getContainer(); +})(); +``` + +## Coordinate Transform + +The above coordinate system can be used in combination with the coordinate transform. + +### Transpose + +One of the more commonly used transform is transpose, which is mainly used to change the direction of the chart. For example, draw horizontal bar charts. + +```js | ob +(() => { + const chart = new G2.Chart(); + + chart + .interval() + .coordinate({ transform: [{ type: 'transpose' }] }) // Appoint transpose + .data([ + { genre: 'Sports', sold: 275 }, + { genre: 'Strategy', sold: 115 }, + { genre: 'Action', sold: 120 }, + { genre: 'Shooter', sold: 350 }, + { genre: 'Other', sold: 150 }, + ]) + .encode('x', 'genre') + .encode('y', 'sold'); + + chart.render(); + + return chart.getContainer(); +})(); +``` + +### Fisheye + +There is also a fisheye coordinate transform, which is used to set the focus of the chart. Here is how to use it. + +```js | ob +(() => { + const chart = new G2.Chart(); + + chart + .point() + .data({ + type: 'fetch', + value: 'https://gw.alipayobjects.com/os/antvdemo/assets/data/bubble.json', + }) + .encode('x', 'GDP') + .encode('y', 'LifeExpectancy') + .encode('size', 'Population') + .encode('color', 'continent') + .encode('shape', 'point') + .scale('size', { type: 'log', range: [4, 20] }) + .axis('x', { labelFormatter: '~s' }) + .style('fillOpacity', 0.3) + .style('lineWidth', 1) + .legend(false) + .interaction('fisheye'); + + chart.render(); + + return chart.getContainer(); +})(); +``` + +## 3D Coordinate System + +At present, we only support `cartesian3D` coordinate system: + +```ts +chart.coordinate({ type: 'cartesian3D' }); +``` diff --git a/site/docs/manual/core/label.en.md b/site/docs/manual/core/label.en.md index 32e14476f1..33b79c7451 100644 --- a/site/docs/manual/core/label.en.md +++ b/site/docs/manual/core/label.en.md @@ -1,6 +1,240 @@ --- -title: Label -order: 10 +title: 数据标签(Label) +order: 6.95 --- - +**Label** in G2 is one of the means to annotate charts. Multiple labels can be added to a mark: + +```js +({ + type: 'interval', + labels: [ + { + text: 'genre', // Specify the bound field + dy: -15, // Specify style + }, + { + text: 'sold', // Specify the bound field + fill: '#fff', // Specify style + dy: 5, + }, + ], +}); +``` + +```js +// API method +// First way +chart + .interval() + .label({ + text: 'genre', // Specify the bound field + dy: -15, //Specify style + }) + .label({ + text: 'sold', // Specify the bound field + fill: '#fff', // Specify style + dy: 5, + }); + +// Second way +chart.interval().label([ + { + text: 'genre', // Specify the bound field + dy: -15, // Specify style + }, + { + text: 'sold', // Specify the bound field + fill: '#fff', // Specify style + dy: 5, + }, +]); +``` + +At the level of View, you can declare label transform through `labelTransform`: + +```js +({ + type: 'view', + labelTransform: [{ type: 'overlapHide' }, { type: 'contrastReverse' }], +}); +``` + +```js +// API method +// First way +chart + .labelTransform({ type: 'overlapHide' }) + .labelTransform({ type: 'contrastReverse' }); + +// Second way +chart.labelTransform([{ type: 'overlapHide' }, { type: 'contrastReverse' }]); +``` + +## Mark Label + +Each mark can have multiple labels. The configuration of a label is roughly as follows: + +```js +({ + type: 'interval', + labels: [ + { + text: 'name', // Bound field or a constant string + dy: -2, // @antv/g supported styles + fill: 'red', // @antv/g supported styles + selector: 'last', // Selector + transform: [], // Label transform + }, + ], +}); +``` + +Here's a simple example: + +```js | ob +(() => { + const chart = new G2.Chart(); + + chart + .interval() + .data([ + { genre: 'Sports', sold: 275 }, + { genre: 'Strategy', sold: 115 }, + { genre: 'Action', sold: 120 }, + { genre: 'Shooter', sold: 350 }, + { genre: 'Other', sold: 150 }, + ]) + .encode('x', 'genre') + .encode('y', 'sold') + // Declare the first label + .label({ + text: 'genre', // Specify the bound field + style: { + dy: -15, // Specify style + }, + }) + // Declare the second label + .label({ + text: 'sold', // Specify the bound field + style: { + fill: '#fff', // Specify style + dy: 5, + }, + }); + + chart.render(); + + return chart.getContainer(); +})(); +``` + +## Selector + +For the mark of a graph corresponding to multiple data items, we can select the mark that needs to be retained through `selector`. Currently supported values ​​are as follows: + +- **first** - the first one +- **last** - the last one +- **function** - custom selector + +```js | ob +(() => { + const chart = new G2.Chart(); + + chart + .line() + .data({ + type: 'fetch', + value: 'https://assets.antv.antgroup.com/g2/indices.json', + }) + .transform({ type: 'normalizeY', basis: 'first', groupBy: 'color' }) + .encode('x', (d) => new Date(d.Date)) + .encode('y', 'Close') + .encode('color', 'Symbol') + .axis('y', { title: '↑ Change in price (%)' }) + .label({ + text: 'Symbol', + selector: 'last', // Select the last one + style: { + fontSize: 10, + }, + }); + chart.render(); + + return chart.getContainer(); +})(); +``` + +## Label Transform + +When the display of labels does not meet expectations, such as overlapping or unclear colors, we can use **Label Transform** to optimize label display. + +It can be found that in the example below, the labels corresponding to times such as 2004 have overlapped. + +```js | ob +(() => { + const chart = new G2.Chart(); + + chart + .line() + .data({ + type: 'fetch', + value: + 'https://gw.alipayobjects.com/os/bmw-prod/cb99c4ab-e0a3-4c76-9586-fe7fa2ff1a8c.csv', + }) + .transform({ type: 'groupX', y: 'mean' }) + .encode('x', (d) => new Date(d.date).getFullYear()) + .encode('y', 'price') + .encode('color', 'symbol') + .label({ + text: 'price', + fontSize: 10, + }) + .tooltip({ channel: 'y', valueFormatter: '.1f' }); + + chart.render(); + + return chart.getContainer(); +})(); +``` + +At this time, we can set the label transform for the corresponding label: overlapDodgeY, which is used to prevent the labels from overlapping in the y direction. + +```js | ob +(() => { + const chart = new G2.Chart(); + + chart + .line() + .data({ + type: 'fetch', + value: + 'https://gw.alipayobjects.com/os/bmw-prod/cb99c4ab-e0a3-4c76-9586-fe7fa2ff1a8c.csv', + }) + .transform({ type: 'groupX', y: 'mean' }) + .encode('x', (d) => new Date(d.date).getFullYear()) + .encode('y', 'price') + .encode('color', 'symbol') + .label({ + text: 'price', + transform: [{ type: 'overlapDodgeY' }], // Appoint labelTransform + fontSize: 10, + }) + .tooltip({ channel: 'y', valueFormatter: '.1f' }); + + chart.render(); + + return chart.getContainer(); +})(); +``` + +## View Level Label Transform + +Label transform can also be declared at the level of view to process labels for the entire view. + +```js +({ + type: 'view', + labelTransform: [], +}); +``` diff --git a/site/docs/manual/core/layout.en.md b/site/docs/manual/core/layout.en.md index 39410edd7e..0411afc3ad 100644 --- a/site/docs/manual/core/layout.en.md +++ b/site/docs/manual/core/layout.en.md @@ -1,6 +1,21 @@ --- -title: Layout +title: 布局(Layout) order: 6.1 --- - +**Layout** in G2 is used to specify some parameters of layout methods marked by specific layout functions, such as Snakey, WordCloud, ForceGraph, etc. + +```js +({ + type: 'sankey', + layout: { + nodeAlign: 'center', + nodePadding: 0.03, + }, +}); +``` + +```js +// API +chart.sankey().layout({ nodeAlign: 'center', nodePadding: 0.03 }); +``` diff --git a/site/docs/manual/core/layout.zh.md b/site/docs/manual/core/layout.zh.md index 00b58b39e9..d734a4d11a 100644 --- a/site/docs/manual/core/layout.zh.md +++ b/site/docs/manual/core/layout.zh.md @@ -3,7 +3,7 @@ title: 布局(Layout) order: 6.1 --- -G2 中**布局(Layout)** 用于指定是一些有特定布局函数的标记的布局方法的参数,比如 Snakey, WordCloud, ForceGraph 等。 +G2 中**布局(Layout)** 用于指定一些有特定布局函数标记的布局方法的参数,比如 Snakey, WordCloud, ForceGraph 等。 ```js ({ diff --git a/site/docs/manual/core/state.en.md b/site/docs/manual/core/state.en.md index af4356138c..3e42b6d36e 100644 --- a/site/docs/manual/core/state.en.md +++ b/site/docs/manual/core/state.en.md @@ -1,6 +1,92 @@ --- -title: State +title: 状态(State) order: 6.9 --- - \ No newline at end of file +State in G2 is mainly used to control the state style of mark. These states will be interactively triggered and the attributes are style attributes supported by @antv/g. + +```js +({ + type: 'interval', + state: { + active: { fill: 'red', stroke: 2 }, + inactive: { fill: '#aaa' }, + }, +}); +``` + +```js +// API +// First way +chart + .interval() + .state('active', { fill: 'red', stroke: 2 }) + .state('inactive', { fill: '#aaa' }); + +// Second way +chart.interval().state({ + active: { fill: 'red', stroke: 2 }, + inactive: { fill: '#aaa' }, +}); +``` + +## Built-in States + +There are currently 4 built-in states: + +- active - the style when highlighted +- inactive - style when not highlighted +- selected - style when selected +- unselected - style when not selected + +## Highlighted States + +```js | ob +(() => { + const chart = new G2.Chart(); + + chart + .interval() + .data({ + type: 'fetch', + value: + 'https://gw.alipayobjects.com/os/bmw-prod/fb9db6b7-23a5-4c23-bbef-c54a55fee580.csv', + }) + .encode('x', 'letter') + .encode('y', 'frequency') + .axis('y', { labelFormatter: '.0%' }) + .state('active', { fill: 'red' }) + .state('inactive', { fill: '#aaa' }) + .interaction('elementHighlight'); // Set up highlight interaction + + chart.render(); + + return chart.getContainer(); +})(); +``` + +## Selected States + +```js | ob +(() => { + const chart = new G2.Chart(); + + chart + .interval() + .data({ + type: 'fetch', + value: + 'https://gw.alipayobjects.com/os/bmw-prod/fb9db6b7-23a5-4c23-bbef-c54a55fee580.csv', + }) + .encode('x', 'letter') + .encode('y', 'frequency') + .axis('y', { labelFormatter: '.0%' }) + .state('selected', { fill: 'red' }) + .state('unselected', { fill: '#aaa' }) + .interaction('elementSelect'); // Set up selection interaction + + chart.render(); + + return chart.getContainer(); +})(); +``` diff --git a/site/docs/manual/core/style.en.md b/site/docs/manual/core/style.en.md index 14a564c71b..f17c3588ac 100644 --- a/site/docs/manual/core/style.en.md +++ b/site/docs/manual/core/style.en.md @@ -1,6 +1,163 @@ --- -title: Style +title: 样式(Style) order: 6.6 --- - +Style in G2 is mainly used to control the visual style of mark and view. Supported styles refer to @antv/g supported styles. + +Mark can set its own style or the style of the view: + +```js +({ + type: 'interval', + style: { + // own style + stroke: 'black', + strokeWidth: 2, + }, + viewStyle: { + // View style + viewFill: 'red', + contentFill: 'yellow', + }, +}); +``` + +```js +// API +// First way +chart + .interval() + .style('stroke', 'black') + .style('strokeWidth', 2) + .viewStyle('viewFill', 'red') + .viewStyle('contentFill', 'yellow'); + +// Second way +chart + .interval() + .style({ + stroke: 'black', + strokeWidth: 2, + }) + .viewStyle({ + viewFill: 'red', + contentFill: 'yellow', + }); +``` + +View can set its own style: + +```js +({ + type: 'view', + style: { + viewFill: 'red', + contentFill: 'yellow', + }, +}); +``` + +```js +// API +// First way +chart.style('viewFill', 'red').style('contentFill', 'yellow'); + +// Second way +chart.style({ + viewFill: 'red', + contentFill: 'yellow', +}); +``` + +## Mark Style + +In addition to `mark.encode`, the visual properties of the mark can also be set through `mark.style`. There are two main differences between the two: + +- The channel set by `mark.encode` will be a bit special, either unique to the mark, such as the src channel of image; or it has some special logic, such as the x channel that affects the generation of the x-direction coordinate axis. +- `mark.encode` is more inclined to set up channels related to data, but `mark.style` prefers to set up channels that have nothing to do with data. Although `mark.style` also supports callbacks to set up data-driven channels. + +```js | ob +(() => { + const chart = new G2.Chart(); + + chart + .interval() + .data({ + type: 'fetch', + value: + 'https://gw.alipayobjects.com/os/bmw-prod/fb9db6b7-23a5-4c23-bbef-c54a55fee580.csv', + }) + .encode('x', 'letter') + .encode('y', 'frequency') + .style('fill', 'steelblue') // Set data-independent channels + .style('strokeWidth', (d) => (d.frequency > 0.1 ? 2 : 1)) // Set data-related channels + .style('stroke', (d) => (d.frequency > 0.1 ? 'red' : 'black')) + .axis('y', { labelFormatter: '.0%' }); + + chart.render(); + + return chart.getContainer(); +})(); +``` + +## View Style + +The styles of each area can be set in the form of `${name}${Style}`, among them, Style is all styles supported by the rectangle of G, such as `fill`,`stroke`,etc. Please note that the first letter should be capitalized to form camel case. + +- **view${Style}**- Set the style of the view area +- **plot${Style}**- Set the style of the drawing area +- **main${Style}**- Set the style of the main area +- **content${Style}**- Set styles of the content areas + +For example, color each area in the picture below: + +```js | ob +(() => { + const chart = new G2.Chart(); + + chart.options({ + type: 'view', + height: 280, + inset: 10, + marginTop: 30, + marginLeft: 40, + marginBottom: 10, + marginRight: 20, + style: { + // Set the view style + viewFill: '#4e79a7', + plotFill: '#f28e2c', + mainFill: '#e15759', + contentFill: '#76b7b2', + }, + children: [ + { + type: 'point', + data: { + type: 'fetch', + value: 'https://assets.antv.antgroup.com/g2/commits.json', + }, + encode: { + x: (d) => new Date(d.time).getUTCHours(), + y: (d) => new Date(d.time).getUTCDay(), + size: 'count', + shape: 'point', + }, + transform: [{ type: 'group', size: 'sum' }, { type: 'sortY' }], + scale: { y: { type: 'point' } }, + style: { shape: 'point', fill: '#59a14f' }, + axis: { + x: { title: 'time (hours)', tickCount: 24 }, + y: { title: 'time (day)', grid: true }, + }, + legend: false, + }, + ], + }); + + chart.render(); + + return chart.getContainer(); +})(); +``` diff --git a/site/docs/manual/core/title.en.md b/site/docs/manual/core/title.en.md index 808924c875..aebb3d658a 100644 --- a/site/docs/manual/core/title.en.md +++ b/site/docs/manual/core/title.en.md @@ -1,4 +1,43 @@ --- -title: Title +title: 标题(Title) order: 7 --- + +Title in G2 is used to specify the title of the chart. + +Titles can be configured at the level of mark: + +```js +({ + type: 'interval', + title: { + title: 'hello', + subtitle: 'world', + }, +}); +``` + +```js +// API +chart.interval().title({ + title: 'hello', + subtitle: 'world', +}); +``` + +Titles can also be configured at the level of view: + +```js +({ + type: 'view', + title: { + title: 'hello', + subtitle: 'world', + }, +}); +``` + +```js +// API +chart.title({ title: 'hello', subtitle: 'world' }); +``` diff --git a/site/docs/manual/core/transform.en.md b/site/docs/manual/core/transform.en.md index f04d71b875..f371bc325c 100644 --- a/site/docs/manual/core/transform.en.md +++ b/site/docs/manual/core/transform.en.md @@ -1,6 +1,294 @@ --- -title: Transform +title: 转换(Transform) order: 6 --- - \ No newline at end of file +**The Mark Transform** in G2 offers a convenient method for transforming data and mark options, mainly used for analyzing data. The core of mark transform, which **filters, modifies, aggregates and generates** new channel values. + +Transform is an array, executed in the order when they are declared. It can be configured at the level of mark: + +```js +({ + type: 'interval', + transform: [{ type: 'stackY' }, { type: 'sortX' }], +}); +``` + +```js +// API +// First way +chart.interval().transform({ type: 'stackY' }).transform({ type: 'sortX' }); + +// Second way +chart.interval().transform([{ type: 'stackY' }, { type: 'sortX' }]); +``` + +Transform can also configure the level of view: + +```js +({ + type: 'view', + transform: [{ type: 'stackY' }, { type: 'sortX' }], +}); +``` + +```js +// API +// First way +chart.transform({ type: 'stackY' }).transform({ type: 'sortX' }); + +// Second way +chart.transform([{ type: 'stackY' }, { type: 'sortX' }]); +``` + +## Mark Transform + +Mark transform will modify the data bound to each channel, thereby changing the display form of the chart. For example, StackY transform stacks the column data bound to bar graph y and y1 channels: + +```js | ob +(() => { + const chart = new G2.Chart(); + + chart + .interval() + .data([ + { city: 'London', month: 'Jan.', rainfall: 18.9 }, + { city: 'London', month: 'Feb.', rainfall: 28.8 }, + { city: 'London', month: 'Mar.', rainfall: 39.3 }, + { city: 'London', month: 'Apr.', rainfall: 81.4 }, + { city: 'London', month: 'May', rainfall: 47 }, + { city: 'London', month: 'Jun.', rainfall: 20.3 }, + { city: 'London', month: 'Jul.', rainfall: 24 }, + { city: 'London', month: 'Aug.', rainfall: 35.6 }, + { city: 'Berlin', month: 'Jan.', rainfall: 12.4 }, + { city: 'Berlin', month: 'Feb.', rainfall: 23.2 }, + { city: 'Berlin', month: 'Mar.', rainfall: 34.5 }, + { city: 'Berlin', month: 'Apr.', rainfall: 99.7 }, + { city: 'Berlin', month: 'May', rainfall: 52.6 }, + { city: 'Berlin', month: 'Jun.', rainfall: 35.5 }, + { city: 'Berlin', month: 'Jul.', rainfall: 37.4 }, + { city: 'Berlin', month: 'Aug.', rainfall: 42.4 }, + ]) + .encode('x', 'month') + .encode('y', 'rainfall') + .encode('color', 'city') + .transform({ type: 'stackY' }); + + chart.render(); + + return chart.getContainer(); +})(); +``` + +## View Transform + +Transform declared on the view will be passed on to the mark declared in `children`. Set if it is not transformed, otherwise, it has no effect. For example, the following stacked area chart with transform: + +```js | ob +(() => { + const chart = new G2.Chart(); + + chart + .data([ + { city: 'London', month: 'Jan.', rainfall: 18.9 }, + { city: 'London', month: 'Feb.', rainfall: 28.8 }, + { city: 'London', month: 'Mar.', rainfall: 39.3 }, + { city: 'London', month: 'Apr.', rainfall: 81.4 }, + { city: 'London', month: 'May', rainfall: 47 }, + { city: 'London', month: 'Jun.', rainfall: 20.3 }, + { city: 'London', month: 'Jul.', rainfall: 24 }, + { city: 'London', month: 'Aug.', rainfall: 35.6 }, + { city: 'Berlin', month: 'Jan.', rainfall: 12.4 }, + { city: 'Berlin', month: 'Feb.', rainfall: 23.2 }, + { city: 'Berlin', month: 'Mar.', rainfall: 34.5 }, + { city: 'Berlin', month: 'Apr.', rainfall: 99.7 }, + { city: 'Berlin', month: 'May', rainfall: 52.6 }, + { city: 'Berlin', month: 'Jun.', rainfall: 35.5 }, + { city: 'Berlin', month: 'Jul.', rainfall: 37.4 }, + { city: 'Berlin', month: 'Aug.', rainfall: 42.4 }, + ]) + .encode('x', 'month') + .encode('y', 'rainfall') + .encode('color', 'city') + .transform({ type: 'stackY' }); // Transform of the level of view + + chart.area().style('fillOpacity', 0.5); + + chart.line().style('strokeWidth', 2).tooltip(false); + + chart.render(); + + return chart.getContainer(); +})(); +``` + +## Common Transform + +There are generally two common transform functions: + +- Prevent overlap +- Data aggregation + +### Prevent overlap + +One function of transform is to prevent overlap. For example, the bars in the following data bar chart overlap. + +```js | ob +(() => { + const chart = new G2.Chart(); + + chart + .interval() + .data([ + { city: 'London', month: 'Jan.', rainfall: 18.9 }, + { city: 'London', month: 'Feb.', rainfall: 28.8 }, + { city: 'London', month: 'Mar.', rainfall: 39.3 }, + { city: 'London', month: 'Apr.', rainfall: 81.4 }, + { city: 'London', month: 'May', rainfall: 47 }, + { city: 'London', month: 'Jun.', rainfall: 20.3 }, + { city: 'London', month: 'Jul.', rainfall: 24 }, + { city: 'London', month: 'Aug.', rainfall: 35.6 }, + { city: 'Berlin', month: 'Jan.', rainfall: 12.4 }, + { city: 'Berlin', month: 'Feb.', rainfall: 23.2 }, + { city: 'Berlin', month: 'Mar.', rainfall: 34.5 }, + { city: 'Berlin', month: 'Apr.', rainfall: 99.7 }, + { city: 'Berlin', month: 'May', rainfall: 52.6 }, + { city: 'Berlin', month: 'Jun.', rainfall: 35.5 }, + { city: 'Berlin', month: 'Jul.', rainfall: 37.4 }, + { city: 'Berlin', month: 'Aug.', rainfall: 42.4 }, + ]) + .encode('x', 'month') + .encode('y', 'rainfall') + .encode('color', 'city'); + + chart.render(); + + return chart.getContainer(); +})(); +``` + +At this time, you can declare a DodgeX to draw a grouped bar chart: + +```js | ob +(() => { + const chart = new G2.Chart(); + + chart + .interval() + .data([ + { city: 'London', month: 'Jan.', rainfall: 18.9 }, + { city: 'London', month: 'Feb.', rainfall: 28.8 }, + { city: 'London', month: 'Mar.', rainfall: 39.3 }, + { city: 'London', month: 'Apr.', rainfall: 81.4 }, + { city: 'London', month: 'May', rainfall: 47 }, + { city: 'London', month: 'Jun.', rainfall: 20.3 }, + { city: 'London', month: 'Jul.', rainfall: 24 }, + { city: 'London', month: 'Aug.', rainfall: 35.6 }, + { city: 'Berlin', month: 'Jan.', rainfall: 12.4 }, + { city: 'Berlin', month: 'Feb.', rainfall: 23.2 }, + { city: 'Berlin', month: 'Mar.', rainfall: 34.5 }, + { city: 'Berlin', month: 'Apr.', rainfall: 99.7 }, + { city: 'Berlin', month: 'May', rainfall: 52.6 }, + { city: 'Berlin', month: 'Jun.', rainfall: 35.5 }, + { city: 'Berlin', month: 'Jul.', rainfall: 37.4 }, + { city: 'Berlin', month: 'Aug.', rainfall: 42.4 }, + ]) + .encode('x', 'month') + .encode('y', 'rainfall') + .encode('color', 'city') + .transform({ type: 'dodgeX' }); // Declare transform + + chart.render(); + + return chart.getContainer(); +})(); +``` + +This is actually one of the functions of mark transform: **Prevent overlap**. In addition to DodgeX, there are also transform such as StackY and JitterX that can be used to prevent overlap. + +### Data aggregation + +In addition to preventing overlap, there is also a type of mark transform mainly used for data aggregation: such as Bin and Group. Different from traditional data aggregation, mark aggregation occurs in drawing, not before drawing. This eliminates the need for us to manipulate abstract raw data, but directly manipulate channel values. This greatly improves our efficiency in exploring data. + +First, let's draw a scatterplot as follows, showing the correlation between penguin culmen_depth_mm and culmen_length_mm. + +```js | ob +(() => { + const chart = new G2.Chart(); + + chart + .point() + .data({ + type: 'fetch', + value: 'https://assets.antv.antgroup.com/g2/penguins.json', + transform: [ + { type: 'filter', callback: (d) => d.culmen_depth_mm !== null }, + ], + }) + .encode('x', (d) => +d.culmen_depth_mm) + .encode('y', (d) => +d.culmen_length_mm); + + chart.render(); + + return chart.getContainer(); +})(); +``` + +At this time, if you want to see the distribution of penguin culmen_depth_mm, you can use bin to binning the data. + +```js | ob +(() => { + const chart = new G2.Chart(); + + chart + .rect() + .data({ + type: 'fetch', + value: 'https://assets.antv.antgroup.com/g2/penguins.json', + transform: [ + { type: 'filter', callback: (d) => d.culmen_depth_mm !== null }, + ], + }) + .encode('x', (d) => +d.culmen_depth_mm) + .transform({ + type: 'binX', // Bin the x channel value + y: 'count', // Generate the y channel and select the count reducer to count the total number of each box + }) + .style('insetLeft', 1); + + chart.render(); + + return chart.getContainer(); +})(); +``` + +Bin is mainly used to aggregate numerical data, and Group is mainly used for discrete data. + +## Multiple Transform + +We can also declare multiple transform at the same time. For example, in the penguin example above, if we consider one more data dimension: the gender of the penguin, we can declare Bin and StackY transform continuously. + +```js | ob +(() => { + const chart = new G2.Chart(); + + chart + .rect() + .data({ + type: 'fetch', + value: 'https://assets.antv.antgroup.com/g2/penguins.json', + transform: [ + { type: 'filter', callback: (d) => d.culmen_depth_mm !== null }, + ], + }) + .encode('x', (d) => +d.culmen_depth_mm) + .encode('color', 'sex') + .transform({ type: 'binX', y: 'count' }) // 声明 bin 转换 + .transform({ type: 'stackY', orderBy: 'sum', reverse: true }) // 声明 stack 转换 + .style('insetLeft', 1); + + chart.render(); + + return chart.getContainer(); +})(); +``` diff --git a/site/docs/manual/core/transform.zh.md b/site/docs/manual/core/transform.zh.md index 1a40d67f6e..9aee7027f4 100644 --- a/site/docs/manual/core/transform.zh.md +++ b/site/docs/manual/core/transform.zh.md @@ -43,7 +43,7 @@ chart.transform([{ type: 'stackY' }, { type: 'sortX' }]); ## 标记转换 -标记转换会去修改每个通道绑定的数据,从而改变图表的展示形式。比如 StackY 转换堆叠了条新图 y 和 y1 通道绑定的列数据: +标记转换会去修改每个通道绑定的数据,从而改变图表的展示形式。比如 StackY 转换堆叠了条形图 y 和 y1 通道绑定的列数据: ```js | ob (() => { @@ -82,7 +82,7 @@ chart.transform([{ type: 'stackY' }, { type: 'sortX' }]); ## 视图转换 -在视图上声明的转换会传递给 `children` 声明的标记。如果该标记没有转换就设置,否则没有影响。比如下面这个带有变的堆叠面积图: +在视图上声明的转换会传递给 `children` 声明的标记。如果该标记没有转换就设置,否则没有影响。比如下面这个带有转换的堆叠面积图: ```js | ob (() => { @@ -131,7 +131,7 @@ chart.transform([{ type: 'stackY' }, { type: 'sortX' }]); ### 防止重叠 -转换的一个作用是防止重叠。比如如下的数据绘制条形图中的条就重叠了。 +转换的一个作用是防止重叠。比如如下的数据绘制的条形图中的条就重叠了。 ```js | ob (() => {