Shihui dev (#807)

* feat: add getModelMatrix into viewport

* feat: 新增地球模式 (初步构建)

* feat: 完善地球交互

* style: lint style

* feat: 调整地球图层缩放的方向

* style: lint style

* feat: 增加地球模式的 pointLayer/fill 图层

* style: lint style

* feat: 增加地球、太阳的简单运动系统,优化部分代码结构

* fix: 修复时间点击出错

* style: lint style

* fix: 修复地图 panBy 方法参数错误

* style: lint style

* feat: pointLayer/cylinder 圆柱兼容地球模式

* style: lint style

* feat: 修复 pointLayer/fill 在拾取是破面严重的情况

* style: lint style

* feat: 增加 arc 弧度调节

* feat: 增加 lineLayer/arc3d 兼容地球模式

* style: lint style

* feat: 增加地球图层 - 大气层

* style: lint style

* feat: 增加设置可视化层背景色的能力

* style: lint style

* feat: 增加地球外发光效果

* style: lint style

* feat: 允许用户不使用 layer 的 source 方法 - 地球模式下光晕图层不需要传数据

* style: lint style

* feat: 调整光晕的 shader 计算

* feat: 调整地球大气层的渲染层级

* style: lint style

* feat: 调整案例

* style: lint style

* feat: 增加地球图层的默认参数、调整部分代码

* style: lint style

* fix: 修复 amap2 新增样式导致的 marker 失效

* feat: 修复 amap2 的 amap-maps 新增 z-index=0; 引发的marker 显示层级失效

* feat: amap2 的 amap-maps 新增 z-index=0; 样式,让 marker 中 zIndex 失效

* style: lint style

* chore: update version 2.5.36 -> 2.5.37

* feat: 增加 demo

* style: lint style

* feat: 修复 varying 传递 float 总数在部分终端设备 ios13 上突破限制的问题

* chore: update version 2.5.37 -> 2.5.38

* feat: add stoty demo

* style: lint style

* feat: 调整 aspace demo
This commit is contained in:
YiQianYao 2021-10-25 16:44:37 +08:00 committed by GitHub
parent 2a3aaa3725
commit 7f6f07462c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 510 additions and 52 deletions

View File

@ -14,7 +14,7 @@
"message": "chore: publish"
}
},
"version": "2.5.37",
"version": "2.5.38",
"npmClient": "yarn",
"useWorkspaces": true,
"publishConfig": {

View File

@ -1,6 +1,6 @@
{
"name": "@antv/l7-component",
"version": "2.5.37",
"version": "2.5.38",
"description": "",
"main": "lib/index.js",
"module": "es/index.js",
@ -25,8 +25,8 @@
"author": "lzxue",
"license": "ISC",
"dependencies": {
"@antv/l7-core": "^2.5.37",
"@antv/l7-utils": "^2.5.37",
"@antv/l7-core": "^2.5.38",
"@antv/l7-utils": "^2.5.38",
"@babel/runtime": "^7.7.7",
"eventemitter3": "^4.0.0",
"inversify": "^5.0.1",

View File

@ -1,6 +1,6 @@
{
"name": "@antv/l7-core",
"version": "2.5.37",
"version": "2.5.38",
"description": "",
"main": "lib/index.js",
"module": "es/index.js",
@ -24,7 +24,7 @@
"license": "ISC",
"dependencies": {
"@antv/async-hook": "^2.1.0",
"@antv/l7-utils": "^2.5.37",
"@antv/l7-utils": "^2.5.38",
"@babel/runtime": "^7.7.7",
"@mapbox/tiny-sdf": "^1.1.1",
"ajv": "^6.10.2",

View File

@ -124,6 +124,16 @@ export interface ILayer {
options?: ISourceCFG;
};
multiPassRenderer: IMultiPassRenderer;
/**
* threejs
* @param lnglat
* @param altitude
* @param rotation
* @param scale
*/
threeRenderService?: any;
needPick(type: string): boolean;
getLayerConfig(): Partial<ILayerConfig & ISceneConfig>;
getContainer(): Container;
@ -220,14 +230,6 @@ export interface ILayer {
setAnimateStartTime(): void;
getLayerAnimateTime(): number;
/**
* threejs
* @param lnglat
* @param altitude
* @param rotation
* @param scale
*/
// 获取对应地图的经纬度模型矩阵
getModelMatrix?(
lnglat: ILngLat,
@ -260,6 +262,9 @@ export interface ILayer {
// 增加加载模型的动画混合器
addAnimateMixer?(mixer: any): void;
// 返回当前的 threejs camera
getRenderCamera?(): any;
/**
*
*/

View File

@ -1,6 +1,6 @@
{
"name": "@antv/l7",
"version": "2.5.37",
"version": "2.5.38",
"description": "A Large-scale WebGL-powered Geospatial Data Visualization",
"main": "lib/index.js",
"module": "es/index.js",
@ -25,12 +25,12 @@
"author": "antv",
"license": "MIT",
"dependencies": {
"@antv/l7-component": "^2.5.37",
"@antv/l7-core": "^2.5.37",
"@antv/l7-layers": "^2.5.37",
"@antv/l7-maps": "^2.5.37",
"@antv/l7-scene": "^2.5.37",
"@antv/l7-utils": "^2.5.37",
"@antv/l7-component": "^2.5.38",
"@antv/l7-core": "^2.5.38",
"@antv/l7-layers": "^2.5.38",
"@antv/l7-maps": "^2.5.38",
"@antv/l7-scene": "^2.5.38",
"@antv/l7-utils": "^2.5.38",
"@babel/runtime": "^7.7.7"
},
"gitHead": "684ba4eb806a798713496d3fc0b4d1e17517dc31",

View File

@ -1,2 +1,2 @@
const version = '2.5.37';
const version = '2.5.38';
export { version };

View File

@ -1,6 +1,6 @@
{
"name": "@antv/l7-layers",
"version": "2.5.37",
"version": "2.5.38",
"description": "L7's collection of built-in layers",
"main": "lib/index.js",
"module": "es/index.js",
@ -24,9 +24,9 @@
"license": "ISC",
"dependencies": {
"@antv/async-hook": "^2.1.0",
"@antv/l7-core": "^2.5.37",
"@antv/l7-source": "^2.5.37",
"@antv/l7-utils": "^2.5.37",
"@antv/l7-core": "^2.5.38",
"@antv/l7-source": "^2.5.38",
"@antv/l7-utils": "^2.5.38",
"@babel/runtime": "^7.7.7",
"@mapbox/martini": "^0.2.0",
"@turf/meta": "^6.0.2",

View File

@ -1,6 +1,6 @@
{
"name": "@antv/l7-map",
"version": "2.5.37",
"version": "2.5.38",
"description": "l7 map",
"keywords": [],
"author": "thinkinggis <lzx199065@gmail.com>",
@ -37,7 +37,7 @@
},
"homepage": "https://github.com/antvis/L7#readme",
"dependencies": {
"@antv/l7-utils": "^2.5.37",
"@antv/l7-utils": "^2.5.38",
"@babel/runtime": "^7.7.7",
"@mapbox/point-geometry": "^0.1.0",
"@mapbox/unitbezier": "^0.0.0",

View File

@ -1,6 +1,6 @@
{
"name": "@antv/l7-maps",
"version": "2.5.37",
"version": "2.5.38",
"description": "",
"main": "lib/index.js",
"module": "es/index.js",
@ -27,9 +27,9 @@
"license": "ISC",
"dependencies": {
"@amap/amap-jsapi-loader": "^0.0.3",
"@antv/l7-core": "^2.5.37",
"@antv/l7-map": "^2.5.37",
"@antv/l7-utils": "^2.5.37",
"@antv/l7-core": "^2.5.38",
"@antv/l7-map": "^2.5.38",
"@antv/l7-utils": "^2.5.38",
"@babel/runtime": "^7.7.7",
"@types/amap-js-api": "^1.4.6",
"@types/mapbox-gl": "^1.11.2",

View File

@ -1,6 +1,6 @@
{
"name": "@antv/l7-renderer",
"version": "2.5.37",
"version": "2.5.38",
"description": "",
"main": "lib/index.js",
"module": "es/index.js",
@ -26,7 +26,7 @@
"gl": "^4.4.0"
},
"dependencies": {
"@antv/l7-core": "^2.5.37",
"@antv/l7-core": "^2.5.38",
"@babel/runtime": "^7.7.7",
"inversify": "^5.0.1",
"l7regl": "^0.0.14",

View File

@ -1,6 +1,6 @@
{
"name": "@antv/l7-scene",
"version": "2.5.37",
"version": "2.5.38",
"description": "",
"main": "lib/index.js",
"module": "es/index.js",
@ -23,12 +23,12 @@
"author": "xiaoiver",
"license": "ISC",
"dependencies": {
"@antv/l7-component": "^2.5.37",
"@antv/l7-core": "^2.5.37",
"@antv/l7-layers": "^2.5.37",
"@antv/l7-maps": "^2.5.37",
"@antv/l7-renderer": "^2.5.37",
"@antv/l7-utils": "^2.5.37",
"@antv/l7-component": "^2.5.38",
"@antv/l7-core": "^2.5.38",
"@antv/l7-layers": "^2.5.38",
"@antv/l7-maps": "^2.5.38",
"@antv/l7-renderer": "^2.5.38",
"@antv/l7-utils": "^2.5.38",
"@babel/runtime": "^7.7.7",
"inversify": "^5.0.1",
"mapbox-gl": "^1.2.1",

View File

@ -1,6 +1,6 @@
{
"name": "@antv/l7-source",
"version": "2.5.37",
"version": "2.5.38",
"description": "",
"main": "lib/index.js",
"module": "es/index.js",
@ -26,8 +26,8 @@
"license": "ISC",
"dependencies": {
"@antv/async-hook": "^2.1.0",
"@antv/l7-core": "^2.5.37",
"@antv/l7-utils": "^2.5.37",
"@antv/l7-core": "^2.5.38",
"@antv/l7-utils": "^2.5.38",
"@babel/runtime": "^7.7.7",
"@mapbox/geojson-rewind": "^0.4.0",
"@turf/helpers": "^6.1.4",

View File

@ -1,6 +1,6 @@
{
"name": "@antv/l7-three",
"version": "2.5.37",
"version": "2.5.38",
"description": "three for L7 ",
"keywords": [
"3D",
@ -44,9 +44,9 @@
},
"homepage": "https://github.com/antvis/L7#readme",
"dependencies": {
"@antv/l7-core": "^2.5.37",
"@antv/l7-layers": "^2.5.37",
"@antv/l7-scene": "^2.5.37",
"@antv/l7-core": "^2.5.38",
"@antv/l7-layers": "^2.5.38",
"@antv/l7-scene": "^2.5.38",
"@babel/runtime": "^7.7.7",
"inversify": "^5.0.1",
"reflect-metadata": "^0.1.13",

View File

@ -23,7 +23,7 @@ export default class ThreeJSLayer
}>
implements ILayer {
public type: string = 'custom';
protected threeRenderService: IThreeRenderService;
public threeRenderService: IThreeRenderService;
// 构建 threejs 的 scene
private scene: Scene = new Scene();
private renderer: WebGLRenderer;
@ -198,6 +198,10 @@ export default class ThreeJSLayer
return this;
}
public getRenderCamera() {
return this.threeRenderService.getRenderCamera();
}
public addAnimateMixer(mixer: AnimationMixer) {
this.animateMixer.push(mixer);
}

View File

@ -6,7 +6,7 @@ import {
} from './threeRenderService';
export default class ThreeRender {
private threeRenderService: IThreeRenderService;
public threeRenderService: IThreeRenderService;
constructor(scene: Scene) {
const sceneContainer = scene.getServiceContainer();
sceneContainer

View File

@ -1,6 +1,6 @@
{
"name": "@antv/l7-utils",
"version": "2.5.37",
"version": "2.5.38",
"description": "",
"main": "lib/index.js",
"module": "es/index.js",

View File

@ -0,0 +1,446 @@
// @ts-ignore
import { Scene, AMap } from '@antv/l7';
import { GaodeMap, Mapbox } from '@antv/l7-maps';
import { ThreeLayer, ThreeRender } from '@antv/l7-three';
import * as React from 'react';
// import { DirectionalLight, Scene as ThreeScene } from 'three';
import * as THREE from 'three';
// tslint:disable-next-line:no-submodule-imports
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
import { FBXLoader } from 'three/examples/jsm/loaders/FBXLoader';
import { animate, easeInOut } from 'popmotion';
interface IView {
lng: number;
lat: number;
pitch: number;
rotation: number;
zoom: number;
}
function changeValue(
startValue: number | IView,
endValue: number | IView,
duration: number = 500,
callback: any,
complete?: any,
) {
if (typeof startValue === 'number') {
animate({
from: {
v: startValue,
},
to: {
v: endValue,
},
ease: easeInOut,
duration,
onUpdate: (o) => {
callback(o.v);
},
onComplete: () => {
complete && complete();
},
});
} else {
animate({
from: {
lng: startValue.lng,
lat: startValue.lat,
pitch: startValue.pitch,
rotation: startValue.rotation,
zoom: startValue.zoom,
},
to: {
lng: (endValue as IView).lng,
lat: (endValue as IView).lat,
pitch: (endValue as IView).pitch,
rotation: (endValue as IView).rotation,
zoom: (endValue as IView).zoom,
},
ease: easeInOut,
duration,
onUpdate: (o) => {
callback(o);
},
onComplete: () => {
complete && complete();
},
});
}
}
export default class Aspace extends React.Component {
// @ts-ignore
private scene: Scene;
public componentWillUnmount() {
this.scene.destroy();
}
public async componentDidMount() {
const raycaster = new THREE.Raycaster();
let lng = 120.1;
let lat = 30.265;
const scene = new Scene({
id: 'map',
map: new GaodeMap({
center: [lng, lat],
pitch: 70,
rotation: 220,
zoom: 16,
}),
});
this.scene = scene;
scene.registerRenderService(ThreeRender);
let mouse = new THREE.Vector2();
let zspace: THREE.Object3D,
aspace: THREE.Object3D,
ASpaceTextMesh: THREE.Object3D,
ZSpaceTextMesh: THREE.Object3D;
scene.on('loaded', () => {
const center = scene.getCenter();
const threeJSLayer = new ThreeLayer({
enableMultiPassRenderer: false,
// @ts-ignore
onAddMeshes: (threeScene: THREE.Scene, layer: ThreeLayer) => {
threeScene.add(new THREE.AmbientLight(0xffffff));
const sunlight = new THREE.DirectionalLight(0xffffff, 0.25);
sunlight.position.set(0, 80000000, 100000000);
sunlight.matrixWorldNeedsUpdate = true;
threeScene.add(sunlight);
// map
// https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*gA0NRbuOF5cAAAAAAAAAAAAAARQnAQ
// height
// https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*eYFaRYlnnOUAAAAAAAAAAAAAARQnAQ
let image = new Image();
image.crossOrigin = '';
image.src =
'https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*eYFaRYlnnOUAAAAAAAAAAAAAARQnAQ';
image.onload = () => {
let canvas: HTMLCanvasElement = document.createElement('canvas');
canvas.width = image.width;
canvas.height = image.height;
let ctx = canvas.getContext('2d') as CanvasRenderingContext2D;
ctx.drawImage(image, 0, 0, image.width, image.height);
let heightData = ctx.getImageData(0, 0, image.width, image.height)
.data;
let s = 53000;
var geometry = new THREE.PlaneGeometry(s, s, 255, 255);
geometry.vertices.map((v, i) => {
let r = heightData[i * 4];
let g = heightData[i * 4 + 1];
let b = heightData[i * 4 + 2];
let h =
-10000.0 +
(r * 255.0 * 256.0 * 256.0 + g * 255.0 * 256.0 + b * 255.0) *
0.1;
h = h / 20 - 127600;
h = Math.max(0, h);
v.z = h;
});
var material = new THREE.MeshPhongMaterial({
transparent: true,
// opacity: 0.6,
map: new THREE.TextureLoader().load(
'https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*gA0NRbuOF5cAAAAAAAAAAAAAARQnAQ',
),
});
var plane = new THREE.Mesh(geometry, material);
layer.setObjectLngLat(plane, [120.1008, 30.2573], 0);
plane.position.z = 10;
threeScene.add(plane);
};
// 使用 Three.js glTFLoader 加载模型
const loader = new GLTFLoader();
loader.load(
'https://gw.alipayobjects.com/os/bmw-prod/3ca0a546-92d8-4ba0-a89c-017c218d5bea.gltf',
(gltf) => {
const antModel = gltf.scene;
layer.adjustMeshToMap(antModel);
layer.setMeshScale(antModel, 20, 20, 20);
layer.setObjectLngLat(
antModel,
[center.lng - 0.002, center.lat],
0,
);
const animations = gltf.animations;
if (animations && animations.length) {
const mixer = new THREE.AnimationMixer(antModel);
const animation = animations[1];
const action = mixer.clipAction(animation);
action.play();
layer.addAnimateMixer(mixer);
}
antModel.rotation.y = Math.PI;
// 向场景中添加模型
threeScene.add(antModel);
// 重绘图层
layer.render();
},
);
let v = `
varying vec2 vUv;
varying vec4 worldPosition;
void main() {
vUv = uv;
worldPosition = modelMatrix * vec4(position, 1.0);
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}`;
let f = `
varying vec2 vUv;
varying vec4 worldPosition;
uniform vec3 color;
void main() {
gl_FragColor = vec4(color, fract(worldPosition.z / 50.0));
}`;
let shadermaterial = new THREE.ShaderMaterial({
uniforms: {
color: {
value: new THREE.Vector3(0.21372549, 0.34705882, 0.56470588),
},
},
vertexShader: v,
fragmentShader: f,
});
let fbxLoaded = new FBXLoader();
// load ZSpace
fbxLoaded.load(
'https://gw.alipayobjects.com/os/bmw-prod/af1652c9-3c4f-4e73-ac4c-1f78fefbaf6a.fbx',
(gltf) => {
zspace = gltf;
layer.adjustMeshToMap(zspace);
// @ts-ignore
zspace.children[0].material = shadermaterial;
layer.setMeshScale(zspace, 10, 10, 10);
layer.setObjectLngLat(zspace, [120.1015, 30.2661], 0);
zspace.rotation.x = Math.PI * 2;
zspace.rotation.z = -Math.PI * (-2 / 15);
threeScene.add(zspace);
},
);
fbxLoaded.load(
'https://gw.alipayobjects.com/os/bmw-prod/11d6e4c1-bd5b-4dc1-bae5-ac51c14e9056.fbx',
(model) => {
aspace = model;
layer.adjustMeshToMap(aspace);
// @ts-ignore
aspace.children[0].material = shadermaterial;
layer.setMeshScale(aspace, 8, 8, 8);
layer.setObjectLngLat(aspace, [120.099, 30.261], 0);
aspace.rotation.x = Math.PI * 2;
aspace.rotation.z = -Math.PI * (3 / 15);
threeScene.add(aspace);
},
);
let textLoader = new THREE.FontLoader();
textLoader.load(
'https://gw.alipayobjects.com/os/bmw-prod/0a3f46eb-294e-4d95-87f2-052c26ad4bf1.json',
(font) => {
let aspaceGeo = new THREE.TextGeometry('ASpace', {
size: 360, //字号大小,一般为大写字母的高度
height: 50, //文字的厚度
font: font, //字体,默认是'helvetiker',需对应引用的字体文件
bevelThickness: 10, //倒角厚度
bevelSize: 10, //倒角宽度
curveSegments: 30, //弧线分段数,使得文字的曲线更加光滑
bevelEnabled: true, //布尔值,是否使用倒角,意为在边缘处斜切
});
aspaceGeo.center();
let zspaceGeo = new THREE.TextGeometry('ZSpace', {
size: 360, //字号大小,一般为大写字母的高度
height: 50, //文字的厚度
font: font, //字体,默认是'helvetiker',需对应引用的字体文件
bevelThickness: 10, //倒角厚度
bevelSize: 10, //倒角宽度
curveSegments: 30, //弧线分段数,使得文字的曲线更加光滑
bevelEnabled: true, //布尔值,是否使用倒角,意为在边缘处斜切
});
zspaceGeo.center();
let fontMat = new THREE.MeshPhongMaterial({
color: 0xcccccc,
shininess: 60,
specular: 0xcccccc,
});
const testHeight = 900;
ASpaceTextMesh = new THREE.Mesh(aspaceGeo, fontMat);
ASpaceTextMesh.rotation.x = Math.PI / 2;
ASpaceTextMesh.rotation.y = (-Math.PI * 3) / 4;
layer.setObjectLngLat(
ASpaceTextMesh,
[120.099, 30.261],
testHeight,
);
threeScene.add(ASpaceTextMesh);
ZSpaceTextMesh = new THREE.Mesh(zspaceGeo, fontMat);
ZSpaceTextMesh.rotation.x = Math.PI / 2;
ZSpaceTextMesh.rotation.y = (-Math.PI * 3) / 4;
layer.setObjectLngLat(
ZSpaceTextMesh,
[120.103, 30.2661],
testHeight,
);
threeScene.add(ZSpaceTextMesh);
getH(0, 200);
function getH(h1: number, h2: number) {
changeValue(
h1,
h2,
1000,
(h: number) => {
ASpaceTextMesh.position.z = testHeight + h;
ZSpaceTextMesh.position.z = testHeight + h;
},
() => {
setTimeout(() => getH(h2, h1), 10);
},
);
}
},
);
},
})
.source({
type: 'FeatureCollection',
features: [
{
type: 'Feature',
properties: {},
geometry: {
type: 'Point',
coordinates: [111.4453125, 32.84267363195431],
},
},
],
})
.animate(true);
scene.addLayer(threeJSLayer);
// @ts-ignore
let currentCamera = threeJSLayer.threeRenderService.getRenderCamera();
let currentView: IView = {
lng: center.lng,
lat: center.lat,
pitch: 70,
rotation: 220,
zoom: 16,
};
scene.on('zoom', () => {
let cen = scene.getCenter();
currentView.lng = cen.lng;
currentView.lat = cen.lat;
currentView.pitch = scene.getPitch();
currentView.zoom = scene.getZoom();
});
// @ts-ignore
scene?.map?.on('camerachange', (e: any) => {
// @ts-ignore
currentCamera = threeJSLayer.threeRenderService.getRenderCamera();
currentView.pitch = scene.getPitch();
});
let ASpaceView = {
lng: 120.108009,
lat: 30.251129,
pitch: 83,
rotation: 225,
zoom: 16,
};
let ZSpaceView = {
lng: 120.110726,
lat: 30.256481,
pitch: 80,
rotation: 220,
zoom: 16,
};
scene.on('click', (ev) => {
// @ts-ignore
let size = scene?.map?.getSize();
mouse.x = (ev.pixel.x / size.width) * 2 - 1;
mouse.y = -(ev.pixel.y / size.height) * 2 + 1;
raycaster.setFromCamera(mouse, currentCamera);
var intersects = raycaster.intersectObjects([zspace, aspace], true);
if (intersects.length > 0) {
let object = intersects[0].object;
if (object.name === 'Z空间') {
selectSpace(currentView, ZSpaceView, ZSpaceTextMesh);
} else {
selectSpace(currentView, ASpaceView, ASpaceTextMesh);
}
}
});
function selectSpace(
currentView: IView,
targetView: IView,
spaceText?: THREE.Object3D,
) {
if (spaceText) {
changeValue(
spaceText.rotation.y,
spaceText.rotation.y + Math.PI * 2,
500,
(r: number) => {
spaceText.rotation.y = r;
},
);
}
changeValue(currentView, targetView, 500, (view: IView) => {
scene.setCenter([view.lng, view.lat]);
scene.setPitch(view.pitch);
scene.setRotation(view.rotation);
scene.setZoom(view.zoom);
currentView.lng = view.lng;
currentView.lat = view.lat;
currentView.pitch = view.pitch;
currentView.rotation = view.rotation;
currentView.zoom = view.zoom;
});
}
});
}
public render() {
return (
<div
id="map"
style={{
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
}}
/>
);
}
}

View File

@ -5,8 +5,11 @@ import AMap2Model from './Components/amap2_three';
import MapboxModel from './Components/mapbox_three';
import ThreeRender from './Components/threeRender';
import Aspace from './Components/aspace';
storiesOf('3D 模型', module)
.add('ThreeJS Render', () => <ThreeRender />, {})
.add('高德模型1.x', () => <AMapModel />, {})
.add('高德模型2.x', () => <AMap2Model />, {})
.add('Mapbox模型', () => <MapboxModel />, {});
.add('Mapbox模型', () => <MapboxModel />, {})
.add('Aspace', () => <Aspace />, {});