diff --git a/packages/renderer/src/regl/index.ts b/packages/renderer/src/regl/index.ts index 355ca3ff84..8d367581c4 100644 --- a/packages/renderer/src/regl/index.ts +++ b/packages/renderer/src/regl/index.ts @@ -224,6 +224,7 @@ export default class ReglRendererService implements IRendererService { }, framebuffer: null, }); + this.gl._refresh(); } public setBaseState() { diff --git a/stories/3D_Model/Components/amap_car.tsx b/stories/3D_Model/Components/amap_car.tsx new file mode 100644 index 0000000000..bf22fa01a3 --- /dev/null +++ b/stories/3D_Model/Components/amap_car.tsx @@ -0,0 +1,255 @@ +// @ts-ignore +import { Scene, PolygonLayer } 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 { animate, easeInOut } from 'popmotion'; + +let isTravel = false; +// @ts-ignore +function travel( + // @ts-ignore + mesh, + // @ts-ignore + path, + // @ts-ignore + duration, + // @ts-ignore + callback, +) { + if (path.length < 2 || isTravel) return; + isTravel = true; + let startIndex = 0; + const len = path.length; + const currentP = path[0], + nextP = path[1]; + const t = duration / len; + //@ts-ignore + move(currentP, nextP); + // @ts-ignore + function move(currentP, nextP) { + animate({ + from: { + x: currentP.x, + y: currentP.y, + z: currentP.z, + }, + to: { + x: nextP.x, + y: nextP.y, + z: nextP.z, + }, + ease: easeInOut, + duration: t, + repeatType: 'loop', + onUpdate: (o) => { + mesh.position.set(o.x, o.y, o.z); + }, + onComplete: () => { + startIndex++; + if (startIndex < len - 1) { + const currentP = path[startIndex], + nextP = path[startIndex + 1]; + mesh.lookAt(nextP); + + move(currentP, nextP); + } else { + isTravel = false; + callback && callback(); + } + }, + }); + } +} + +export default class GlTFThreeJSDemo extends React.Component { + // @ts-ignore + private scene: Scene; + + public componentWillUnmount() { + this.scene.destroy(); + } + + public async componentDidMount() { + const scene = new Scene({ + id: 'map', + map: new GaodeMap({ + center: [112, 35.39847], + pitch: 45, + rotation: 30, + zoom: 5, + }), + }); + this.scene = scene; + // scene.registerRenderService(ThreeRender); + scene.on('loaded', () => { + scene.registerRenderService(ThreeRender); + + fetch( + 'https://gw.alipayobjects.com/os/basement_prod/d2e0e930-fd44-4fca-8872-c1037b0fee7b.json', + ) + .then((d) => d.json()) + .then((data) => { + const polygonlayer = new PolygonLayer({ + name: '01', + zIndex: -1, + }) + .source(data) + .color('name', [ + '#2E8AE6', + '#69D1AB', + '#DAF291', + '#FFD591', + '#FF7A45', + '#CF1D49', + ]) + .shape('fill') + // .select(true) + .style({ + opacity: 1.0, + }); + scene.addLayer(polygonlayer); + }); + + const threeJSLayer = new ThreeLayer({ + enableMultiPassRenderer: false, + onAddMeshes: (threeScene, layer) => { + // 添加光 + 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); + + const lineData = [ + [116.71874999999999, 26.745610382199022], + [117.3779296875, 28.8831596093235], + [115.75195312499999, 31.466153715024294], + [113.466796875, 33.32134852669881], + [113.9501953125, 35.85343961959182], + [115.400390625, 38.272688535980976], + [116.5869140625, 40.3130432088809], + [115.6201171875, 42.261049162113856], + [112.236328125, 42.94033923363181], + [109.3798828125, 41.04621681452063], + [103.84277343749999, 39.80853604144591], + [98.9208984375, 39.842286020743394], + [95.2294921875, 40.713955826286046], + [91.7138671875, 39.87601941962116], + [90.8349609375, 37.125286284966805], + [90.3076171875, 35.88905007936091], + [90.703125, 33.284619968887675], + [92.94433593749999, 31.98944183792288], + [96.2841796875, 32.21280106801518], + [98.87695312499999, 32.0639555946604], + [102.919921875, 28.459033019728043], + [107.9736328125, 28.497660832963472], + [108.10546875, 24.206889622398023], + [109.072265625, 23.039297747769726], + [112.763671875, 24.44714958973082], + [116.54296874999999, 25.958044673317843], + ]; + // @ts-ignore + const lineCoordData = lineData.map((d) => { + // @ts-ignore + return layer.lnglatToCoord(d); + }); + + // @ts-ignore + const rawPoints = []; + // @ts-ignore + lineCoordData.map((d) => { + rawPoints.push(new THREE.Vector3(d[0], d[1], 0)); + return ''; + }); + // @ts-ignore + const curve = new THREE.CatmullRomCurve3(rawPoints); + const points = curve.getPoints(200); + const geometry = new THREE.BufferGeometry().setFromPoints(points); + + const material = new THREE.LineBasicMaterial({ color: 0xff0000 }); + + const line = new THREE.LineLoop(geometry, material); + threeScene.add(line); + + // 使用 Three.js glTFLoader 加载模型 + // const loader = new GLTFLoader(); + // loader.load( + // 'https://gw.alipayobjects.com/os/antvdemo/assets/gltf/truck/CesiumMilkTruck.gltf', // Truck + // gltf => { + // // 根据 GeoJSON 数据放置模型 + // const gltfScene = gltf.scene.clone(); + // // setDouble(gltfScene); + // layer.getSource().data.dataArray.forEach(() => { + // layer.adjustMeshToMap(gltfScene); + // gltfScene.scale.set(500000, 500000, 500000); + + // const animations = gltf.animations; + // if (animations && animations.length) { + // const mixer = new THREE.AnimationMixer(gltfScene); + // // @ts-ignore + // for (let i = 0; i < animations.length; i++) { + // const animation = animations[i]; + + // // There's .3333 seconds junk at the tail of the Monster animation that + // // keeps it from looping cleanly. Clip it at 3 seconds + + // const action = mixer.clipAction(animation); + + // action.play(); + // } + // layer.addAnimateMixer(mixer); + // } + + // // 向场景中添加模型 + // threeScene.add(gltfScene); + // }); + + // travelLoop(); + // function travelLoop() { + // travel(gltfScene, points, 5000, () => { + // travelLoop(); + // }); + // } + // // 重绘图层 + // // layer.render(); + // } + // ); + }, + }).source({ + type: 'FeatureCollection', + features: [ + { + type: 'Feature', + properties: {}, + geometry: { + type: 'Point', + coordinates: [112, 35.39847], + }, + }, + ], + }); + // .animate(true); + scene.addLayer(threeJSLayer); + }); + } + + public render() { + return ( +
+ ); + } +} diff --git a/stories/3D_Model/model.stories.tsx b/stories/3D_Model/model.stories.tsx index 40b6355f36..885b1977bb 100644 --- a/stories/3D_Model/model.stories.tsx +++ b/stories/3D_Model/model.stories.tsx @@ -6,6 +6,7 @@ import MapboxModel from './Components/mapbox_three'; import ThreeRender from './Components/threeRender'; import Threemap from './Components/threejsmap'; import Aspace from './Components/aspace'; +import Car from './Components/amap_car'; storiesOf('3D 模型', module) .add('ThreeJS Render', () => , {}) @@ -13,4 +14,5 @@ storiesOf('3D 模型', module) .add('高德模型2.x', () => , {}) .add('Mapbox模型', () => , {}) .add('Aspace', () => , {}) + .add('Car', () => , {}) .add('Threemap', () => , {}); diff --git a/stories/Map/components/amap2demo_lineStreet.tsx b/stories/Map/components/amap2demo_lineStreet.tsx index 38b4b3b6ea..682017678b 100644 --- a/stories/Map/components/amap2demo_lineStreet.tsx +++ b/stories/Map/components/amap2demo_lineStreet.tsx @@ -1,4 +1,4 @@ -import { LineLayer, Scene } from '@antv/l7'; +import { PointLayer, PolygonLayer, LineLayer, Scene } from '@antv/l7'; import { GaodeMap, GaodeMapV2, Mapbox } from '@antv/l7-maps'; import * as React from 'react'; @@ -14,54 +14,163 @@ export default class Amap2demo_lineStreet extends React.Component { const scene = new Scene({ id: 'map', map: new GaodeMap({ - center: [120.19382669582967, 30.258134], + center: [120.15, 30.246], pitch: 0, - zoom: 16, + zoom: 13.5, style: 'dark', + pitchEnable: false, + rotation: -90, }), }); this.scene = scene; + scene.addImage( + 'westLakeBuilding', + 'https://gw.alipayobjects.com/zos/bmw-prod/8c3f6415-c1ca-4f7e-8ac6-89571ac75309.svg', + ); + scene.addImage( + 'arrow', + 'https://gw.alipayobjects.com/zos/bmw-prod/ce83fc30-701f-415b-9750-4b146f4b3dd6.svg', + ); + scene.addImage( + 'shop', + 'https://gw.alipayobjects.com/zos/bmw-prod/238e7c7c-c26c-454c-9341-35d466c4b991.svg', + ); + scene.addImage( + 'hospital', + 'https://gw.alipayobjects.com/zos/bmw-prod/fd08bf28-f73e-4b9c-ba8d-2c73d4fca6dc.svg', + ); + scene.addImage( + 'westlake', + 'https://gw.alipayobjects.com/zos/bmw-prod/7b011298-454d-431b-9637-ab23a752e731.svg', + ); + scene.addImage( + 'ship', + 'https://gw.alipayobjects.com/zos/bmw-prod/104cfca2-f3c5-49e8-b084-d339f4ba1adc.svg', + ); + scene.addImage( + 'travel', + 'https://gw.alipayobjects.com/zos/bmw-prod/904d047a-16a5-461b-a921-98fa537fc04a.svg', + ); + scene.addImage( + 'pavilion', + 'https://gw.alipayobjects.com/zos/bmw-prod/8839795d-43d9-46c5-a5b1-95bf9a1146a0.svg', + ); + scene.addImage( + 'museum', + 'https://gw.alipayobjects.com/zos/bmw-prod/5436a335-8ec3-40e4-9c93-16d0f844b0e7.svg', + ); + scene.addImage( + 'bridge', + 'https://gw.alipayobjects.com/zos/bmw-prod/b88e6f2f-ad12-4980-969e-3849cbcd28c6.svg', + ); + scene.addImage( + 'school', + 'https://gw.alipayobjects.com/zos/bmw-prod/948e665d-ab1e-4010-b75a-236057837bec.svg', + ); + scene.on('loaded', () => { + fetch( + 'https://gw.alipayobjects.com/os/bmw-prod/67130c6c-7f49-4680-915c-54e69730861d.json', + ) + .then((data) => data.json()) + .then( + ({ + lakeBorderData, + lakeData, + landData, + westLakePoiData, + poiData, + }) => { + const lakeLayer = new PolygonLayer() + .source(lakeData) + .shape('fill') + .color('#1E90FF') + .style({ + opacity: 0.4, + opacityLinear: { + enable: true, + dir: 'out', // in - out + }, + }); + const landLayer = new PolygonLayer() + .source(landData) + .shape('fill') + .color('#3CB371') + .style({ + opacity: 0.4, + opacityLinear: { + enable: true, + dir: 'in', // in - out + }, + }); + + const lakeBorderLayer = new PolygonLayer() + .source(lakeBorderData) + .shape('fill') + .color('#ccc') + .style({ + opacity: 0.5, + opacityLinear: { + enable: true, + dir: 'in', // in - out + }, + }); + + const westLakePoiLayer = new PointLayer({ zIndex: 1 }) + .source(westLakePoiData, { + parser: { + type: 'json', + x: 'lng', + y: 'lat', + }, + }) + .shape('type', (v) => v) + .size(40); + + const poiLayer = new PointLayer({ zIndex: 1 }) + .source(poiData, { + parser: { + type: 'json', + x: 'lng', + y: 'lat', + }, + }) + .shape('type', (v) => v) + .size(10); + + scene.addLayer(lakeLayer); + scene.addLayer(lakeBorderLayer); + scene.addLayer(landLayer); + scene.addLayer(westLakePoiLayer); + scene.addLayer(poiLayer); + }, + ); + fetch( 'https://gw.alipayobjects.com/os/basement_prod/40ef2173-df66-4154-a8c0-785e93a5f18e.json', ) .then((res) => res.json()) .then((data) => { - scene.addImage( - '00', - 'https://gw.alipayobjects.com/zos/bmw-prod/ce83fc30-701f-415b-9750-4b146f4b3dd6.svg', - ); - scene.addImage( - '01', - 'https://gw.alipayobjects.com/zos/basement_prod/30580bc9-506f-4438-8c1a-744e082054ec.svg', - ); - scene.addImage( - '02', - 'https://gw.alipayobjects.com/zos/bmw-prod/ce83fc30-701f-415b-9750-4b146f4b3dd6.svg', - ); + const colors = ['#66c2a4', '#2ca25f', '#006d2c']; // @ts-ignore const layer = new LineLayer({}) .source(data) - .size(5) + .size(2.5) .shape('line') - .texture('00') - .color('#25d8b7') + .texture('arrow') + .color('', () => { + return colors[Math.floor(Math.random() * colors.length)]; + }) .animate({ interval: 1, // 间隔 duration: 1, // 持续时间,延时 trailLength: 2, // 流线长度 }) .style({ - // opacity: 0.5, - // opacity: 0, + opacity: 0.6, lineTexture: true, // 开启线的贴图功能 iconStep: 20, // 设置贴图纹理的间距 - // lineType: 'dash', - // dashArray: [5, 5], - // textureBlend: 'replace', - // textureBlend: 'normal', - borderWidth: 0.4, // 默认文 0,最大有效值为 0.5 borderColor: '#fff', // 默认为 #ccc });