mirror of https://gitee.com/antv-l7/antv-l7
refactor: 更新threejs 依赖
This commit is contained in:
parent
f0061a5ec0
commit
2f19f2c419
|
@ -102,6 +102,7 @@
|
|||
"rollup-pluginutils": "^2.8.2",
|
||||
"sass-loader": "^7.1.0",
|
||||
"style-loader": "^1.0.0",
|
||||
"three": "0.115.0",
|
||||
"styled-components": "^3.4.6",
|
||||
"stylelint": "^9.5.0",
|
||||
"stylelint-config-recommended": "^2.1.0",
|
||||
|
|
|
@ -40,7 +40,6 @@
|
|||
"lodash": "^4.17.15",
|
||||
"merge-json-schemas": "1.0.0",
|
||||
"polyline-miter-util": "^1.0.1",
|
||||
"three": "^0.111.0",
|
||||
"reflect-metadata": "^0.1.13"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
|
@ -8,7 +8,6 @@ import LineLayer from './line/index';
|
|||
import PointLayer from './point';
|
||||
import PolygonLayer from './polygon';
|
||||
import RasterLayer from './raster';
|
||||
import ThreeJSLayer from './three';
|
||||
|
||||
// import ConfigSchemaValidationPlugin from './plugins/ConfigSchemaValidationPlugin';
|
||||
import DataMappingPlugin from './plugins/DataMappingPlugin';
|
||||
|
@ -138,5 +137,4 @@ export {
|
|||
ImageLayer,
|
||||
RasterLayer,
|
||||
HeatmapLayer,
|
||||
ThreeJSLayer,
|
||||
};
|
||||
|
|
|
@ -1,176 +0,0 @@
|
|||
/**
|
||||
* inspired by threebox & Mapbox examples
|
||||
* @see https://github.com/peterqliu/threebox/blob/master/src/Threebox.js
|
||||
* @see https://github.com/peterqliu/threebox/blob/master/examples/Object3D.html
|
||||
*/
|
||||
import { IMercator } from '@antv/l7-core';
|
||||
import {
|
||||
AnimationMixer,
|
||||
Camera,
|
||||
Matrix4,
|
||||
PCFSoftShadowMap,
|
||||
PerspectiveCamera,
|
||||
Scene,
|
||||
WebGLRenderer,
|
||||
} from 'three';
|
||||
import BaseLayer from '../core/BaseLayer';
|
||||
const DEG2RAD = Math.PI / 180;
|
||||
export default class ThreeJSLayer extends BaseLayer<{
|
||||
onAddMeshes: (threeScene: Scene, layer: ThreeJSLayer) => void;
|
||||
}> {
|
||||
public name: string = 'ThreeJSLayer';
|
||||
public type: string = 'custom';
|
||||
|
||||
private scene: Scene;
|
||||
private camera: Camera;
|
||||
private renderer: WebGLRenderer;
|
||||
private animateMixer: AnimationMixer[] = [];
|
||||
|
||||
// 地图中点墨卡托坐标
|
||||
private center: IMercator;
|
||||
|
||||
// 初始状态相机变换矩阵
|
||||
private cameraTransform: Matrix4;
|
||||
|
||||
/**
|
||||
* 根据模型
|
||||
*/
|
||||
public getModelMatrix(
|
||||
lnglat: [number, number],
|
||||
altitude: number = 0,
|
||||
rotation: [number, number, number] = [0, 0, 0],
|
||||
scale: [number, number, number] = [1, 1, 1],
|
||||
): Matrix4 {
|
||||
return new Matrix4().fromArray(
|
||||
this.mapService.getModelMatrix(
|
||||
lnglat,
|
||||
altitude,
|
||||
rotation,
|
||||
scale,
|
||||
this.center,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
public buildModels() {
|
||||
const canvas = this.rendererService.getCanvas();
|
||||
const gl = this.rendererService.getGLContext();
|
||||
if (canvas && gl) {
|
||||
const center = this.mapService.getCenter();
|
||||
this.center = this.mapService.lngLatToMercator(
|
||||
[center.lng, center.lat],
|
||||
0,
|
||||
);
|
||||
const { x, y, z } = this.center;
|
||||
this.cameraTransform = new Matrix4().makeTranslation(x, y, z);
|
||||
|
||||
this.renderer = new WebGLRenderer({
|
||||
canvas,
|
||||
context: gl,
|
||||
antialias: true,
|
||||
});
|
||||
|
||||
// L7 负责 clear
|
||||
this.renderer.autoClear = false;
|
||||
// 是否需要 gamma correction?
|
||||
this.renderer.gammaFactor = 2.2;
|
||||
this.renderer.shadowMap.enabled = true;
|
||||
// this.renderer.shadowMap.type = PCFSoftShadowMap;
|
||||
|
||||
this.scene = new Scene();
|
||||
this.camera = new PerspectiveCamera(45, 1, 1, 2000000);
|
||||
|
||||
const config = this.getLayerConfig();
|
||||
if (config && config.onAddMeshes) {
|
||||
config.onAddMeshes(this.scene, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
public renderModels() {
|
||||
return this.mapService.constructor.name === 'AMapService'
|
||||
? this.renderAMapModels()
|
||||
: this.renderMapboxModels();
|
||||
}
|
||||
public renderMapboxModels() {
|
||||
// const { width, height } = this.rendererService.getViewportSize();
|
||||
// this.renderer.setSize(width, height, false);
|
||||
|
||||
const gl = this.rendererService.getGLContext();
|
||||
gl.frontFace(gl.CCW);
|
||||
gl.enable(gl.CULL_FACE);
|
||||
gl.cullFace(gl.FRONT);
|
||||
|
||||
// 同步相机
|
||||
const mercatorMatrix = new Matrix4().fromArray(
|
||||
// @ts-ignore
|
||||
this.mapService.map.transform.customLayerMatrix(),
|
||||
);
|
||||
|
||||
this.camera.projectionMatrix = mercatorMatrix.multiply(
|
||||
this.cameraTransform,
|
||||
);
|
||||
this.renderer.state.reset();
|
||||
this.renderer.render(this.scene, this.camera);
|
||||
this.rendererService.setBaseState();
|
||||
this.animateMixer.forEach((mixer: AnimationMixer) => {
|
||||
mixer.update(this.getTime());
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
public renderAMapModels() {
|
||||
const gl = this.rendererService.getGLContext();
|
||||
gl.frontFace(gl.CCW);
|
||||
gl.enable(gl.CULL_FACE);
|
||||
gl.cullFace(gl.BACK);
|
||||
|
||||
// @ts-ignore
|
||||
const mapCamera = this.mapService.map.getCameraState();
|
||||
const camera = this.camera;
|
||||
let { pitch, rotation } = mapCamera;
|
||||
const { fov, near, far, height, aspect } = mapCamera;
|
||||
pitch *= DEG2RAD;
|
||||
rotation *= DEG2RAD;
|
||||
// @ts-ignore
|
||||
camera.fov = (180 * fov) / Math.PI;
|
||||
// @ts-ignore
|
||||
camera.aspect = aspect;
|
||||
// @ts-ignore
|
||||
camera.near = near;
|
||||
// @ts-ignore
|
||||
camera.far = far;
|
||||
// @ts-ignore
|
||||
camera.updateProjectionMatrix();
|
||||
camera.position.z = height * Math.cos(pitch);
|
||||
camera.position.x = height * Math.sin(pitch) * Math.sin(rotation);
|
||||
camera.position.y = -height * Math.sin(pitch) * Math.cos(rotation);
|
||||
camera.up.x = -Math.cos(pitch) * Math.sin(rotation);
|
||||
camera.up.y = Math.cos(pitch) * Math.cos(rotation);
|
||||
camera.up.z = Math.sin(pitch);
|
||||
camera.lookAt(0, 0, 0);
|
||||
camera.position.x += mapCamera.position.x;
|
||||
camera.position.y += -mapCamera.position.y;
|
||||
this.renderer.state.reset();
|
||||
this.renderer.autoClear = false;
|
||||
this.renderer.render(this.scene, this.camera);
|
||||
this.animateMixer.forEach((mixer: AnimationMixer) => {
|
||||
mixer.update(this.getTime());
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
public addAnimateMixer(mixer: AnimationMixer) {
|
||||
this.animateMixer.push(mixer);
|
||||
}
|
||||
protected getConfigSchema() {
|
||||
return {
|
||||
properties: {
|
||||
// opacity: {
|
||||
// type: 'altitude',
|
||||
// minimum: 0,
|
||||
// maximum: 100,
|
||||
// },
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
|
@ -39,10 +39,13 @@
|
|||
},
|
||||
"homepage": "https://github.com/antvis/L7#readme",
|
||||
"dependencies": {
|
||||
"three": "^0.115.0",
|
||||
|
||||
"@antv/l7": "2.1.15",
|
||||
"@babel/runtime": "^7.7.7",
|
||||
"rollup": "^2.3.3",
|
||||
"rollup-plugin-less": "^1.1.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"three": "^0.115.0"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ export default class GlTFThreeJSDemo extends React.Component {
|
|||
// 根据 GeoJSON 数据放置模型
|
||||
layer.getSource().data.dataArray.forEach(({ coordinates }) => {
|
||||
const gltfScene = gltf.scene;
|
||||
gltfScene.applyMatrix(
|
||||
gltfScene.applyMatrix4(
|
||||
// 生成模型矩阵
|
||||
layer.getModelMatrix(
|
||||
[coordinates[0], coordinates[1]], // 经纬度坐标
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Scene, PolygonLayer, ThreeJSLayer } from '@antv/l7';
|
||||
import { PolygonLayer, Scene } from '@antv/l7';
|
||||
import { GaodeMap, Mapbox } from '@antv/l7-maps';
|
||||
import { ThreeLayer, ThreeRender } from '@antv/l7-three';
|
||||
import * as React from 'react';
|
||||
|
@ -75,7 +75,7 @@ export default class GlTFThreeJSDemo extends React.Component {
|
|||
// 根据 GeoJSON 数据放置模型
|
||||
layer.getSource().data.dataArray.forEach(({ coordinates }) => {
|
||||
const gltfScene = gltf.scene.clone();
|
||||
gltfScene.applyMatrix(
|
||||
gltfScene.applyMatrix4(
|
||||
// 生成模型矩阵
|
||||
layer.getModelMatrix(
|
||||
[coordinates[0], coordinates[1]], // 经纬度坐标
|
||||
|
|
|
@ -87,7 +87,7 @@ export default class GlTFThreeJSDemo extends React.Component {
|
|||
// 根据 GeoJSON 数据放置模型
|
||||
layer.getSource().data.dataArray.forEach(({ coordinates }) => {
|
||||
const gltfScene = gltf.scene;
|
||||
gltfScene.applyMatrix(
|
||||
gltfScene.applyMatrix4(
|
||||
// 生成模型矩阵
|
||||
layer.getModelMatrix(
|
||||
[coordinates[0], coordinates[1]], // 经纬度坐标
|
||||
|
|
|
@ -5,10 +5,8 @@ import Arc2DLineDemo from './components/Arc2DLine';
|
|||
import ArcLineDemo from './components/Arcline';
|
||||
import CityBuildingLayerDemo from './components/citybuilding';
|
||||
import Column from './components/column';
|
||||
import CustomThreeJSDemo from './components/CustomThreeJSLayer';
|
||||
import DashLineDemo from './components/dash';
|
||||
import DataUpdate from './components/data_update';
|
||||
import GlTFThreeJSDemo from './components/GlTFThreeJSDemo';
|
||||
import HeatMapDemo from './components/HeatMap';
|
||||
import HeatMapDemo3D from './components/heatmap3d';
|
||||
import HeatMap3D_2 from './components/heatmap2';
|
||||
|
@ -49,7 +47,5 @@ storiesOf('图层', module)
|
|||
.add('网格热力图', () => <HexagonLayerDemo />)
|
||||
.add('栅格', () => <RasterLayerDemo />)
|
||||
.add('图片', () => <ImageLayerDemo />)
|
||||
.add('Three.js 图层', () => <CustomThreeJSDemo />)
|
||||
.add('glTF 图层', () => <GlTFThreeJSDemo />)
|
||||
.add('网格测试', () => <GridTest />)
|
||||
.add('世界地图', () => <WorldDemo />);
|
||||
|
|
|
@ -1,102 +0,0 @@
|
|||
import { PointLayer, Scene, ThreeJSLayer } from '@antv/l7';
|
||||
import { GaodeMap, Mapbox } from '@antv/l7-maps';
|
||||
import * as React from 'react';
|
||||
import {
|
||||
BackSide,
|
||||
BoxGeometry,
|
||||
DirectionalLight,
|
||||
Mesh,
|
||||
MeshLambertMaterial,
|
||||
Matrix4,
|
||||
Scene as ThreeScene,
|
||||
} from 'three';
|
||||
// @ts-ignore
|
||||
import data from '../data/data.json';
|
||||
|
||||
export default class ThreeJSLayerComponent extends React.Component {
|
||||
// @ts-ignore
|
||||
private scene: Scene;
|
||||
|
||||
public componentWillUnmount() {
|
||||
this.scene.destroy();
|
||||
}
|
||||
|
||||
public async componentDidMount() {
|
||||
const response = await fetch(
|
||||
'https://gw.alipayobjects.com/os/basement_prod/d3564b06-670f-46ea-8edb-842f7010a7c6.json',
|
||||
);
|
||||
const pointsData = await response.json();
|
||||
|
||||
const scene = new Scene({
|
||||
id: 'map',
|
||||
map: new Mapbox({
|
||||
center: [120.19382669582967, 30.258134],
|
||||
pitch: 60,
|
||||
rotation: 30,
|
||||
zoom: 16,
|
||||
}),
|
||||
});
|
||||
this.scene = scene;
|
||||
|
||||
// const pointLayer = new PointLayer({})
|
||||
// .source(pointsData, {
|
||||
// cluster: true,
|
||||
// })
|
||||
// .shape('circle')
|
||||
// .scale('point_count', {
|
||||
// type: 'quantile',
|
||||
// })
|
||||
// .size('point_count', [5, 10, 15, 20, 25])
|
||||
// .color('red')
|
||||
// .style({
|
||||
// opacity: 0.3,
|
||||
// strokeWidth: 1,
|
||||
// });
|
||||
// scene.addLayer(pointLayer);
|
||||
|
||||
const threeJSLayer = new ThreeJSLayer({
|
||||
enableMultiPassRenderer: false,
|
||||
onAddMeshes: (threeScene: ThreeScene, layer: ThreeJSLayer) => {
|
||||
// 添加光源
|
||||
const directionalLight1 = new DirectionalLight(0xffffff);
|
||||
directionalLight1.position.set(0, -70, 100).normalize();
|
||||
threeScene.add(directionalLight1);
|
||||
const directionalLight2 = new DirectionalLight(0xffffff);
|
||||
directionalLight2.position.set(0, 70, 100).normalize();
|
||||
threeScene.add(directionalLight2);
|
||||
|
||||
const geometry = new BoxGeometry(20, 20, 20);
|
||||
const redMaterial = new MeshLambertMaterial({
|
||||
color: 0xffffff,
|
||||
side: BackSide,
|
||||
});
|
||||
const cube = new Mesh(geometry, redMaterial);
|
||||
cube.applyMatrix(
|
||||
layer.getModelMatrix([120.19382669582967, 30.258134], 10, [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
]) as Matrix4,
|
||||
);
|
||||
cube.frustumCulled = false;
|
||||
threeScene.add(cube);
|
||||
},
|
||||
}).source(pointsData);
|
||||
scene.addLayer(threeJSLayer);
|
||||
}
|
||||
|
||||
public render() {
|
||||
return (
|
||||
<div
|
||||
id="map"
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,96 +0,0 @@
|
|||
import { Scene, ThreeJSLayer } from '@antv/l7';
|
||||
import { Mapbox } from '@antv/l7-maps';
|
||||
import * as React from 'react';
|
||||
import { DirectionalLight, Matrix4, Scene as ThreeScene } from 'three';
|
||||
// tslint:disable-next-line:no-submodule-imports
|
||||
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
|
||||
|
||||
export default class GlTFThreeJSDemo extends React.Component {
|
||||
// @ts-ignore
|
||||
private scene: Scene;
|
||||
|
||||
public componentWillUnmount() {
|
||||
this.scene.destroy();
|
||||
}
|
||||
|
||||
public async componentDidMount() {
|
||||
const response = await fetch(
|
||||
'https://gw.alipayobjects.com/os/basement_prod/893d1d5f-11d9-45f3-8322-ee9140d288ae.json',
|
||||
);
|
||||
const pointsData = await response.json();
|
||||
|
||||
const scene = new Scene({
|
||||
id: 'map',
|
||||
map: new Mapbox({
|
||||
center: [121.434765, 31.256735],
|
||||
pitch: 45,
|
||||
rotation: 30,
|
||||
zoom: 18,
|
||||
}),
|
||||
});
|
||||
this.scene = scene;
|
||||
|
||||
const threeJSLayer = new ThreeJSLayer({
|
||||
enableMultiPassRenderer: false,
|
||||
onAddMeshes: (threeScene: ThreeScene, layer: ThreeJSLayer) => {
|
||||
// 添加光源
|
||||
const directionalLight1 = new DirectionalLight(0xffffff);
|
||||
directionalLight1.position.set(0, -70, 100).normalize();
|
||||
threeScene.add(directionalLight1);
|
||||
const directionalLight2 = new DirectionalLight(0xffffff);
|
||||
directionalLight2.position.set(0, 70, 100).normalize();
|
||||
threeScene.add(directionalLight2);
|
||||
|
||||
// 使用 Three.js glTFLoader 加载模型
|
||||
const loader = new GLTFLoader();
|
||||
loader.load(
|
||||
// 'https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/DamagedHelmet/glTF/DamagedHelmet.gltf',
|
||||
// 'https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/AnimatedCube/glTF/AnimatedCube.gltf',
|
||||
'https://gw.alipayobjects.com/os/antvdemo/assets/gltf/radar/34M_17.gltf',
|
||||
// 'https://gw.alipayobjects.com/os/bmw-prod/3ca0a546-92d8-4ba0-a89c-017c218d5bea.gltf',
|
||||
(gltf) => {
|
||||
// 根据 GeoJSON 数据放置模型
|
||||
layer.getSource().data.dataArray.forEach(({ coordinates }) => {
|
||||
const gltfScene = gltf.scene.clone();
|
||||
gltfScene.applyMatrix(
|
||||
// 生成模型矩阵
|
||||
layer.getModelMatrix(
|
||||
[coordinates[0], coordinates[1]], // 经纬度坐标
|
||||
0, // 高度,单位米
|
||||
[Math.PI / 2, 0, 0], // 沿 XYZ 轴旋转角度
|
||||
[5, 5, 5], // 沿 XYZ 轴缩放比例
|
||||
),
|
||||
);
|
||||
// 向场景中添加模型
|
||||
threeScene.add(gltfScene);
|
||||
});
|
||||
// 重绘图层
|
||||
layer.render();
|
||||
},
|
||||
);
|
||||
},
|
||||
}).source(pointsData, {
|
||||
parser: {
|
||||
type: 'json',
|
||||
x: 'longitude',
|
||||
y: 'latitude',
|
||||
},
|
||||
});
|
||||
scene.addLayer(threeJSLayer);
|
||||
}
|
||||
|
||||
public render() {
|
||||
return (
|
||||
<div
|
||||
id="map"
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue