数据绑定chart和子标记的数据会互相干扰 #4710
Stephenzcc posted onGitHub
官方例子的https://g2.antv.antgroup.com/zh/examples/general/dual#line-bar
如果把其中的interval标记的data更改为下面这种形式,按照官方的定义,line会使用chart的数据,而interval会使用自己的数据
chart
.interval()
.data([
{ time: '10:10', call: 4, waiting: 2, people: 2 },
{ time: '10:15', call: 2, waiting: 6, people: 3 },
{ time: '10:30', call: 5, waiting: 2, people: 3 },
])
.encode('x', 'time')
.encode('y', 'waiting')
.axis('y', { titleFill: '#5B8FF9', title: 'Waiting' });
但实际情况是他们会互相干扰
这个可以理解为interval的x轴和line的x轴总长度一样导致的错误吗
还有这个例子https://g2.antv.antgroup.com/examples/annotation/annotation/#line-range
把其中的point改成interval也会出问题
第一个问题是,interval 和 line 默认推断的 x 比例尺 domain 不符合预期。有两种解决办法可以达到以下的效果:
第一种显示指定 x 比例尺的 domain。
import { Chart } from '@antv/g2';
const data = [
{ time: '10:10', call: 4, waiting: 2, people: 2 },
{ time: '10:15', call: 2, waiting: 6, people: 3 },
{ time: '10:20', call: 13, waiting: 2, people: 5 },
{ time: '10:25', call: 9, waiting: 9, people: 1 },
{ time: '10:30', call: 5, waiting: 2, people: 3 },
{ time: '10:35', call: 8, waiting: 2, people: 1 },
{ time: '10:40', call: 13, waiting: 1, people: 2 },
];
const chart = new Chart({
container: 'container',
autoFit: true,
});
// 显示指定 x 比例尺的定义域
chart.data(data).scale('x', { domain: data.map((d) => d.time) });
chart
.interval()
.data([
{ time: '10:10', call: 4, waiting: 2, people: 2 },
{ time: '10:15', call: 2, waiting: 6, people: 3 },
{ time: '10:30', call: 5, waiting: 2, people: 3 },
])
.encode('x', 'time')
.encode('y', 'waiting')
.axis('y', { titleFill: '#5B8FF9', title: 'Waiting' });
chart
.line()
.encode('x', 'time')
.encode('y', 'people')
.encode('shape', 'smooth')
.style('stroke', '#fdae6b')
.style('lineWidth', 2)
.scale('y', { independent: true })
.axis('y', {
position: 'right',
grid: null,
title: 'People',
titleFill: '#fdae6b',
});
chart.render();
第二种,指定 x 比例尺的排序方法。因为 x 通道的数据是离散数据,离散数据没有默认的排序方法,所以需要显式指定。
import { Chart } from '@antv/g2';
const data = [
{ time: '10:10', call: 4, waiting: 2, people: 2 },
{ time: '10:15', call: 2, waiting: 6, people: 3 },
{ time: '10:20', call: 13, waiting: 2, people: 5 },
{ time: '10:25', call: 9, waiting: 9, people: 1 },
{ time: '10:30', call: 5, waiting: 2, people: 3 },
{ time: '10:35', call: 8, waiting: 2, people: 1 },
{ time: '10:40', call: 13, waiting: 1, people: 2 },
];
const chart = new Chart({
container: 'container',
autoFit: true,
});
// 显示指定 x 的排序规则
const minute = (d) => +d.split(':').pop();
chart.data(data).scale('x', { compare: (a, b) => minute(a) - minute(b) });
chart
.interval()
.data([
{ time: '10:10', call: 4, waiting: 2, people: 2 },
{ time: '10:15', call: 2, waiting: 6, people: 3 },
{ time: '10:30', call: 5, waiting: 2, people: 3 },
])
.encode('x', 'time')
.encode('y', 'waiting')
.axis('y', { titleFill: '#5B8FF9', title: 'Waiting' });
chart
.line()
.encode('x', 'time')
.encode('y', 'people')
.encode('shape', 'smooth')
.style('stroke', '#fdae6b')
.style('lineWidth', 2)
.scale('y', { independent: true })
.axis('y', {
position: 'right',
grid: null,
title: 'People',
titleFill: '#fdae6b',
});
chart.render();
第二个问题是因为 interval 只于离散数据(Point 是离散和连续数据都适用),但是 Date 对象不是离散数据。所以解决办法是不转换成 Date 对象,并且指定排序方法。
import { Chart } from '@antv/g2';
const chart = new Chart({
container: 'container',
height: 360,
paddingLeft: 60,
});
chart.data({
type: 'fetch',
value: 'https://assets.antv.antgroup.com/g2/year-population.json',
});
// 排序
chart.scale('x', { compare: (a, b) => +a - +b });
chart
.rangeX()
.data([
{ year: ['1933', '1945'], event: 'Nazi Rule' },
{ year: ['1948', '1989'], event: 'GDR (East Germany)' },
])
.encode('x', 'year')
.encode('color', 'event')
.scale('color', { independent: true, range: ['#FAAD14', '#30BF78'] })
.style('fillOpacity', 0.75);
chart
.line()
.encode('x', 'year')
.encode('y', 'population')
.encode('color', '#333');
chart
.interval()
.encode('x', 'year')
.encode('y', 'population')
.encode('color', '#333')
.style('lineWidth', 1.5);
chart.render();
哦哦明白了,感谢