Skip to content

Commit

Permalink
完善构建方案 & 容器 Bug 修复 (antvis#84)
Browse files Browse the repository at this point in the history
* feat(core): support hierarchical containers

* feat(multipassrenderer): support custom postprocessing pass

* build(rollup): output CDN bundle to @antv/l7/dist

* build(tsc): generate TS declaration files

* chore(prerelease): prerelease beta.10
  • Loading branch information
xiaoiver authored Nov 25, 2019
1 parent 0f11223 commit 44dec44
Show file tree
Hide file tree
Showing 243 changed files with 8,492 additions and 12,339 deletions.
400 changes: 0 additions & 400 deletions .storybook/l7.css

This file was deleted.

31 changes: 2 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,41 +26,14 @@ yarn install
yarn watch
```

运行 Demo
运行 Demo,基于 Storybook:
```bash
yarn storybook
```

代替 `git commit` 提交:
```bash
yarn commit
```

## view doc example

```bash
npm start
yarn start
```
visit http://localhost:8000/

## Add Package

add new package:
```bash
lerna create my-pack -y
```

将 ui-lib 作为 my-pack 的依赖:
```bash
yarn workspace my-pack add ui-lib/1.0.0
```

将 lodash 添加为所有 package 的依赖(不包含root)
```bash
yarn workspaces run add lodash
```

将 typescript 设置为 root 的开发依赖
```bash
yarn add -W -D typescript jest
```
2 changes: 1 addition & 1 deletion README.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ L7 是由蚂蚁金服 AntV 数据可视化团队推出的基于 WebGL 的开源
### Installation

```
npm install @antv/l7
npm install @antv/l7@beta
```

## 核心特性
Expand Down
7 changes: 4 additions & 3 deletions babel.config.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
// @see https://babeljs.io/docs/en/next/config-files#project-wide-configuration
module.exports = api => {
api.cache(() => process.env.NODE_ENV);

const isSite = api.env('site');
const isCDNBundle = api.env('bundle');
const isCommonJS = api.env('cjs');
const isESModule = api.env('esm');
const isTest = api.env('test');

if (process.env.GATSBY === 'true') { //
if (isSite) {
return {
presets: [
'babel-preset-gatsby'
Expand Down Expand Up @@ -56,7 +58,6 @@ module.exports = api => {
}
],
'@babel/preset-typescript',
'babel-preset-gatsby'
],
plugins: [
'@babel/plugin-proposal-optional-chaining',
Expand Down Expand Up @@ -104,7 +105,7 @@ module.exports = api => {
// 按需引用 @see https://github.com/lodash/babel-plugin-lodash
'lodash'
// 内联 WebGL 常量 @see https://www.npmjs.com/package/babel-plugin-inline-webgl-constants
// isCDNBundle ? 'inline-webgl-constants' : {}
// isCDNBundle ? 'inline-webgl-constants' : {},
],
ignore: [
'node_modules',
Expand Down
7 changes: 1 addition & 6 deletions build/bundle.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,2 @@
// @ts-ignore
export * from '@l7/scene';
// @ts-ignore
export * from '@l7/layers';

// @ts-ignore
export * from '@l7/component';
export * from '@antv/l7';
10 changes: 7 additions & 3 deletions build/rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,13 @@ module.exports = [
resolve: [ '.tsx', '.ts' ],
entries: [
{
find: /^@l7\/(.*)/,
replacement: resolveFile('packages/$1/src')
}
find: /^@antv\/l7-(.*)/,
replacement: resolveFile('packages/$1/src'),
},
{
find: /^@antv\/l7$/,
replacement: resolveFile('packages/l7/src'),
},
]
}
),
Expand Down
2 changes: 1 addition & 1 deletion demos/raster/basic/demo/image.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

import { Scene,ImageLayer } from '@antv/l7';
import { Scene, ImageLayer } from '@antv/l7';
const scene = new Scene({
id: 'map',
pitch: 0,
Expand Down
3 changes: 1 addition & 2 deletions demos/raster/basic/demo/raster.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { Scene } from '@l7/scene';
import { RasterLayer } from '@l7/layers'
import { RasterLayer, Scene } from '@antv/l7';
import * as GeoTIFF from 'geotiff';
const scene = new Scene({
id: 'map',
Expand Down
4 changes: 1 addition & 3 deletions demos/tutorial/control/demo/amap.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import { Scene } from '@l7/scene';
import { PointLayer } from '@l7/layers'
import { Scale, Zoom, Layers } from '@l7/component';
import { PointLayer, Scale, Scene, Layers, Zoom } from '@antv/l7';
const scene = new Scene({
id: 'map',
pitch: 0,
Expand Down
3 changes: 1 addition & 2 deletions demos/tutorial/control/demo/mapbox.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { Scene } from '@l7/scene';
import { Scale, Zoom } from '@l7/component';
import { Scale, Zoom, Scene } from '@antv/l7';
const scene = new Scene({
id: 'map',
pitch: 0,
Expand Down
4 changes: 1 addition & 3 deletions demos/tutorial/control/demo/popup.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import { Scene } from '@l7/scene';
import { PointLayer } from '@l7/layers'
import { Scale, Zoom, Layers } from '@l7/component';
import { Scale, Zoom, Scene, Layers, PointLayer } from '@antv/l7';
const scene = new Scene({
id: 'map',
pitch: 0,
Expand Down
3 changes: 1 addition & 2 deletions demos/tutorial/data/demo/line.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { Scene } from '@l7/scene';
import { LineLayer } from '@l7/layers'
import { LineLayer, Scene } from '@antv/l7';
const scene = new Scene({
id: 'map',
pitch: 0,
Expand Down
2 changes: 1 addition & 1 deletion demos/tutorial/map/demo/amap.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Scene } from '@l7/scene';
import { Scene } from '@antv/l7';
const scene = new Scene({
id: 'map',
pitch: 0,
Expand Down
2 changes: 1 addition & 1 deletion demos/tutorial/map/demo/mapbox.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Scene } from '@l7/scene';
import { Scene } from '@antv/l7';
const scene = new Scene({
id: 'map',
pitch: 0,
Expand Down
213 changes: 213 additions & 0 deletions dev-docs/IoC 容器、依赖注入与服务说明.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
# IoC 容器、依赖注入与服务说明

在面向对象编程领域,[SOLID](https://en.wikipedia.org/wiki/SOLID_(object-oriented_design))[“组合优于继承”](https://en.wikipedia.org/wiki/Composition_over_inheritance) 都是经典的设计原则。

IoC(Inversion of Control) 控制反转这种设计模式将对象的创建销毁、依赖关系交给容器处理,是以上设计原则的一种经典实践。其中它的一种实现 DI(Dependency Injection) 即依赖注入在工程领域应用十分广泛(下图来自 [Dependency-Injection-in-practice-CodeCAMP.pdf](http://www.mono.hr/Pdf/Dependency-Injection-in-practice-CodeCAMP.pdf)),最著名的当属 Spring:

![](./screenshots/di-containers.png)

而在 JavaScript 领域,[Angular](https://angular.io/guide/dependency-injection)[NestJS](https://docs.nestjs.com/fundamentals/custom-providers) 也都实现了自己的 IoC 容器。

L7 选择了 [InversifyJS](https://github.com/inversify/InversifyJS/blob/master/wiki/oo_design.md) 作为轻量的 IoC 容器,统一管理各类复杂的服务,实现松耦合的代码结构,同时具有以下收益:
* 提供高扩展性。
* 支持地图底图(高德、Mapbox)切换
* 支持渲染引擎替换
* 插件化
* 便于测试。测试用例中替换渲染引擎服务为基于 headless-gl 的渲染服务。

下图清晰的展示了切换引擎和底图时均不会影响核心代码:
![](./screenshots/packages.png)

# 多层次容器

L7 需要支持多场景(Scene),每个场景中又包含了多个图层(Layer)。不同的服务可能隶属全局、Scene 和 Layer,因此对于容器也有层次化的要求。
试想如果我们只有一个全局容器,其中绑定的所有服务自然也都成了全局服务,在多场景下(页面中一个高德地图、一个 Mapbox)销毁高德地图的渲染服务,将影响到 Mapbox 的展示。

下图为 L7 的四个独立场景(两个高德、两个 Mapbox)DEMO 展示效果,它们应该是能互不干扰运行的:
![](./screenshots/multi-scene.png)

在 Angular 中也有[分层容器](https://angular.io/guide/hierarchical-dependency-injection)的应用。L7 使用的是 InversifyJS 提供的[层次化依赖注入功能](https://github.com/inversify/InversifyJS/blob/master/wiki/hierarchical_di.md)

容器层次关系及数目如下:
```bash
RootContainer 1
-> SceneContainer 1.*
-> LayerContainer 1.*
```
其中每种容器包含不同类型的服务,这些服务有的是单例,有的是工厂方法。子容器应该能访问父容器中绑定的服务,即如果 RootContainer 已经绑定了全局日志服务,SceneContainer 不需要重复绑定也能注入。

下面详细介绍下每种容器中的服务及其 API,在自定义图层、自定义插件以及自定义后处理效果中都可以方便地使用这些服务。

## 全局容器

一些全局性服务不需要用户手动创建,也无需显式销毁。我们在全局容器中完成一次性的绑定,后续在所有场景、图层中都可以让容器注入这些服务的单例。类似 Angular 中的 [root ModuleInjector](https://angular.io/guide/hierarchical-dependency-injection#moduleinjector)

例如日志、Shader 模块化服务应该是全局性的单例,我们在 `RootContainer` 完成依赖声明:
```typescript
// 在根容器中绑定日志服务为单例
rootContainer
.bind<ILogService>(TYPES.ILogService)
.to(LogService)
.inSingletonScope();
```

目前 L7 中全局性服务说明如下:

| 服务名称 | 类型 | 说明 |
| -------- | --- | --------- |
| logger | 全局服务 | 在控制台输出信息 |

* 日志服务。
* Shader 模块化服务。提供基本的 GLSL 模块化服务,基于字符串替换实现。
* 配置项校验服务。[详见](./ConfigSchemaValidation.md)

### 日志服务

基于 `probe.gl` 实现,默认只输出 debug 级别以上的日志信息。开发模式下通过设置日志等级输出 debug 信息,另外 debug 信息会带上时间戳打点,类似这样:
```bash
L7: 403ms map loaded
L7: 405ms add event listeners on canvas
L7: 676ms regenerate vertex attributes: color finished
```

通过 `logger` 引用,可使用 API 如下:

| 方法名 | 参数 | 返回值 | 说明 |
| -------- | ------------- | --------- | --------- |
| debug | `(message: string)` || 输出 debug 级别信息,会带上时间戳 |
| info | `(message: string)` || 输出 info 级别信息 |
| warn | `(message: string)` || 输出 warn 级别信息 |
| error | `(message: string)` || 输出 error 级别信息 |

在自定义图层中使用示例如下:
```typescript
class PolygonLayer extends BaseLayer<IPolygonLayerStyleOptions> {
protected renderModels() {
// 输出 debug 级别信息
this.logger.debug('start to render...');
}
}
```

### Shader 模块化服务

通过 `shaderModuleService` 引用,可使用 API 如下:

| 方法名 | 参数 | 返回值 | 说明 |
| -------- | ------------- | --------- | --------- |
| registerModule | `(moduleName: string, moduleParams: IModuleParams)` || 使用模块名和参数注册 GLSL 模块,其中 `IModuleParams` 格式见下面 |
| getModule | `(moduleName: string)` | `IModuleParams` | 根据模块名获取编译后的 GLSL 模块 |

GLSL 模块参数如下:
```typescript
interface IModuleParams {
vs: string; // vertex shader 字符串
fs: string; // fragment shader 字符串
uniforms?: { // 可选,uniforms
[key: string]: IUniform;
};
}
```

我们以自定义后处理效果场景为例,完整教程见[自定义后处理效果](自定义后处理效果.md)
```typescript
protected setupShaders() {
// 使用 Shader 服务注册 GLSL 模块
this.shaderModuleService.registerModule('dotScreenEffect', {
vs: this.quad, // Vertex Shader 固定
fs: ``, // 暂时省略,在下一小节中详细介绍
});

// 使用 Shader 服务获取编译后的 GLSL 模块
const { vs, fs, uniforms } = this.shaderModuleService.getModule('dotScreenEffect');
// 使用渲染器服务获取视口尺寸
const { width, height } = this.rendererService.getViewportSize();

return {
vs,
fs,
uniforms: {
...uniforms,
u_ViewportSize: [width, height],
},
};
}
```

### 配置项校验服务

开发者不需要显式调用该服务。

Layer 子类可以通过重载 `getConfigSchema()` 方法定义自身的特有属性。例如 `PolygonLayer` 需要定义透明度,详见[ConfigSchemaValidation 使用方法](ConfigSchemaValidation.md)
```typescript
protected getConfigSchema() {
return {
properties: {
opacity: {
type: 'number',
minimum: 0,
maximum: 1,
},
},
};
}
```

以上就是供开发者使用的常见全局服务,下面我们将介绍场景容器及其内部服务。

## Scene 容器

场景可以承载多个图层,与地图底图一一对应。每个场景都有自己独立的容器确保多个场景间服务不会互相干扰,同时继承全局容器以便访问全局服务。容器内服务包括:

* 地图底图服务。每个场景有一个对应的地图底图。
* 渲染引擎服务。由于依赖 WebGL 上下文,基于 `regl` 实现。
* 图层管理服务。管理场景中所有的图层,负责图层的创建、销毁。
* PostProcessingPass。内置常用的后处理效果。

### 地图底图服务

兼容 Mapbox 和高德,开发者可以获取当前地图的状态、调用地图相机动作(缩放、平移、旋转)。

通过 `mapService` 引用。

常用地图状态获取方法如下:
| 方法名 | 参数 | 返回值 | 说明 |
| -------- | ------------- | --------- | --------- |
| getSize || `[number, number]` | 获取地图尺寸(像素单位) |
| getZoom || `number` | 获取当前地图缩放等级,以 Mapbox 为准 |
| getCenter || `{lng: number; lat: number}` | 获取当前地图中心点经纬度 |
| getPitch || `number` | 获取当前地图仰角 |
| getRotation || `number` | 获取当前地图逆时针旋转角度 |
| getBounds || `[[number, number], [number, number]]` | 获取当前地图可视区域 `[西南角、东北角]` |

⚠️对于一些地图属性将采用兼容性处理。

* 缩放等级,差异表现在:
1. 取值范围。高德缩放等级范围 `[3, 18]`,而 Mapbox 为 `[0, 20]`
2. 高德 `3` 缩放等级对应 Mapbox `2` 缩放等级。考虑兼容性,`getZoom()` 将返回 Mapbox 定义等级。
* 旋转角度。高德返回地图顺时针旋转角度,Mapbox 返回逆时针旋转角度。考虑兼容性,`getRotation()` 将返回地图逆时针旋转角度。

除了获取地图状态,还可以控制地图进行一些相机动作。

### [WIP]渲染引擎服务

目前 L7 使用 [regl](https://github.com/regl-project/regl),但开发者不需要关心底层 WebGL 渲染引擎实现,即使后续更换了其他引擎,我们也将保持服务接口的稳定。

通过 `rendererService` 引用。



### 图层管理服务

开发者不需要显式调用。用于管理场景中所有的图层,负责图层的创建、销毁。

## Layer 容器

每个图层有独立的容器,同时继承自所属场景容器,自然也可以访问全局服务。

* 样式管理服务。
* MultiPassRenderer 服务。详见[MultiPassRenderer 说明](./MultiPassRenderer.md)

## 参考资料

* [动态依赖注入](https://github.com/inversify/InversifyJS/issues/1088)
2 changes: 1 addition & 1 deletion dev-docs/MultiPassRenderer.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export interface IPostProcessingPass extends IPass {
}
```

具体实现依赖 `@l7/renderer` 实现,目前使用 regl 实现 IFramebuffer 等接口。
具体实现依赖 `@antv/l7-renderer` 实现,目前使用 regl 实现 IFramebuffer 等接口。

## 内置 Pass

Expand Down
Binary file added dev-docs/screenshots/custom-effect.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added dev-docs/screenshots/di-containers.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added dev-docs/screenshots/dotscreen.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added dev-docs/screenshots/multi-scene.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added dev-docs/screenshots/packages.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 44dec44

Please sign in to comment.