Skip to content

Commit

Permalink
feat/interval3d (#5562)
Browse files Browse the repository at this point in the history
* fix(CONTRIBUTING.md): fix incorrect file path

* feat(api): interval3D

* docs(interval3D): init docs

* fix: fix the bug in the example of intervalThree.zh.md

* feat(interval3D test): beautify test plots
  • Loading branch information
VirusPC authored Sep 20, 2023
1 parent e543e0e commit 763d611
Show file tree
Hide file tree
Showing 12 changed files with 455 additions and 2 deletions.
80 changes: 80 additions & 0 deletions __tests__/plots/api/chart-render-3d-bar-chart-perspective.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { CameraType } from '@antv/g';
import { Renderer as WebGLRenderer } from '@antv/g-webgl';
import { Plugin as ThreeDPlugin, DirectionalLight } from '@antv/g-plugin-3d';
import { Plugin as ControlPlugin } from '@antv/g-plugin-control';
import { Runtime, extend } from '../../../src/api';
import { corelib, threedlib } from '../../../src/lib';

export function chartRender3dBarChartPerspective(context) {
const { container } = context;

// Create a WebGL renderer.
const renderer = new WebGLRenderer();
renderer.registerPlugin(new ThreeDPlugin());
renderer.registerPlugin(new ControlPlugin());

const Chart = extend(Runtime, { ...corelib(), ...threedlib() });
const chart = new Chart({
container,
renderer,
depth: 400,
// padding: 10,
});

const data: { x: string; z: string; y: number; color: number }[] = [];
for (let x = 0; x < 5; ++x) {
for (let z = 0; z < 5; ++z) {
data.push({
x: `x-${x}`,
z: `z-${z}`,
y: 10 - x - z,
color: Math.random() < 0.33 ? 0 : Math.random() < 0.67 ? 1 : 2,
});
}
}

chart
.interval3D()
.data({
type: 'inline',
value: data,
})
.encode('x', 'x')
.encode('y', 'y')
.encode('z', 'z')
.encode('color', 'color')
.encode('shape', 'cube')
.coordinate({ type: 'cartesian3D' })
.scale('x', { nice: true })
.scale('y', { nice: true })
.scale('z', { nice: true })
.legend(false)
.axis('x', { gridLineWidth: 2 })
.axis('y', { gridLineWidth: 2, titleBillboardRotation: -Math.PI / 2 })
.axis('z', { gridLineWidth: 2 })
.style('opacity', 0.7)
.style('cursor', 'pointer');

const finished = chart.render().then(() => {
const { canvas } = chart.getContext();
if (!canvas) return;
const camera = canvas.getCamera();
camera.setPerspective(0.1, 5000, 50, 1280 / 960);
camera.setType(CameraType.ORBITING);
camera.rotate(-20, -20, 0);

// Add a directional light into scene.
const light = new DirectionalLight({
style: {
intensity: 2.5,
fill: 'white',
direction: [-1, 0, 1],
},
});
canvas.appendChild(light);
});

return { finished };
}

chartRender3dBarChartPerspective.skip = true;
78 changes: 78 additions & 0 deletions __tests__/plots/api/chart-render-3d-bar-chart.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { CameraType } from '@antv/g';
import { Renderer as WebGLRenderer } from '@antv/g-webgl';
import { Plugin as ThreeDPlugin, DirectionalLight } from '@antv/g-plugin-3d';
import { Plugin as ControlPlugin } from '@antv/g-plugin-control';
import { Runtime, extend } from '../../../src/api';
import { corelib, threedlib } from '../../../src/lib';

export function chartRender3dBarChart(context) {
const { container } = context;

// Create a WebGL renderer.
const renderer = new WebGLRenderer();
renderer.registerPlugin(new ThreeDPlugin());
renderer.registerPlugin(new ControlPlugin());

const Chart = extend(Runtime, { ...corelib(), ...threedlib() });
const chart = new Chart({
container,
renderer,
depth: 400,
padding: 50,
});

const data: { x: string; z: string; y: number; color: number }[] = [];
for (let x = 0; x < 5; ++x) {
for (let z = 0; z < 5; ++z) {
data.push({
x: `x-${x}`,
z: `z-${z}`,
y: 10 - x - z,
color: Math.random() < 0.33 ? 0 : Math.random() < 0.67 ? 1 : 2,
});
}
}

chart
.interval3D()
.data({
type: 'inline',
value: data,
})
.encode('x', 'x')
.encode('y', 'y')
.encode('z', 'z')
.encode('color', 'color')
.encode('shape', 'cube')
.coordinate({ type: 'cartesian3D' })
.scale('x', { nice: true })
.scale('y', { nice: true })
.scale('z', { nice: true })
.legend(false)
.axis('x', { gridLineWidth: 2 })
.axis('y', { gridLineWidth: 2, titleBillboardRotation: -Math.PI / 2 })
.axis('z', { gridLineWidth: 2 })
.style('opacity', 0.7);

const finished = chart.render().then(() => {
const { canvas } = chart.getContext();
if (!canvas) return;
const camera = canvas.getCamera();
camera.setType(CameraType.ORBITING);
camera.rotate(-20, -20, 0);

// Add a directional light into scene.
const light = new DirectionalLight({
style: {
intensity: 2.5,
fill: 'white',
direction: [-1, 0, 1],
},
});
canvas.appendChild(light);
});

return { finished };
}

chartRender3dBarChart.skip = true;
2 changes: 2 additions & 0 deletions __tests__/plots/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ export { chartOnTextClick } from './chart-on-text-click';
export { chartOnComponentClick } from './chart-on-component-click';
export { chartRenderEvent } from './chart-render-event';
export { chartRender3dScatterPlot } from './chart-render-3d-scatter-plot';
export { chartRender3dBarChart } from './chart-render-3d-bar-chart';
export { chartRender3dBarChartPerspective } from './chart-render-3d-bar-chart-perspective';
export { chartRender3dScatterPlotPerspective } from './chart-render-3d-scatter-plot-perspective';
export { chartRender3dScatterPlotLegend } from './chart-render-3d-scatter-plot-legend';
export { chartRender3dLinePlot } from './chart-render-3d-line-plot';
Expand Down
6 changes: 6 additions & 0 deletions site/.dumi/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"extends": "../tsconfig.json",
"include": [
"**/*"
]
}
4 changes: 4 additions & 0 deletions site/docs/api/chart.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,10 @@ chart.render();

添加 point3D 图形,具体见 [3d](/spec/threed/point-threed)

### `chart.interval3D`

添加 interval3D 图形,具体见 [3d](/spec/threed/interval-threed)

### `chart.line3D`

添加 line3D 图形,具体见 [3d](/spec/threed/line-threed)
Expand Down
6 changes: 6 additions & 0 deletions site/docs/spec/threed/intervalThreed.en.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
title: interval3D
order: 3
---

<embed src="@/docs/spec/threed/intervalThreed.zh.md"></embed>
105 changes: 105 additions & 0 deletions site/docs/spec/threed/intervalThreed.zh.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
---
title: interval3D
order: 3
---

主要用于绘制 3D 条形图。

## 开始使用

首先需要使用 [@antv/g-webgl](https://g.antv.antgroup.com/api/renderer/webgl) 作为渲染器并注册以下两个插件:

- [g-plugin-3d](https://g.antv.antgroup.com/plugins/3d) 提供 3D 场景下的几何、材质和光照
- [g-plugin-control](https://g.antv.antgroup.com/plugins/control) 提供 3D 场景下的相机交互

然后设置 z 通道、scale 和 z 坐标轴,最后在场景中添加光源。

```js | ob
(() => {
// Create a WebGL renderer.
const renderer = new gWebgl.Renderer();
renderer.registerPlugin(new gPluginControl.Plugin());
renderer.registerPlugin(new gPlugin3d.Plugin());

const Chart = G2.extend(G2.Runtime, { ...G2.corelib(), ...G2.threedlib() });

// 初始化图表实例
const chart = new Chart({
renderer,
width: 500,
height: 500,
depth: 400,
});

const data = [];
for (let x = 0; x < 5; ++x) {
for (let z = 0; z < 5; ++z) {
data.push({
x: `x-${x}`,
z: `z-${z}`,
y: 10 - x - z,
color: Math.random() < 0.33 ? 0 : Math.random() < 0.67 ? 1 : 2,
});
}
}

chart
.interval3D()
.data({
type: 'inline',
value: data,
})
.encode('x', 'x')
.encode('y', 'y')
.encode('z', 'z')
.encode('color', 'color')
.encode('shape', 'cube')
.coordinate({ type: 'cartesian3D' })
.scale('x', { nice: true })
.scale('y', { nice: true })
.scale('z', { nice: true })
.legend(false)
.axis('x', { gridLineWidth: 2 })
.axis('y', { gridLineWidth: 2, titleBillboardRotation: -Math.PI / 2 })
.axis('z', { gridLineWidth: 2 });

chart.render().then(() => {
const { canvas } = chart.getContext();
const camera = canvas.getCamera();
camera.setPerspective(0.1, 5000, 80, 1280 / 960);
camera.setType(CameraType.ORBITING);
camera.rotate(-20, -20, 0);

// Add a directional light into scene.
const light = new DirectionalLight({
style: {
intensity: 2.5,
fill: 'white',
direction: [-1, 0, 1],
},
});
canvas.appendChild(light);
});

return chart.getContainer();
})();
```

更多的案例,可以查看[图表示例](/examples)页面。

## 选项

目前 interval3D 有以下一个内置 shape 图形:

| 图形 | 描述 | 示例 |
| ------ | ---------- | ---- |
| cube | 绘制立方体 | |

### cube

| 属性 | 描述 | 类型 | 默认值 |
| ------- | --------------------------------------------- | ------------------------------ | --------- |
| fill | 图形的填充色 | `string` \| `Function<string>` | - |
| opacity | 图形的整体透明度 | `number` \| `Function<number>` | - |
| cursor | 鼠标样式。同 css 的鼠标样式,默认 'default'。 | `string` \| `Function<string>` | 'default' |

3 changes: 2 additions & 1 deletion src/lib/threed.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { Cartesian3D } from '../coordinate';
import { AxisZ } from '../component';
import { Point3D, Line3D } from '../mark';
import { Point3D, Line3D, Interval3D } from '../mark';

export function threedlib() {
return {
'coordinate.cartesian3D': Cartesian3D,
'component.axisZ': AxisZ,
'mark.point3D': Point3D,
'mark.line3D': Line3D,
'mark.interval3D': Interval3D,
} as const;
}
1 change: 1 addition & 0 deletions src/mark/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export { Line } from './line';
export { Line3D } from './line3D';
export { Point } from './point';
export { Point3D } from './point3D';
export { Interval3D } from './interval3D';
export { Text } from './text';
export { Cell } from './cell';
export { Area } from './area';
Expand Down
Loading

0 comments on commit 763d611

Please sign in to comment.