From 6a04210de6f36562839851bf4738ff4313ad6621 Mon Sep 17 00:00:00 2001 From: YiQianYao <42212176+2912401452@users.noreply.github.com> Date: Tue, 2 Aug 2022 19:05:27 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B8=B2=E6=9F=93=E6=B5=81=E7=A8=8B?= =?UTF-8?q?=E5=BC=82=E6=AD=A5=E6=94=B9=E9=80=A0=E3=80=81=E9=83=A8=E5=88=86?= =?UTF-8?q?=E6=94=AF=E6=8C=81=20worker=20(#1224)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 去处事件节流 * feat: 创建图层流程改造 + worker 功能验证 * style: lint style * feat: 修改 worker 引入 * feat: 调整 worker 的拼接 * style: lint style * feat: 修改 source 构建流程为异步 * style: lint style * feat: 在点图层中去除 global 的耦合 * style: lint style * fix: 修复更新 style 的同时更新了 option 带来的问题 * style: lint style * feat: 拆除 arc3d 地球模式和普通模式的耦合 * style: lint style * feat: 修改 worker * style: lint style * feat: 优化图层创建渲染流程 * style: lint style * Merge branch 'workspace' into tileDemo * style: style lint * feat: 改在点图层的创建流程 * style: lint style * style: lint style * chore: worker helper (#1241) * chore: worker helper * chore: 修改注册流程 * chore: 修改打包方式 * chore: 集成打包环境 * style: lint style * feat: add worker pool failed * style: lint style * style: lint style * feat: 更新 worker 的使用 * chore: 更新 scripts 标签 (#1242) * feat: remove utils triangulation * feat: 完成 pointLayer/earthLayer 的异步改造 * style: lint style * style: lint style * style: lint style * chore: 修改 worker 执行函数 (#1246) * chore: 修改 worker 执行函数 * chore: remove console * feat: 完成线图层和线图层的异步创建流程改造 * style: lint style * style: lint style * feat: 完成 polygon 创建流程的异步改造 * style: lint style * feat: 完成 heatmap 创建流程的异步改造 * style: lint style * feat: 完成 citybuildingLayer 图层创建的异步改造 * style: lint style * feat: 完成 imageLayer 创建异步改造 * style: lint style * feat: 完成 ImageLayer/RasterLayer 创建的异步改造 * style: lint style * feat: 完成 geometryLayer 创建的异步改造 * style: lint style * feat: 完成 WindLayer 创建的异步改造 * style: lint style * feat: 完成 tileLayer 瓦片图层创建图层的异步改造 * style: lint style * feat: 调整 worker 调用的参数和 worker 代码的位置 * style: lint style * chore: 调整 worker 代码结构 * style: lint style * feat: 梳理完善 layer 的 modelName * style: lint style * chore: 调整部分 modeName 的命名 * feat: 线图层的 lineModel 支持 worker 计算 * style: lint style * feat: 完善 source 异步改造,增加测试 * style: lint style * feat: 支持 polygonFill 的 worker 计算 * style: lint style * feat: tile point/line/polygon 支持 worker 计算 * style: lint style * chore: 调整 worker 目录结构 * style: lint style * chore: 修改 worker 打包路径 * feat: 增加 ISrource 时间的类型定义 * chore: change function getPureDescriptors -> getDescriptorsWithOutFunc * feat: 完善类型定义,去除额外 worker 代码 * chore: worker 注册放到 utils 里面 (#1253) * chore: 代码清理 * style: lint style * fix: 修复 encodeData 可能的空值 * feat: 地球模式的点、线图层兼容写法 * style: lint style * feat: 完成对 dataImage 的异步改造 * fix: 修复 demo 中对时序数据的使用 * style: lint style * fix: 修复点图层文字重新布局未重绘问题 * fix: 修复 pointLayer fillImage 失效 * style: lint style * chore: 在官网 demo 中去除 multipass * chore: 调整官网 demo 效果 * style: lint style * chore: 调整官网 demo * style: lint style * fix: 修复 layerModel 使用的报错 * chore: update l7plot version Co-authored-by: lvisei --- .eslintignore | 5 + .storybook/preview.ts | 5 +- babel.config.js | 115 +-- build/rollup-plugin-inline-worker.js | 16 + build/rollup.config.js | 75 +- build/rollup.config.worker.js | 64 ++ demos/tutorial/control/demo/meta.json | 2 +- examples/engine/three/demo/space_click.js | 2 +- .../gallery/animate/demo/plane_animate.js | 13 +- examples/gallery/animate/demo/timeline.js | 129 +-- examples/line/isoline/demo/ele_dark.js | 11 - examples/polygon/fill/demo/usa.js | 2 +- examples/tile/vector/demo/line.js | 3 +- examples/tile/vector/demo/point.js | 3 +- examples/tile/vector/demo/polygon.js | 3 +- package.json | 27 +- packages/component/package.json | 6 +- .../core/src/services/layer/ILayerService.ts | 18 +- .../services/layer/IStyleAttributeService.ts | 5 + .../services/layer/StyleAttributeService.ts | 87 +- .../core/src/services/scene/SceneService.ts | 2 - .../src/services/source/ISourceService.ts | 5 + packages/l7/package.json | 6 +- packages/l7/src/index.ts | 2 + packages/l7/tsconfig.build.json | 2 +- packages/layers/package.json | 7 +- packages/layers/src/Geometry/index.ts | 7 +- .../layers/src/Geometry/models/billboard.ts | 25 +- packages/layers/src/Geometry/models/plane.ts | 29 +- packages/layers/src/Geometry/models/sprite.ts | 23 +- packages/layers/src/canvas/index.ts | 7 +- packages/layers/src/citybuliding/building.ts | 8 +- .../layers/src/citybuliding/models/build.ts | 22 +- packages/layers/src/core/BaseLayer.ts | 112 ++- packages/layers/src/core/BaseModel.ts | 4 +- packages/layers/src/core/interface.ts | 2 + packages/layers/src/core/triangulation.ts | 11 +- packages/layers/src/earth/index.ts | 7 +- .../layers/src/earth/models/atmosphere.ts | 26 +- packages/layers/src/earth/models/base.ts | 23 +- .../layers/src/earth/models/bloomsphere.ts | 26 +- packages/layers/src/heatmap/index.ts | 11 +- packages/layers/src/heatmap/models/grid.ts | 25 +- packages/layers/src/heatmap/models/grid3d.ts | 23 +- packages/layers/src/heatmap/models/heatmap.ts | 23 +- packages/layers/src/heatmap/models/hexagon.ts | 22 +- packages/layers/src/image/index.ts | 7 +- packages/layers/src/image/models/dataImage.ts | 21 +- packages/layers/src/image/models/image.ts | 25 +- packages/layers/src/line/index.ts | 8 +- packages/layers/src/line/models/arc.ts | 30 +- packages/layers/src/line/models/arc_3d.ts | 28 +- packages/layers/src/line/models/arcmini.ts | 133 --- .../layers/src/line/models/earthArc_3d.ts | 30 +- .../layers/src/line/models/great_circle.ts | 22 +- packages/layers/src/line/models/half.ts | 26 +- packages/layers/src/line/models/index.ts | 3 - packages/layers/src/line/models/line.ts | 44 +- packages/layers/src/line/models/linearline.ts | 50 +- packages/layers/src/line/models/simpleLine.ts | 29 +- packages/layers/src/line/models/tile.ts | 42 +- packages/layers/src/line/models/wall.ts | 25 +- .../src/line/shaders/line_arcmini_frag.glsl | 40 - .../src/line/shaders/line_arcmini_vert.glsl | 101 -- packages/layers/src/mask/index.ts | 7 +- packages/layers/src/mask/models/fill.ts | 23 +- .../layers/src/plugins/DataMappingPlugin.ts | 27 +- .../layers/src/plugins/DataSourcePlugin.ts | 27 +- .../layers/src/plugins/LayerModelPlugin.ts | 46 +- .../layers/src/plugins/PixelPickingPlugin.ts | 4 +- packages/layers/src/point/index.ts | 33 +- .../layers/src/point/models/earthExtrude.ts | 33 +- packages/layers/src/point/models/earthFill.ts | 40 +- packages/layers/src/point/models/extrude.ts | 26 +- packages/layers/src/point/models/fill.ts | 49 +- packages/layers/src/point/models/fillmage.ts | 36 +- packages/layers/src/point/models/icon-font.ts | 146 --- packages/layers/src/point/models/image.ts | 23 +- packages/layers/src/point/models/index.ts | 3 - packages/layers/src/point/models/normal.ts | 23 +- packages/layers/src/point/models/radar.ts | 41 +- .../layers/src/point/models/simplePoint.ts | 23 +- packages/layers/src/point/models/text.ts | 60 +- packages/layers/src/point/models/tile.ts | 49 +- packages/layers/src/polygon/index.ts | 7 +- packages/layers/src/polygon/models/extrude.ts | 21 +- packages/layers/src/polygon/models/fill.ts | 48 +- packages/layers/src/polygon/models/ocean.ts | 23 +- packages/layers/src/polygon/models/tile.ts | 48 +- packages/layers/src/polygon/models/water.ts | 23 +- packages/layers/src/raster/image.ts | 106 --- packages/layers/src/raster/index.ts | 7 +- packages/layers/src/raster/models/raster.ts | 25 +- packages/layers/src/raster/raster2d.ts | 118 --- .../src/tile/manager/tileLayerManager.ts | 3 + .../src/tile/manager/tilePickerManager.ts | 1 + packages/layers/src/tile/tileFactory/base.ts | 4 - packages/layers/src/tile/tileFactory/point.ts | 2 - .../src/tile/tileFactory/rasterDataLayer.ts | 7 +- .../src/tile/tileFactory/vectorLayer.ts | 7 +- packages/layers/src/utils/geo.ts | 60 -- packages/layers/src/wind/index.ts | 7 +- packages/layers/src/wind/models/wind.ts | 39 +- packages/map/package.json | 6 +- packages/maps/package.json | 6 +- packages/mini/package.json | 6 +- packages/renderer/package.json | 6 +- packages/scene/package.json | 6 +- packages/source/package.json | 6 +- packages/source/src/index.ts | 3 +- packages/source/src/parser/json.ts | 32 + packages/source/src/source.ts | 31 +- packages/three/package.json | 6 +- packages/utils/package.json | 14 +- packages/utils/src/geo.ts | 64 ++ packages/utils/src/index.ts | 2 + packages/utils/src/math.ts | 3 + packages/utils/src/worker-helper/index.ts | 44 + .../utils/src/worker-helper/worker-map.ts | 10 + .../utils/src/workers/commonFeatureFunc.ts | 30 + .../utils/src/workers/extrude_polyline.ts | 866 ++++++++++++++++++ packages/utils/src/workers/index.ts | 30 + packages/utils/src/workers/lineModel.ts | 175 ++++ packages/utils/src/workers/pointFillModel.ts | 149 +++ .../utils/src/workers/polygonFillModel.ts | 115 +++ packages/utils/src/workers/triangulation.ts | 74 ++ stories/Map/components/amap2demo_image.tsx | 10 +- stories/Map/components/amap2demo_styleMap.tsx | 3 +- stories/Map/components/amap2demo_text.tsx | 2 +- stories/Map/components/bugfix.tsx | 56 +- .../components/{Map.tsx => Points.tsx} | 54 +- .../components/updataPointsTimeLine.tsx | 4 +- stories/MapPerformance/map.stories.tsx | 2 +- stories/layerbuild/components/Billboard.tsx | 79 ++ .../layerbuild/components/CityBuilding.tsx | 67 ++ stories/layerbuild/components/Heatmap.tsx | 64 ++ stories/layerbuild/components/Heatmap3d.tsx | 64 ++ stories/layerbuild/components/HeatmapGrid.tsx | 85 ++ .../layerbuild/components/HeatmapGrid3d.tsx | 83 ++ .../layerbuild/components/HeatmapHexagon.tsx | 78 ++ stories/layerbuild/components/ImageLayer.tsx | 48 + stories/layerbuild/components/Line.tsx | 57 ++ stories/layerbuild/components/LineArc.tsx | 57 ++ stories/layerbuild/components/LineArc3d.tsx | 57 ++ .../layerbuild/components/LineEarthArc3D.tsx | 93 ++ .../layerbuild/components/LineGreatCircle.tsx | 57 ++ stories/layerbuild/components/LineHalf.tsx | 62 ++ stories/layerbuild/components/LineLinear.tsx | 70 ++ stories/layerbuild/components/LineSimple.tsx | 57 ++ stories/layerbuild/components/LineTile.tsx | 61 ++ stories/layerbuild/components/LineWall.tsx | 57 ++ stories/layerbuild/components/Plane.tsx | 108 +++ stories/layerbuild/components/Points.tsx | 95 ++ .../components/PointsEarthExtrude.tsx | 106 +++ .../layerbuild/components/PointsEarthFill.tsx | 106 +++ .../layerbuild/components/PointsExtrude.tsx | 59 ++ .../layerbuild/components/PointsFillImage.tsx | 65 ++ .../layerbuild/components/PointsIconFont.tsx | 74 ++ stories/layerbuild/components/PointsImage.tsx | 65 ++ .../layerbuild/components/PointsNormal.tsx | 60 ++ stories/layerbuild/components/PointsRadar.tsx | 61 ++ .../layerbuild/components/PointsSimple.tsx | 60 ++ stories/layerbuild/components/PointsText.tsx | 60 ++ .../layerbuild/components/PointsTextTile.tsx | 64 ++ stories/layerbuild/components/PointsTile.tsx | 60 ++ stories/layerbuild/components/Polygon.tsx | 61 ++ .../layerbuild/components/PolygonExtrude.tsx | 62 ++ .../layerbuild/components/PolygonOcean.tsx | 65 ++ stories/layerbuild/components/PolygonTile.tsx | 60 ++ .../layerbuild/components/PolygonWater.tsx | 66 ++ .../layerbuild/components/RasterDataTile.tsx | 104 +++ .../layerbuild/components/RasterImageTile.tsx | 51 ++ stories/layerbuild/components/RasterLayer.tsx | 92 ++ stories/layerbuild/components/SourceTest.tsx | 415 +++++++++ stories/layerbuild/components/Sprite.tsx | 53 ++ stories/layerbuild/components/Wind.tsx | 68 ++ stories/layerbuild/map.stories.tsx | 111 +++ tsconfig.json | 3 +- tslint.json | 3 +- 179 files changed, 6567 insertions(+), 1691 deletions(-) create mode 100644 .eslintignore create mode 100644 build/rollup-plugin-inline-worker.js create mode 100644 build/rollup.config.worker.js delete mode 100644 packages/layers/src/line/models/arcmini.ts delete mode 100644 packages/layers/src/line/shaders/line_arcmini_frag.glsl delete mode 100644 packages/layers/src/line/shaders/line_arcmini_vert.glsl delete mode 100644 packages/layers/src/point/models/icon-font.ts delete mode 100644 packages/layers/src/raster/image.ts delete mode 100644 packages/layers/src/raster/raster2d.ts delete mode 100644 packages/layers/src/utils/geo.ts create mode 100644 packages/utils/src/math.ts create mode 100644 packages/utils/src/worker-helper/index.ts create mode 100644 packages/utils/src/worker-helper/worker-map.ts create mode 100644 packages/utils/src/workers/commonFeatureFunc.ts create mode 100644 packages/utils/src/workers/extrude_polyline.ts create mode 100644 packages/utils/src/workers/index.ts create mode 100644 packages/utils/src/workers/lineModel.ts create mode 100644 packages/utils/src/workers/pointFillModel.ts create mode 100644 packages/utils/src/workers/polygonFillModel.ts create mode 100644 packages/utils/src/workers/triangulation.ts rename stories/MapPerformance/components/{Map.tsx => Points.tsx} (56%) create mode 100644 stories/layerbuild/components/Billboard.tsx create mode 100644 stories/layerbuild/components/CityBuilding.tsx create mode 100644 stories/layerbuild/components/Heatmap.tsx create mode 100644 stories/layerbuild/components/Heatmap3d.tsx create mode 100644 stories/layerbuild/components/HeatmapGrid.tsx create mode 100644 stories/layerbuild/components/HeatmapGrid3d.tsx create mode 100644 stories/layerbuild/components/HeatmapHexagon.tsx create mode 100644 stories/layerbuild/components/ImageLayer.tsx create mode 100644 stories/layerbuild/components/Line.tsx create mode 100644 stories/layerbuild/components/LineArc.tsx create mode 100644 stories/layerbuild/components/LineArc3d.tsx create mode 100644 stories/layerbuild/components/LineEarthArc3D.tsx create mode 100644 stories/layerbuild/components/LineGreatCircle.tsx create mode 100644 stories/layerbuild/components/LineHalf.tsx create mode 100644 stories/layerbuild/components/LineLinear.tsx create mode 100644 stories/layerbuild/components/LineSimple.tsx create mode 100644 stories/layerbuild/components/LineTile.tsx create mode 100644 stories/layerbuild/components/LineWall.tsx create mode 100644 stories/layerbuild/components/Plane.tsx create mode 100644 stories/layerbuild/components/Points.tsx create mode 100644 stories/layerbuild/components/PointsEarthExtrude.tsx create mode 100644 stories/layerbuild/components/PointsEarthFill.tsx create mode 100644 stories/layerbuild/components/PointsExtrude.tsx create mode 100644 stories/layerbuild/components/PointsFillImage.tsx create mode 100644 stories/layerbuild/components/PointsIconFont.tsx create mode 100644 stories/layerbuild/components/PointsImage.tsx create mode 100644 stories/layerbuild/components/PointsNormal.tsx create mode 100644 stories/layerbuild/components/PointsRadar.tsx create mode 100644 stories/layerbuild/components/PointsSimple.tsx create mode 100644 stories/layerbuild/components/PointsText.tsx create mode 100644 stories/layerbuild/components/PointsTextTile.tsx create mode 100644 stories/layerbuild/components/PointsTile.tsx create mode 100644 stories/layerbuild/components/Polygon.tsx create mode 100644 stories/layerbuild/components/PolygonExtrude.tsx create mode 100644 stories/layerbuild/components/PolygonOcean.tsx create mode 100644 stories/layerbuild/components/PolygonTile.tsx create mode 100644 stories/layerbuild/components/PolygonWater.tsx create mode 100644 stories/layerbuild/components/RasterDataTile.tsx create mode 100644 stories/layerbuild/components/RasterImageTile.tsx create mode 100644 stories/layerbuild/components/RasterLayer.tsx create mode 100644 stories/layerbuild/components/SourceTest.tsx create mode 100644 stories/layerbuild/components/Sprite.tsx create mode 100644 stories/layerbuild/components/Wind.tsx create mode 100644 stories/layerbuild/map.stories.tsx diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000000..196f07b8e7 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,5 @@ +# don't ever lint node_modules +node_modules +# don't lint build output (make sure it's set to your correct build folder name) +dist + diff --git a/.storybook/preview.ts b/.storybook/preview.ts index 83444bc2cb..febd5ba076 100644 --- a/.storybook/preview.ts +++ b/.storybook/preview.ts @@ -21,8 +21,11 @@ addParameters({ }); // automatically import all files ending in *.stories.tsx + // const req = require.context('../stories', true, /\.stories\.tsx$/); -const req = require.context('../stories/Map', true, /\.stories\.tsx$/); +const req = require.context('../stories/layerbuild', true, /\.stories\.tsx$/); +// const req = require.context('../stories/Map', true, /\.stories\.tsx$/); +// const req = require.context('../stories/MapPerformance', true, /\.stories\.tsx$/); // const req = require.context('../stories/tile', true, /\.stories\.tsx$/); function loadStories() { diff --git a/babel.config.js b/babel.config.js index 411f735e9e..2216dec9ed 100644 --- a/babel.config.js +++ b/babel.config.js @@ -1,12 +1,12 @@ // @see https://babeljs.io/docs/en/next/config-files#project-wide-configuration -module.exports = api => { +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 (isSite) { return { presets: [ @@ -14,8 +14,8 @@ module.exports = api => { [ '@babel/preset-react', { - development: isCommonJS - } + development: isCommonJS, + }, ], // 'babel-preset-gatsby', { // silence: true @@ -28,8 +28,8 @@ module.exports = api => { [ '@babel/plugin-proposal-decorators', { - legacy: true - } + legacy: true, + }, ], [ // import glsl as raw text @@ -38,11 +38,11 @@ module.exports = api => { extensions: [ // 由于使用了 TS 的 resolveJsonModule 选项,JSON 可以直接引入,不需要当作纯文本 '.pbf', - '.glsl' - ] - } - ] - ] + '.glsl', + ], + }, + ], + ], }; } @@ -53,24 +53,24 @@ module.exports = api => { { // https://babeljs.io/docs/en/babel-preset-env#usebuiltins // useBuiltIns: 'usage', - ...isCDNBundle ? { corejs: 3 } : {}, + ...(isCDNBundle ? { corejs: 3 } : {}), useBuiltIns: isCDNBundle ? 'usage' : false, // set `modules: false` when building CDN bundle, let rollup do commonjs works // @see https://github.com/rollup/rollup-plugin-babel#modules - modules: (isCDNBundle || isESModule) ? false : 'auto', + modules: isCDNBundle || isESModule ? false : 'auto', targets: { chrome: 58, - browsers: [ 'ie >= 11' ] - } - } + browsers: ['ie >= 11'], + }, + }, ], [ '@babel/preset-react', { - development: isCommonJS - } + development: isCommonJS, + }, ], - '@babel/preset-typescript' + '@babel/preset-typescript', ], plugins: [ isCDNBundle ? {} : '@babel/plugin-transform-runtime', @@ -83,61 +83,70 @@ module.exports = api => { [ '@babel/plugin-proposal-decorators', { - legacy: true - } + legacy: true, + }, ], [ '@babel/plugin-proposal-class-properties', { // @see https://github.com/storybookjs/storybook/issues/6069#issuecomment-472544973 - loose: false - } + loose: false, + }, ], '@babel/plugin-syntax-dynamic-import', // let rollup do commonjs works // @see https://github.com/rollup/rollup-plugin-babel#modules - (isCDNBundle || isESModule) ? {} : '@babel/plugin-transform-modules-commonjs', + isCDNBundle || isESModule + ? {} + : '@babel/plugin-transform-modules-commonjs', // 开发模式下以原始文本引入,便于调试 - isCDNBundle ? {} : [ - // import glsl as raw text - 'babel-plugin-inline-import', - { - extensions: [ - // 由于使用了 TS 的 resolveJsonModule 选项,JSON 可以直接引入,不需要当作纯文本 - // '.json', - '.glsl' - ] - } - ], - isCDNBundle ? {} : [ - 'transform-import-css-l7' - // 'transform-import-styles' // babel 编译将样式打包到js - ], + isCDNBundle + ? {} + : [ + // import glsl as raw text + 'babel-plugin-inline-import', + { + extensions: [ + // 由于使用了 TS 的 resolveJsonModule 选项,JSON 可以直接引入,不需要当作纯文本 + // '.json', + '.glsl', + '.worker.js', + ], + }, + ], + isCDNBundle + ? {} + : [ + 'transform-import-css-l7', + // 'transform-import-styles' // babel 编译将样式打包到js + ], [ // @see https://github.com/babel/babel/issues/8741#issuecomment-509041135 'const-enum', { - transform: 'constObject' - } + transform: 'constObject', + }, ], // 按需引用 @see https://github.com/lodash/babel-plugin-lodash - 'lodash' + 'lodash', // 内联 WebGL 常量 @see https://www.npmjs.com/package/babel-plugin-inline-webgl-constants // isCDNBundle ? 'inline-webgl-constants' : {}, ], ignore: [ // /node_modules\/(?![kdbush|supercluster|async])/, 'node_modules', - ...!isTest ? [ - '**/*.test.tsx', - '**/*.test.ts', - '**/*.story.tsx', - '__snapshots__', - '__tests__', - '__stories__', - '**/*/__snapshots__', - '**/*/__tests__' - ] : [] - ] + ...(!isTest + ? [ + '**/*.test.tsx', + '**/*.test.ts', + '**/*.story.tsx', + '__snapshots__', + '__tests__', + '__stories__', + '**/*/__snapshots__', + '**/*/__tests__', + ] + : []), + ], }; }; diff --git a/build/rollup-plugin-inline-worker.js b/build/rollup-plugin-inline-worker.js new file mode 100644 index 0000000000..dc6b152620 --- /dev/null +++ b/build/rollup-plugin-inline-worker.js @@ -0,0 +1,16 @@ +import { createFilter } from 'rollup-pluginutils'; + +export default function inlineWorker(include) { + const filter = createFilter(include); + return { + name: 'inline-worker', + transform(code, id) { + if (!filter(id)) return; + + return { + code: `export default ${JSON.stringify(code)};`, + map: { mappings: '' }, + }; + }, + }; +} diff --git a/build/rollup.config.js b/build/rollup.config.js index 6c164e5d3b..1a88ea3554 100644 --- a/build/rollup.config.js +++ b/build/rollup.config.js @@ -7,19 +7,18 @@ import { terser } from 'rollup-plugin-terser'; import analyze from 'rollup-plugin-analyzer'; import babel from 'rollup-plugin-babel'; import glsl from './rollup-plugin-glsl'; +import inlineWorker from './rollup-plugin-inline-worker'; import postcss from 'rollup-plugin-postcss'; import url from 'postcss-url'; - const { BUILD, MINIFY } = process.env; const minified = MINIFY === 'true'; const production = BUILD === 'production'; const outputFile = !production ? 'packages/l7/dist/l7-dev.js' : minified - ? 'packages/l7/dist/l7.js' - : 'packages/l7/dist/l7-dev.js'; - + ? 'packages/l7/dist/l7.js' + : 'packages/l7/dist/l7-dev.js'; function resolveFile(filePath) { return path.join(__dirname, '..', filePath); @@ -33,49 +32,41 @@ module.exports = [ format: 'umd', name: 'L7', globals: { - 'mapbox-gl': 'mapboxgl' - } + 'mapbox-gl': 'mapboxgl', + }, }, - external: [ - 'mapbox-gl' - ], + external: ['mapbox-gl'], treeshake: minified, plugins: [ - alias( - { - resolve: [ '.tsx', '.ts' ], - entries: [ - { - find: /^@antv\/l7-(.*)/, - replacement: resolveFile('packages/$1/src') - }, - { - find: /^@antv\/l7$/, - replacement: resolveFile('packages/l7/src') - } - ] - } - ), + alias({ + resolve: ['.tsx', '.ts'], + entries: [ + { + find: /^@antv\/l7-(.*)/, + replacement: resolveFile('packages/$1/src'), + }, + { + find: /^@antv\/l7$/, + replacement: resolveFile('packages/l7/src'), + }, + ], + }), resolve({ browser: true, preferBuiltins: false, - extensions: [ '.js', '.ts' ] + extensions: ['.js', '.ts'], }), - glsl( - [ '**/*.glsl' ], - true - ), + glsl(['**/*.glsl'], true), + inlineWorker(['**/*.worker.js']), json(), postcss({ extract: false, - plugins: [ - url({ url: 'inline' }) - ] + plugins: [url({ url: 'inline' })], }), // @see https://github.com/rollup/rollup-plugin-node-resolve#using-with-rollup-plugin-commonjs commonjs({ namedExports: { - eventemitter3: [ 'EventEmitter' ], + eventemitter3: ['EventEmitter'], // inversify: [ 'inject', 'injectable', 'postConstruct', 'Container', 'decorate', 'interfaces' ], // @see https://github.com/rollup/rollup-plugin-commonjs/issues/266 lodash: [ @@ -87,22 +78,22 @@ module.exports = [ 'cloneDeep', 'isString', 'isNumber', - 'merge' - ] + 'merge', + ], }, dynamicRequireTargets: [ - 'node_modules/inversify/lib/syntax/binding_{on,when}_syntax.js' - ] + 'node_modules/inversify/lib/syntax/binding_{on,when}_syntax.js', + ], }), babel({ - extensions: [ '.js', '.ts' ] + extensions: ['.js', '.ts'], }), // terser(), minified ? terser() : false, analyze({ summaryOnly: true, - limit: 20 - }) - ] - } + limit: 20, + }), + ], + }, ]; diff --git a/build/rollup.config.worker.js b/build/rollup.config.worker.js new file mode 100644 index 0000000000..c2ccf59313 --- /dev/null +++ b/build/rollup.config.worker.js @@ -0,0 +1,64 @@ +import path from 'path'; +import alias from '@rollup/plugin-alias'; +import json from '@rollup/plugin-json'; +import resolve from '@rollup/plugin-node-resolve'; +import commonjs from '@rollup/plugin-commonjs'; +import { terser } from 'rollup-plugin-terser'; +// import analyze from 'rollup-plugin-analyzer'; +import babel from 'rollup-plugin-babel'; + +const { BUILD } = process.env; +const production = BUILD === 'production'; +const outputFile = production + ? 'packages/utils/dist/l7-utils.worker.js' + : 'packages/utils/dist/l7-utils.worker.js'; +function resolveFile(filePath) { + return path.join(__dirname, '..', filePath); +} + +module.exports = [ + { + input: resolveFile('packages/utils/src/workers/index.ts'), + output: { + file: resolveFile(outputFile), + format: 'iife', + name: 'L7', + }, + context: 'self', + treeshake: true, + plugins: [ + alias({ + resolve: ['.tsx', '.ts'], + entries: [ + { + find: /^@antv\/l7-(.*)\/src\/(.*)/, + replacement: resolveFile('packages/$1/src/$2'), + }, + { + find: /^@antv\/l7-(.*)/, + replacement: resolveFile('packages/$1/src'), + }, + { + find: /^@antv\/l7$/, + replacement: resolveFile('packages/l7/src'), + }, + ], + }), + resolve({ + browser: true, + preferBuiltins: false, + extensions: ['.js', '.ts'], + }), + json(), + commonjs(), + babel({ + extensions: ['.js', '.ts'], + }), + production ? terser() : false, + // analyze({ + // summaryOnly: true, + // limit: 20, + // }), + ], + }, +]; diff --git a/demos/tutorial/control/demo/meta.json b/demos/tutorial/control/demo/meta.json index d921629ac5..f4615691cd 100644 --- a/demos/tutorial/control/demo/meta.json +++ b/demos/tutorial/control/demo/meta.json @@ -6,7 +6,7 @@ "demos": [ { "filename": "amap.js", - "title": "高德底图组件", + "title": "高德底图组件" }, { "filename": "mapbox.js", diff --git a/examples/engine/three/demo/space_click.js b/examples/engine/three/demo/space_click.js index 94a61bc858..7e0194867b 100644 --- a/examples/engine/three/demo/space_click.js +++ b/examples/engine/three/demo/space_click.js @@ -334,7 +334,7 @@ scene.on('loaded', () => { .animate(true); scene.addLayer(threeJSLayer); // @ts-ignore - let currentCamera = threeJSLayer.threeRenderService.getRenderCamera(); + let currentCamera = threeJSLayer.threeRenderService?.getRenderCamera(); const currentView = { lng: center.lng, lat: center.lat, diff --git a/examples/gallery/animate/demo/plane_animate.js b/examples/gallery/animate/demo/plane_animate.js index 2cfaeccdd0..d12ac80b5e 100644 --- a/examples/gallery/animate/demo/plane_animate.js +++ b/examples/gallery/animate/demo/plane_animate.js @@ -93,18 +93,7 @@ scene.on('loaded', () => { }); const flyLine = new LineLayer({ blend: 'additive', - zIndex: 2, - enableMultiPassRenderer: true, - passes: [ - [ - 'bloom', - { - bloomBaseRadio: 0.8, - bloomRadius: 2, - bloomIntensity: 1 - } - ] - ] + zIndex: 2 }) .source(flydata, { parser: { diff --git a/examples/gallery/animate/demo/timeline.js b/examples/gallery/animate/demo/timeline.js index 6c61b6a962..785313a403 100644 --- a/examples/gallery/animate/demo/timeline.js +++ b/examples/gallery/animate/demo/timeline.js @@ -1,7 +1,8 @@ import { Scene, PointLayer } from '@antv/l7'; import { GaodeMap } from '@antv/l7-maps'; -let currentTimeKey = '0000'; +const currentTimeKey = '0000'; let timeKeys = []; +let wrap = null; let layer = null; const modelDatas = {}; const parser = { @@ -21,7 +22,6 @@ const scene = new Scene({ }) }); scene.on('loaded', () => { - setDragBar(); fetch( 'https://gw.alipayobjects.com/os/bmw-prod/82d85bb6-db7c-4583-af26-35b11c7b2d0d.json' @@ -48,12 +48,36 @@ scene.on('loaded', () => { scene.addLayer(layer); - getModelDatas(originData); + layer.on('modelLoaded', () => { + getModelDatas(originData); + + run(); + }); + return ''; }); return ''; }); +function run() { + let count = 0; + const timer = setInterval(() => { + if (count > 47) { + clearInterval(timer); + } + + const key = getTimeKey(count, ''); + const key2 = getTimeKey(count, ':'); + const data = modelDatas[key]; + if (layer && scene && data) { + layer.updateModelData(data); + wrap.innerHTML = key2; + scene.render(); + } + + count++; + }, 300); +} function getModelDatas(originData) { timeKeys.map(timeKey => { @@ -62,103 +86,18 @@ function getModelDatas(originData) { }); } -function updateTime() { - if (layer && scene) { - layer.updateModelData(modelDatas[currentTimeKey]); - scene.render(); - } -} - -function setDragBar() { - const script = document.createElement('script'); - script.setAttribute('type', 'text/javascript'); - script.setAttribute('src', 'https://cdn.bootcss.com/jquery/2.1.1/jquery.min.js'); - script.async = true; - document.head.appendChild(script); - - script.onload = () => { - const bar = document.getElementById('progress'); - const barWidth = bar.getBoundingClientRect().width; - let tag = false, - ox = 0, - left = 0, - bgleft = 0; - const $ = window.$; - $('.progress_btn').mousedown(function(e) { - ox = e.pageX - left; - tag = true; - }); - - $(document).mouseup(function() { tag = false; }); - - $(document).mousemove(function(e) { // 鼠标移动 - if (tag) { - left = e.pageX - ox; - currentTimeKey = setText(left, barWidth); - updateTime(); - } - }); - - $('.progress_bg').click(function(e) { // 鼠标点击 - if (!tag) { - bgleft = $('.progress_bg').offset().left; - left = e.pageX - bgleft; - currentTimeKey = setText(left, barWidth); - updateTime(); - } - }); - return ''; - }; - - - function setText(left, barWidth) { - - if (left <= 0) { - left = 0; - } else if (left > barWidth) { - left = barWidth; - } - const $ = window.$; - $('.progress_btn').css('left', left); - - const time = parseInt((left / barWidth) * 48); - const timeText = getTimeKey(time, ':'); - const timeKey = getTimeKey(time, ''); - $('.text').html(timeText); - return timeKey; - } -} function insetDom() { const mapContrainer = document.getElementById('map'); - const wrap = document.createElement('div'); - wrap.id = 'progress'; + wrap = document.createElement('div'); wrap.style.zIndex = 10; wrap.style.position = 'absolute'; - wrap.style.bottom = '50px'; - wrap.style.left = '10%'; - wrap.style.right = '10%'; - wrap.innerHTML = ` -
-
-
-
00:00
-
- `; + wrap.style.top = '50px'; + wrap.style.left = '5%'; + wrap.style.right = '5%'; + wrap.style.color = '#fff'; + wrap.style.fontSize = '18px'; + wrap.innerHTML = '00:00'; mapContrainer.appendChild(wrap); } diff --git a/examples/line/isoline/demo/ele_dark.js b/examples/line/isoline/demo/ele_dark.js index a4dd683548..72d9e73463 100644 --- a/examples/line/isoline/demo/ele_dark.js +++ b/examples/line/isoline/demo/ele_dark.js @@ -17,17 +17,6 @@ scene.on('loaded', () => { .then(res => res.json()) .then(data => { const layer = new LineLayer({ - enableMultiPassRenderer: true, - passes: [ - [ - 'bloom', - { - bloomBaseRadio: 0.8, - bloomRadius: 2, - bloomIntensity: 1 - } - ] - ] }) .source(data) .size('ELEV', h => { diff --git a/examples/polygon/fill/demo/usa.js b/examples/polygon/fill/demo/usa.js index dbb3f92f77..79b24eea6d 100644 --- a/examples/polygon/fill/demo/usa.js +++ b/examples/polygon/fill/demo/usa.js @@ -20,7 +20,7 @@ scene.on('loaded', () => { const layer = new PolygonLayer({}) .source(data) .scale('density', { - type: 'quantize' + type: 'quantile' }) .color( 'density', color diff --git a/examples/tile/vector/demo/line.js b/examples/tile/vector/demo/line.js index d63950f9ca..99724f6bdc 100644 --- a/examples/tile/vector/demo/line.js +++ b/examples/tile/vector/demo/line.js @@ -23,7 +23,8 @@ scene.on('loaded', () => { type: 'mvt', tileSize: 256, zoomOffset: 0, - maxZoom: 9 + maxZoom: 9, + extent: [ -180, -85.051129, 179, 85.051129 ] } } ) diff --git a/examples/tile/vector/demo/point.js b/examples/tile/vector/demo/point.js index ff4c1a32d5..cd1872f617 100644 --- a/examples/tile/vector/demo/point.js +++ b/examples/tile/vector/demo/point.js @@ -23,7 +23,8 @@ scene.on('loaded', () => { type: 'mvt', tileSize: 256, zoomOffset: 0, - maxZoom: 9 + maxZoom: 9, + extent: [ -180, -85.051129, 179, 85.051129 ] } } ) diff --git a/examples/tile/vector/demo/polygon.js b/examples/tile/vector/demo/polygon.js index 735044dbd0..fe8dec0cfd 100644 --- a/examples/tile/vector/demo/polygon.js +++ b/examples/tile/vector/demo/polygon.js @@ -23,7 +23,8 @@ scene.on('loaded', () => { type: 'mvt', tileSize: 256, zoomOffset: 0, - maxZoom: 9 + maxZoom: 9, + extent: [ -180, -85.051129, 179, 85.051129 ] } } ) diff --git a/package.json b/package.json index e61408d4db..d538e58c08 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "@antv/l7-district": "^2.3.9", "@antv/l7-draw": "2.4.18", "@antv/l7-react": "^2.3.3", - "@antv/l7plot": "^0.0.4", + "@antv/l7plot": "^0.1.0", "@babel/cli": "^7.6.4", "@babel/core": "^7.6.4", "@babel/plugin-proposal-decorators": "^7.6.0", @@ -87,10 +87,10 @@ "glsl-minifier": "^0.0.13", "html-webpack-plugin": "^4.3.0", "husky": "^3.0.9", - "lerc": "^3.0.0", "jest": "^24.9.0", "jest-electron": "^0.1.11", "jest-styled-components": "^6.2.1", + "lerc": "^3.0.0", "lerna": "^3.16.4", "lint-staged": "^9.2.4", "mockjs": "^1.1.0", @@ -148,9 +148,9 @@ "site:publish": "gh-pages -d public", "storybook": "start-storybook -p 6006", "prebuild": "run-p tsc lint", - "build": "yarn clean && lerna run build", + "build": "yarn clean && yarn worker && lerna run build", "postbuild": "yarn build:declarations", - "build:declarations": "lerna exec --stream --no-bail 'tsc --project ./tsconfig.build.json'", + "build:declarations": "lerna run tsc --stream --no-bail", "fix": "run-p -c 'lint:ts-* --fix'", "lint:fix": "prettier --write docs/api/**/*.md docs/api/*.md stories/**/**/*.tsx *.md", "lint:examples": "eslint examples --fix --ext .js", @@ -163,20 +163,22 @@ "version": "lerna version --force-publish --conventional-commits --exact --no-changelog", "version:prerelease": "lerna version --force-publish --exact --conventional-prerelease", "prerelease": "yarn build && yarn bundle", - "release-beta": "yarn run prerelease && lerna publish --dist-tag beta from-package --force-publish && lerna run sync", - "release": "lerna publish from-package --force-publish && lerna run sync", + "release-beta": "yarn run prerelease && lerna publish --dist-tag beta from-package --force-publish && yarn sync", + "release": "lerna publish from-package --force-publish && yarn sync", "release-cdn": "antv-bin upload -n @antv/l7", "test": "cross-env BABEL_ENV=test jest", "test-live": "cross-env BABEL_ENV=test DEBUG_MODE=1 jest --watch", "coveralls": "jest --coverage && cat ./tests/coverage/lcov.info | coveralls", "tsc": "tsc", - "watch": "yarn clean && lerna exec --parallel -- cross-env BABEL_ENV=cjs NODE_ENV=production babel --watch src --root-mode upward --out-dir lib --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments", - "bundle": "cross-env BABEL_ENV=bundle NODE_ENV=production yarn rollup -c build/rollup.config.js --environment BUILD:production,MINIFY:true", - "bundle-dev": "cross-env BABEL_ENV=bundle yarn rollup -c build/rollup.config.js --environment BUILD:production,MINIFY:false", + "watch": "yarn clean && yarn worker && lerna run watch --parallel", + "bundle": "yarn worker && cross-env BABEL_ENV=bundle NODE_ENV=production yarn rollup -c build/rollup.config.js --environment BUILD:production,MINIFY:true", + "bundle-dev": "yarn worker && cross-env BABEL_ENV=bundle yarn rollup -c build/rollup.config.js --environment BUILD:production,MINIFY:false", "bundle:watch": "cross-env BABEL_ENV=bundle yarn rollup -c build/rollup.config.js --watch", "glsl-minify": "yarn glsl-minifier -i build/example.frag -o build/example.min.frag", - "clean": "lerna run clean", - "sync": "lerna run sync" + "worker": "cross-env BABEL_ENV=bundle NODE_ENV=production yarn rollup -c build/rollup.config.worker.js --environment BUILD:production", + "worker:watch": "cross-env BABEL_ENV=bundle NODE_ENV=production yarn rollup -c build/rollup.config.worker.js --environment BUILD:development --watch", + "clean": "lerna run clean --parallel", + "sync": "lerna run sync --parallel" }, "workspaces": [ "packages/*", @@ -207,5 +209,6 @@ }, "tnpm": { "mode": "yarn" - } + }, + "dependencies": {} } diff --git a/packages/component/package.json b/packages/component/package.json index 1dc47bb476..b7036892d8 100644 --- a/packages/component/package.json +++ b/packages/component/package.json @@ -15,9 +15,9 @@ "tsc": "tsc --project tsconfig.build.json", "clean": "rimraf dist; rimraf es; rimraf lib;", "build": "run-p build:*", - "build:cjs": "BABEL_ENV=cjs babel src --root-mode upward --out-dir lib --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments", - "build:esm": "BABEL_ENV=esm babel src --root-mode upward --out-dir es --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments", - "watch": "BABEL_ENV=cjs babel src --watch --root-mode upward --out-dir lib --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments", + "build:cjs": "cross-env BABEL_ENV=cjs NODE_ENV=production babel src --root-mode upward --out-dir lib --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments", + "build:esm": "cross-env BABEL_ENV=esm NODE_ENV=production babel src --root-mode upward --out-dir es --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments", + "watch": "cross-env BABEL_ENV=cjs NODE_ENV=production babel src --watch --root-mode upward --out-dir lib --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments", "lint:ts": "run-p -c lint:ts-*", "test": "jest", "sync": "tnpm sync" diff --git a/packages/core/src/services/layer/ILayerService.ts b/packages/core/src/services/layer/ILayerService.ts index 92b65f91ed..0ec72fdeac 100644 --- a/packages/core/src/services/layer/ILayerService.ts +++ b/packages/core/src/services/layer/ILayerService.ts @@ -59,12 +59,19 @@ export interface IDataState { featureScaleNeedUpdate: boolean; StyleAttrNeedUpdate: boolean; } + +export interface IWorkerOption { + modelType: string; + [key: string]: any; +} export interface ILayerModelInitializationOptions { moduleName: string; vertexShader: string; fragmentShader: string; triangulation: Triangulation; segmentNumber?: number; + workerEnabled?: boolean; + workerOptions?: IWorkerOption; } export interface ILayerModel { @@ -73,8 +80,8 @@ export interface ILayerModel { getUninforms(): IModelUniform; getDefaultStyle(): unknown; getAnimateUniforms(): IModelUniform; - buildModels(): IModel[]; - initModels(): IModel[]; + buildModels(callbackModel: (models: IModel[]) => void): void; + initModels(callbackModel: (models: IModel[]) => void): void; needUpdate(): boolean; clearModels(): void; @@ -161,6 +168,8 @@ export interface ISubLayerInitOptions { coords?: string; sourceLayer?: string; featureId?: string; + + workerEnabled?: boolean; } export interface ITilePickManager { @@ -281,6 +290,7 @@ export interface ILayer { layerType?: string | undefined; isVector?: boolean; triangulation?: Triangulation | undefined; + /** * threejs 适配兼容相关的方法 * @param lnglat @@ -314,7 +324,7 @@ export interface ILayer { buildLayerModel( options: ILayerModelInitializationOptions & Partial, - ): IModel; + ): Promise; createAttrubutes( options: ILayerModelInitializationOptions & Partial, @@ -555,6 +565,8 @@ export interface ILayerConfig { * layer point text 是否是 iconfont 模式 */ iconfont: boolean; + + workerEnabled?: boolean; onHover(pickedFeature: IPickedFeature): void; onClick(pickedFeature: IPickedFeature): void; } diff --git a/packages/core/src/services/layer/IStyleAttributeService.ts b/packages/core/src/services/layer/IStyleAttributeService.ts index d04c1676ac..8990976d51 100644 --- a/packages/core/src/services/layer/IStyleAttributeService.ts +++ b/packages/core/src/services/layer/IStyleAttributeService.ts @@ -216,6 +216,11 @@ export interface IStyleAttributeService { }; elements: IElements; }; + createAttributesAndIndicesAscy( + encodedFeatures: IEncodeFeature[], + segmentNumber?: number, + workerOptions?: any, + ): Promise; /** * 根据 feature range 更新指定属性 */ diff --git a/packages/core/src/services/layer/StyleAttributeService.ts b/packages/core/src/services/layer/StyleAttributeService.ts index c83e963a09..c16573934b 100644 --- a/packages/core/src/services/layer/StyleAttributeService.ts +++ b/packages/core/src/services/layer/StyleAttributeService.ts @@ -1,3 +1,4 @@ +import { executeWorkerTask } from '@antv/l7-utils'; import { inject, injectable, optional } from 'inversify'; import 'reflect-metadata'; import { TYPES } from '../../types'; @@ -6,7 +7,7 @@ import { IAttribute } from '../renderer/IAttribute'; import { IElements } from '../renderer/IElements'; import { IRendererService } from '../renderer/IRendererService'; import { IParseDataItem } from '../source/ISourceService'; -import { ILayer } from './ILayerService'; +import { ILayer, IWorkerOption } from './ILayerService'; import { IAttributeScale, IEncodeFeature, @@ -185,6 +186,80 @@ export default class StyleAttributeService implements IStyleAttributeService { } } + public createAttributesAndIndicesAscy( + features: IEncodeFeature[], + segmentNumber: number, + workerOptions: IWorkerOption, + ) { + // 每次创建的初始化化 LayerOut + this.featureLayout = { + sizePerElement: 0, + elements: [], + }; + + const descriptors = this.attributes + .map((attr) => { + attr.resetDescriptor(); + return attr.descriptor; + }) + .filter((d) => d); + const { modelType, ...restOptions } = workerOptions; + + const { + createAttribute, + createBuffer, + createElements, + } = this.rendererService; + const attributes: { + [attributeName: string]: IAttribute; + } = {}; + return new Promise((resolve, reject) => { + executeWorkerTask(modelType, { + // Tip: worker 不支持传递 function 函数 + descriptors: this.getDescriptorsWithOutFunc(descriptors), + features, + segmentNumber, + ...restOptions, + }) + .then((e) => { + e.descriptors.forEach( + (descriptor: IVertexAttributeDescriptor, attributeIdx: number) => { + if (descriptor) { + // IAttribute 参数透传 + const { buffer, update, name, ...rest } = descriptor; + + const vertexAttribute = createAttribute({ + // IBuffer 参数透传 + buffer: createBuffer(buffer), + ...rest, + }); + attributes[descriptor.name || ''] = vertexAttribute; + + // 在 StyleAttribute 上保存对 VertexAttribute 的引用 + this.attributes[attributeIdx].vertexAttribute = vertexAttribute; + } + }, + ); + this.featureLayout = e.featureLayout; + const elements = createElements({ + data: e.indices, + type: gl.UNSIGNED_INT, + count: e.indices.length, + }); + this.attributesAndIndices = { + attributes, + elements, + }; + + resolve(this.attributesAndIndices); + }) + .catch((err: Error) => { + console.warn(err); + reject(err); + }); + }); + } + public createAttributesAndIndices( features: IEncodeFeature[], triangulation: Triangulation, @@ -434,4 +509,14 @@ export default class StyleAttributeService implements IStyleAttributeService { this.attributesAndIndices?.elements.destroy(); this.attributes = []; } + + private getDescriptorsWithOutFunc(descriptors: IVertexAttributeDescriptor[]) { + return descriptors.map((d) => { + return { + buffer: d.buffer, + name: d.name, + size: d.size, + }; + }); + } } diff --git a/packages/core/src/services/scene/SceneService.ts b/packages/core/src/services/scene/SceneService.ts index c60372797f..63789f36c3 100644 --- a/packages/core/src/services/scene/SceneService.ts +++ b/packages/core/src/services/scene/SceneService.ts @@ -302,13 +302,11 @@ export default class Scene extends EventEmitter implements ISceneService { public addLayer(layer: ILayer) { this.layerService.sceneService = this; this.layerService.add(layer); - this.render(); } public addMask(mask: ILayer) { this.layerService.sceneService = this; this.layerService.addMask(mask); - this.render(); } public async render() { diff --git a/packages/core/src/services/source/ISourceService.ts b/packages/core/src/services/source/ISourceService.ts index b03fc5d887..3fa6894591 100644 --- a/packages/core/src/services/source/ISourceService.ts +++ b/packages/core/src/services/source/ISourceService.ts @@ -60,6 +60,7 @@ export interface IJsonItem { export type IJsonData = IJsonItem[]; export interface ISource { + inited: boolean; data: IParserData; center: [number, number]; parser: IParserCfg; @@ -79,6 +80,10 @@ export interface ISource { properties: Record, ): void; destroy(): void; + // Event + on(type: string, handler: (...args: any[]) => void): void; + off(type: string, handler: (...args: any[]) => void): void; + once(type: string, handler: (...args: any[]) => void): void; } export interface IRasterCfg { extent: [number, number, number, number]; diff --git a/packages/l7/package.json b/packages/l7/package.json index 6b2faeb3c9..c7eaa19a79 100644 --- a/packages/l7/package.json +++ b/packages/l7/package.json @@ -17,9 +17,9 @@ "tsc": "tsc --project tsconfig.build.json", "clean": "rimraf dist; rimraf es; rimraf lib;", "build": "run-p build:*", - "build:cjs": "BABEL_ENV=cjs babel src --root-mode upward --out-dir lib --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments", - "build:esm": "BABEL_ENV=esm babel src --root-mode upward --out-dir es --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments", - "watch": "BABEL_ENV=cjs babel src --watch --root-mode upward --out-dir lib --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments", + "build:cjs": "cross-env BABEL_ENV=cjs NODE_ENV=production babel src --root-mode upward --out-dir lib --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments", + "build:esm": "cross-env BABEL_ENV=esm NODE_ENV=production babel src --root-mode upward --out-dir es --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments", + "watch": "cross-env BABEL_ENV=cjs NODE_ENV=production babel src --watch --root-mode upward --out-dir lib --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments", "sync": "tnpm sync" }, "author": "antv", diff --git a/packages/l7/src/index.ts b/packages/l7/src/index.ts index dafcc0cee3..fc535e244c 100644 --- a/packages/l7/src/index.ts +++ b/packages/l7/src/index.ts @@ -1,4 +1,5 @@ import Source from '@antv/l7-source'; + export * from '@antv/l7-core'; export * from '@antv/l7-scene'; export * from '@antv/l7-maps'; @@ -6,4 +7,5 @@ export * from '@antv/l7-layers'; export * from '@antv/l7-component'; export * from '@antv/l7-utils'; export * from './version'; + export { Source }; diff --git a/packages/l7/tsconfig.build.json b/packages/l7/tsconfig.build.json index 17f6c4525a..99200a9677 100644 --- a/packages/l7/tsconfig.build.json +++ b/packages/l7/tsconfig.build.json @@ -6,4 +6,4 @@ "baseUrl": "./" }, "include": ["./src"] -} \ No newline at end of file +} diff --git a/packages/layers/package.json b/packages/layers/package.json index 3968494d90..0c3acfe165 100644 --- a/packages/layers/package.json +++ b/packages/layers/package.json @@ -9,6 +9,7 @@ "./es/index.js" ], "files": [ + "dist", "lib", "es", "README.md" @@ -17,9 +18,9 @@ "tsc": "tsc --project tsconfig.build.json", "clean": "rimraf dist; rimraf es; rimraf lib;", "build": "run-p build:*", - "build:cjs": "BABEL_ENV=cjs babel src --root-mode upward --out-dir lib --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments", - "build:esm": "BABEL_ENV=esm babel src --root-mode upward --out-dir es --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments", - "watch": "BABEL_ENV=cjs babel src --watch --root-mode upward --out-dir lib --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments", + "build:cjs": "cross-env BABEL_ENV=cjs NODE_ENV=production babel src --root-mode upward --out-dir lib --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments", + "build:esm": "cross-env BABEL_ENV=esm NODE_ENV=production babel src --root-mode upward --out-dir es --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments", + "watch": "cross-env BABEL_ENV=cjs NODE_ENV=production babel src --watch --root-mode upward --out-dir lib --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments", "sync": "tnpm sync" }, "author": "xiaoiver", diff --git a/packages/layers/src/Geometry/index.ts b/packages/layers/src/Geometry/index.ts index b340725447..18df78239c 100644 --- a/packages/layers/src/Geometry/index.ts +++ b/packages/layers/src/Geometry/index.ts @@ -9,10 +9,13 @@ export default class GeometryLayer extends BaseLayer< public buildModels() { const modelType = this.getModelType(); this.layerModel = new GeometryModels[modelType](this); - this.models = this.layerModel.initModels(); + this.layerModel.initModels((models) => { + this.models = models; + this.renderLayers(); + }); } public rebuildModels() { - this.models = this.layerModel.buildModels(); + this.layerModel.buildModels((models) => (this.models = models)); } protected getConfigSchema() { diff --git a/packages/layers/src/Geometry/models/billboard.ts b/packages/layers/src/Geometry/models/billboard.ts index a15a8d3e85..5853a9ade5 100644 --- a/packages/layers/src/Geometry/models/billboard.ts +++ b/packages/layers/src/Geometry/models/billboard.ts @@ -3,10 +3,11 @@ import { gl, IAttrubuteAndElements, IEncodeFeature, + IModel, IModelUniform, ITexture2D, } from '@antv/l7-core'; -import { getMask, isMini } from '@antv/l7-utils'; +import { getMask } from '@antv/l7-utils'; import BaseModel from '../../core/BaseModel'; import { IGeometryLayerStyleOptions } from '../../core/interface'; import planeFrag from '../shaders/billboard_frag.glsl'; @@ -81,7 +82,7 @@ export default class BillBoardModel extends BaseModel { this.texture?.destroy(); } - public initModels() { + public initModels(callbackModel: (models: IModel[]) => void) { const { mask = false, maskInside = true, @@ -98,9 +99,9 @@ export default class BillBoardModel extends BaseModel { this.updateTexture(drawCanvas); } - return [ - this.layer.buildLayerModel({ - moduleName: 'geometry_billboard', + this.layer + .buildLayerModel({ + moduleName: 'geometryBillboard', vertexShader: planeVert, fragmentShader: planeFrag, triangulation: this.planeGeometryTriangulation, @@ -108,12 +109,18 @@ export default class BillBoardModel extends BaseModel { depth: { enable: true }, blend: this.getBlend(), stencil: getMask(mask, maskInside), - }), - ]; + }) + .then((model) => { + callbackModel([model]); + }) + .catch((err) => { + console.warn(err); + callbackModel([]); + }); } - public buildModels() { - return this.initModels(); + public buildModels(callbackModel: (models: IModel[]) => void) { + this.initModels(callbackModel); } public updateTexture(drawCanvas: (canvas: HTMLCanvasElement) => void): void { diff --git a/packages/layers/src/Geometry/models/plane.ts b/packages/layers/src/Geometry/models/plane.ts index 1eb6ab8d8a..66fa63caea 100644 --- a/packages/layers/src/Geometry/models/plane.ts +++ b/packages/layers/src/Geometry/models/plane.ts @@ -3,11 +3,12 @@ import { gl, IAttrubuteAndElements, IEncodeFeature, + IModel, IModelUniform, ITexture2D, } from '@antv/l7-core'; import { Version } from '@antv/l7-maps'; -import { getMask, isMini } from '@antv/l7-utils'; +import { getMask } from '@antv/l7-utils'; // import { mat4, vec3 } from 'gl-matrix'; import BaseModel from '../../core/BaseModel'; import { IGeometryLayerStyleOptions } from '../../core/interface'; @@ -134,7 +135,7 @@ export default class PlaneModel extends BaseModel { this.texture?.destroy(); } - public initModels() { + public initModels(callbackModel: (models: IModel[]) => void) { const { mask = false, maskInside = true, @@ -149,27 +150,33 @@ export default class PlaneModel extends BaseModel { }); this.updateTexture(mapTexture); - return [ - this.layer.buildLayerModel({ - moduleName: 'geometry_plane', + + this.layer + .buildLayerModel({ + moduleName: 'geometryPlane', vertexShader: planeVert, fragmentShader: planeFrag, triangulation: this.planeGeometryTriangulation, primitive: gl.TRIANGLES, - // primitive: gl.LINES, depth: { enable: true }, - blend: this.getBlend(), stencil: getMask(mask, maskInside), + blend: this.getBlend(), cull: { enable: true, face: gl.BACK, // gl.FRONT | gl.BACK; }, - }), - ]; + }) + .then((model) => { + callbackModel([model]); + }) + .catch((err) => { + console.warn(err); + callbackModel([]); + }); } - public buildModels() { - return this.initModels(); + public buildModels(callbackModel: (models: IModel[]) => void) { + this.initModels(callbackModel); } public createModelData(options?: any) { diff --git a/packages/layers/src/Geometry/models/sprite.ts b/packages/layers/src/Geometry/models/sprite.ts index 5aba2c9d79..2df492ad94 100644 --- a/packages/layers/src/Geometry/models/sprite.ts +++ b/packages/layers/src/Geometry/models/sprite.ts @@ -4,6 +4,7 @@ import { IAnimateOption, IEncodeFeature, ILayerConfig, + IModel, IModelUniform, ITexture2D, } from '@antv/l7-core'; @@ -153,7 +154,7 @@ export default class SpriteModel extends BaseModel { this.texture?.destroy(); } - public initModels() { + public initModels(callbackModel: (models: IModel[]) => void) { const { mapTexture, spriteTop = 5000000, @@ -179,21 +180,27 @@ export default class SpriteModel extends BaseModel { this.updateModel(); }, 100); - return [ - this.layer.buildLayerModel({ - moduleName: 'geometry_sprite', + this.layer + .buildLayerModel({ + moduleName: 'geometrySprite', vertexShader: spriteVert, fragmentShader: spriteFrag, triangulation: this.planeGeometryTriangulation, primitive: gl.POINTS, depth: { enable: false }, blend: this.getBlend(), - }), - ]; + }) + .then((model) => { + callbackModel([model]); + }) + .catch((err) => { + console.warn(err); + callbackModel([]); + }); } - public buildModels() { - return this.initModels(); + public buildModels(callbackModel: (models: IModel[]) => void) { + this.initModels(callbackModel); } public updateTexture(mapTexture: string | undefined): void { diff --git a/packages/layers/src/canvas/index.ts b/packages/layers/src/canvas/index.ts index 519f8a2bd7..981da540f9 100644 --- a/packages/layers/src/canvas/index.ts +++ b/packages/layers/src/canvas/index.ts @@ -6,10 +6,13 @@ export default class CanvasLayer extends BaseLayer { public buildModels() { const modelType = this.getModelType(); this.layerModel = new CanvasModels[modelType](this); - this.models = this.layerModel.initModels(); + this.layerModel.initModels((models) => { + this.models = models; + this.renderLayers(); + }); } public rebuildModels() { - this.models = this.layerModel.buildModels(); + this.layerModel.buildModels((models) => (this.models = models)); } protected getConfigSchema() { return { diff --git a/packages/layers/src/citybuliding/building.ts b/packages/layers/src/citybuliding/building.ts index 267e620449..e713da8d64 100644 --- a/packages/layers/src/citybuliding/building.ts +++ b/packages/layers/src/citybuliding/building.ts @@ -1,4 +1,3 @@ -import { IEncodeFeature } from '@antv/l7-core'; import BaseLayer from '../core/BaseLayer'; import CityBuildModel from './models/build'; @@ -6,10 +5,13 @@ export default class CityBuildingLayer extends BaseLayer { public type: string = 'PolygonLayer'; public buildModels() { this.layerModel = new CityBuildModel(this); - this.models = this.layerModel.initModels(); + this.layerModel.initModels((models) => { + this.models = models; + this.renderLayers(); + }); } public rebuildModels() { - this.models = this.layerModel.buildModels(); + this.layerModel.buildModels((models) => (this.models = models)); } public setLight(t: number) { this.updateLayerConfig({ diff --git a/packages/layers/src/citybuliding/models/build.ts b/packages/layers/src/citybuliding/models/build.ts index 8102bc8039..b3a1e5211a 100644 --- a/packages/layers/src/citybuliding/models/build.ts +++ b/packages/layers/src/citybuliding/models/build.ts @@ -75,22 +75,34 @@ export default class CityBuildModel extends BaseModel { } } - public initModels(): IModel[] { + public initModels(callbackModel: (models: IModel[]) => void) { this.calCityGeo(); this.startModelAnimate(); - return [ - this.layer.buildLayerModel({ + + this.buildModels(callbackModel); + } + + public buildModels(callbackModel: (models: IModel[]) => void) { + this.layer + .buildLayerModel({ moduleName: 'cityBuilding', vertexShader: buildVert, fragmentShader: buildFrag, triangulation: PolygonExtrudeTriangulation, + depth: { enable: true }, cull: { enable: true, face: gl.BACK, }, - }), - ]; + }) + .then((model) => { + callbackModel([model]); + }) + .catch((err) => { + console.warn(err); + callbackModel([]); + }); } protected registerBuiltinAttributes() { diff --git a/packages/layers/src/core/BaseLayer.ts b/packages/layers/src/core/BaseLayer.ts index bce6e20953..bcfade0185 100644 --- a/packages/layers/src/core/BaseLayer.ts +++ b/packages/layers/src/core/BaseLayer.ts @@ -50,7 +50,7 @@ import { TYPES, } from '@antv/l7-core'; import Source from '@antv/l7-source'; -import { encodePickingColor } from '@antv/l7-utils'; +import { encodePickingColor, WorkerSourceMap } from '@antv/l7-utils'; import { EventEmitter } from 'eventemitter3'; import { Container } from 'inversify'; import { isFunction, isObject, isUndefined } from 'lodash'; @@ -432,7 +432,7 @@ export default class BaseLayer } public createModelData(data: any, option?: ISourceCFG) { - if (this.layerModel.createModelData) { + if (this.layerModel?.createModelData) { // 在某些特殊图层中单独构建 attribute & elements return this.layerModel.createModelData(option); } @@ -654,7 +654,9 @@ export default class BaseLayer // @ts-ignore if (lastConfig && lastConfig.mask === true && options.mask === false) { this.clearModels(); - this.models = this.layerModel.buildModels(); + this.layerModel.buildModels((models) => { + this.models = models; + }); } return this; } @@ -688,7 +690,7 @@ export default class BaseLayer return this; } // TODO: this.getEncodedData().length !== 0 这个判断是为了解决在 2.5.x 引入数据纹理后产生的 空数据渲染导致 texture 超出上限问题 - if (this.getEncodedData().length !== 0) { + if (this.getEncodedData() && this.getEncodedData().length !== 0) { this.renderModels(); } return this; @@ -698,7 +700,7 @@ export default class BaseLayer * renderMultiPass 专门用于渲染支持 multipass 的 layer */ public async renderMultiPass() { - if (this.getEncodedData().length !== 0) { + if (this.getEncodedData() && this.getEncodedData().length !== 0) { if (this.multiPassRenderer && this.multiPassRenderer.getRenderFlag()) { // multi render 开始执行 multiPassRender 的渲染流程 await this.multiPassRenderer.render(); @@ -983,7 +985,7 @@ export default class BaseLayer this.hooks.beforeDestroy.call(); // 清除sources事件 - this.layerSource.off('update', this.sourceEvent); + this.layerSource.off('sourceUpdate', this.sourceEvent); this.multiPassRenderer.destroy(); // console.log(this.styleAttributeService.getAttributes()) @@ -1023,7 +1025,7 @@ export default class BaseLayer } public clearModels() { this.models.forEach((model) => model.destroy()); - this.layerModel.clearModels(); + this.layerModel?.clearModels(); this.models = []; } @@ -1041,7 +1043,7 @@ export default class BaseLayer public setSource(source: Source) { // 清除旧 sources 事件 if (this.layerSource) { - this.layerSource.off('update', this.sourceEvent); + this.layerSource.off('sourceUpdate', this.sourceEvent); } this.layerSource = source; @@ -1053,7 +1055,13 @@ export default class BaseLayer this.layerSource.updateClusterData(zoom); } // source 可能会复用,会在其它layer被修改 - this.layerSource.on('update', this.sourceEvent); + if (this.layerSource.inited) { + this.sourceEvent(); + } + // this.layerSource.inited 为 true 后,sourceUpdate 事件不会再触发 + this.layerSource.on('sourceUpdate', () => { + this.sourceEvent(); + }); } public getSource() { return this.layerSource; @@ -1136,37 +1144,70 @@ export default class BaseLayer public buildLayerModel( options: ILayerModelInitializationOptions & Partial, - ): IModel { + ): Promise { const { moduleName, vertexShader, fragmentShader, triangulation, segmentNumber, + workerEnabled = false, + workerOptions, ...rest } = options; + this.shaderModuleService.registerModule(moduleName, { vs: vertexShader, fs: fragmentShader, }); const { vs, fs, uniforms } = this.shaderModuleService.getModule(moduleName); const { createModel } = this.rendererService; - const { - attributes, - elements, - } = this.styleAttributeService.createAttributesAndIndices( - this.encodedData, - triangulation, - segmentNumber, - ); - return createModel({ - attributes, - uniforms, - fs, - vs, - elements, - blend: BlendTypes[BlendType.normal], - ...rest, + return new Promise((resolve, reject) => { + // filter supported worker & worker enabled layer + if ( + workerOptions && + workerOptions.modelType in WorkerSourceMap && + workerEnabled + ) { + this.styleAttributeService + .createAttributesAndIndicesAscy( + this.encodedData, + segmentNumber, + workerOptions, + ) + .then(({ attributes, elements }) => { + const m = createModel({ + attributes, + uniforms, + fs, + vs, + elements, + blend: BlendTypes[BlendType.normal], + ...rest, + }); + resolve(m); + }) + .catch((err) => reject(err)); + } else { + const { + attributes, + elements, + } = this.styleAttributeService.createAttributesAndIndices( + this.encodedData, + triangulation, + segmentNumber, + ); + const m = createModel({ + attributes, + uniforms, + fs, + vs, + elements, + blend: BlendTypes[BlendType.normal], + ...rest, + }); + resolve(m); + } }); } @@ -1241,15 +1282,18 @@ export default class BaseLayer public renderModels(isPicking?: boolean) { // TODO: this.getEncodedData().length > 0 这个判断是为了解决在 2.5.x 引入数据纹理后产生的 空数据渲染导致 texture 超出上限问题 - if (this.getEncodedData().length > 0) { + if (this.getEncodedData() && this.getEncodedData().length > 0) { if (this.layerModelNeedUpdate && this.layerModel) { - this.models = this.layerModel.buildModels(); - this.hooks.beforeRender.call(); - this.layerModelNeedUpdate = false; + this.layerModel.buildModels((models: IModel[]) => { + this.models = models; + this.hooks.beforeRender.call(); + this.layerModelNeedUpdate = false; + }); } - if (this.layerModel.renderUpdate) { + if (this?.layerModel?.renderUpdate) { this.layerModel.renderUpdate(); } + this.models.forEach((model) => { model.draw( { @@ -1321,9 +1365,9 @@ export default class BaseLayer private sourceEvent = () => { this.dataState.dataSourceNeedUpdate = true; - const { autoFit, fitBoundsOptions } = this.getLayerConfig(); - if (autoFit) { - this.fitBounds(fitBoundsOptions); + const layerConfig = this.getLayerConfig(); + if (layerConfig && layerConfig.autoFit) { + this.fitBounds(layerConfig.fitBoundsOptions); } // 对外暴露事件 迁移到 DataMappingPlugin generateMapping,保证在重新重新映射后触发 // this.emit('dataUpdate'); diff --git a/packages/layers/src/core/BaseModel.ts b/packages/layers/src/core/BaseModel.ts index 604cda96f7..af45efd78d 100644 --- a/packages/layers/src/core/BaseModel.ts +++ b/packages/layers/src/core/BaseModel.ts @@ -514,10 +514,10 @@ export default class BaseModel public needUpdate(): boolean { return false; } - public buildModels(): IModel[] { + public buildModels(callbackModel: (models: IModel[]) => void): void { throw new Error('Method not implemented.'); } - public initModels(): IModel[] { + public initModels(callbackModel: (models: IModel[]) => void): void { throw new Error('Method not implemented.'); } public clearModels() { diff --git a/packages/layers/src/core/interface.ts b/packages/layers/src/core/interface.ts index 93061f54aa..79c93d4904 100644 --- a/packages/layers/src/core/interface.ts +++ b/packages/layers/src/core/interface.ts @@ -50,6 +50,8 @@ export interface ILineLayerStyleOptions { rampColors?: IColorRamp; featureId?: string; sourceLayer?: string; + enablePicking?: boolean; + workerEnabled?: boolean; } export interface IPointLayerStyleOptions { diff --git a/packages/layers/src/core/triangulation.ts b/packages/layers/src/core/triangulation.ts index c8c2cb4dac..7e48f08995 100644 --- a/packages/layers/src/core/triangulation.ts +++ b/packages/layers/src/core/triangulation.ts @@ -1,5 +1,10 @@ import { IEncodeFeature } from '@antv/l7-core'; -import { aProjectFlat, lngLatToMeters } from '@antv/l7-utils'; +import { + aProjectFlat, + calculateCentroid, + calculatePointsCenterAndRadius, + lngLatToMeters, +} from '@antv/l7-utils'; import earcut from 'earcut'; // @ts-ignore import { mat4, vec3 } from 'gl-matrix'; @@ -11,10 +16,6 @@ import { primitiveSphere, } from '../earth/utils'; import ExtrudePolyline from '../utils/extrude_polyline'; -import { - calculateCentroid, - calculatePointsCenterAndRadius, -} from '../utils/geo'; import SimpleLine from '../utils/simpleLine'; import extrudePolygon, { extrude_PolygonNormal, diff --git a/packages/layers/src/earth/index.ts b/packages/layers/src/earth/index.ts index 0824b1f8a2..253bda8192 100644 --- a/packages/layers/src/earth/index.ts +++ b/packages/layers/src/earth/index.ts @@ -24,7 +24,10 @@ export default class EarthLayer extends BaseLayer { public buildModels() { const shape = this.getModelType(); this.layerModel = new EarthModels[shape](this); - this.models = this.layerModel.initModels(); + this.layerModel.initModels((models) => { + this.models = models; + this.renderLayers(); + }); } /** @@ -35,7 +38,7 @@ export default class EarthLayer extends BaseLayer { if (this.layerModel && this.layerModel.setEarthTime) { this.layerModel.setEarthTime(time); } else { - console.error('请在 scene loaded 之后执行该方法!'); + console.warn('请在 scene loaded 之后执行该方法!'); } } diff --git a/packages/layers/src/earth/models/atmosphere.ts b/packages/layers/src/earth/models/atmosphere.ts index 9134e583d2..091ab9688e 100644 --- a/packages/layers/src/earth/models/atmosphere.ts +++ b/packages/layers/src/earth/models/atmosphere.ts @@ -25,29 +25,33 @@ export default class EarthAtomSphereModel extends BaseModel { }; } - public initModels(): IModel[] { - return this.buildModels(); + public initModels(callbackModel: (models: IModel[]) => void) { + this.buildModels(callbackModel); } public clearModels() { return ''; } - public buildModels(): IModel[] { + public buildModels(callbackModel: (models: IModel[]) => void) { // TODO: 调整图层的绘制顺序 地球大气层 this.layer.zIndex = -997; - return [ - this.layer.buildLayerModel({ - moduleName: 'earthAtmoSphere', + this.layer + .buildLayerModel({ + moduleName: 'earthAtmo', vertexShader: atmoSphereVert, fragmentShader: atmoSphereFrag, triangulation: earthTriangulation, - depth: { - enable: false, - }, + depth: { enable: false }, blend: this.getBlend(), - }), - ]; + }) + .then((model) => { + callbackModel([model]); + }) + .catch((err) => { + console.warn(err); + callbackModel([]); + }); } protected registerBuiltinAttributes() { diff --git a/packages/layers/src/earth/models/base.ts b/packages/layers/src/earth/models/base.ts index 56d9ce634a..04c24429df 100644 --- a/packages/layers/src/earth/models/base.ts +++ b/packages/layers/src/earth/models/base.ts @@ -62,7 +62,7 @@ export default class BaseEarthModel extends BaseModel { this.layerService.renderLayers(); } - public initModels(): IModel[] { + public initModels(callbackModel: (models: IModel[]) => void) { const { globelOtions } = this.layer.getLayerConfig(); if (globelOtions?.earthTime !== undefined) { this.setEarthTime(globelOtions.earthTime); @@ -84,26 +84,33 @@ export default class BaseEarthModel extends BaseModel { this.layerService.renderLayers(); }); - return this.buildModels(); + this.buildModels(callbackModel); } public clearModels() { return ''; } - public buildModels(): IModel[] { + public buildModels(callbackModel: (models: IModel[]) => void) { // TODO: 调整图层的绘制顺序 地球大气层 this.layer.zIndex = -998; - return [ - this.layer.buildLayerModel({ - moduleName: 'baseEarth', + + this.layer + .buildLayerModel({ + moduleName: 'earthBase', vertexShader: baseVert, fragmentShader: baseFrag, triangulation: earthTriangulation, depth: { enable: true }, blend: this.getBlend(), - }), - ]; + }) + .then((model) => { + callbackModel([model]); + }) + .catch((err) => { + console.warn(err); + callbackModel([]); + }); } protected registerBuiltinAttributes() { diff --git a/packages/layers/src/earth/models/bloomsphere.ts b/packages/layers/src/earth/models/bloomsphere.ts index 0d20bd8f4f..59d9405c51 100644 --- a/packages/layers/src/earth/models/bloomsphere.ts +++ b/packages/layers/src/earth/models/bloomsphere.ts @@ -25,29 +25,33 @@ export default class EarthBloomSphereModel extends BaseModel { }; } - public initModels(): IModel[] { - return this.buildModels(); + public initModels(callbackModel: (models: IModel[]) => void) { + this.buildModels(callbackModel); } public clearModels() { return ''; } - public buildModels(): IModel[] { + public buildModels(callbackModel: (models: IModel[]) => void) { // TODO: 调整图层的绘制顺序,让它保持在地球后面(减少锯齿现象) this.layer.zIndex = -999; - return [ - this.layer.buildLayerModel({ - moduleName: 'earthBloomSphere', + this.layer + .buildLayerModel({ + moduleName: 'earthBloom', vertexShader: bloomSphereVert, fragmentShader: bloomSphereFrag, triangulation: earthOuterTriangulation, - depth: { - enable: false, - }, + depth: { enable: false }, blend: this.getBlend(), - }), - ]; + }) + .then((model) => { + callbackModel([model]); + }) + .catch((err) => { + console.warn(err); + callbackModel([]); + }); } protected registerBuiltinAttributes() { diff --git a/packages/layers/src/heatmap/index.ts b/packages/layers/src/heatmap/index.ts index c29511bb7a..0388e0e2f4 100644 --- a/packages/layers/src/heatmap/index.ts +++ b/packages/layers/src/heatmap/index.ts @@ -8,10 +8,13 @@ export default class HeatMapLayer extends BaseLayer { public buildModels() { const shape = this.getModelType(); this.layerModel = new HeatMapModels[shape](this); - this.models = this.layerModel.initModels(); + this.layerModel.initModels((models) => { + this.models = models; + this.renderLayers(); + }); } public rebuildModels() { - this.models = this.layerModel.buildModels(); + this.layerModel.buildModels((models) => (this.models = models)); } public renderModels() { const shape = this.getModelType(); @@ -23,7 +26,9 @@ export default class HeatMapLayer extends BaseLayer { return this; } if (this.layerModelNeedUpdate) { - this.models = this.layerModel.buildModels(); + this.layerModel.buildModels((models) => (this.models = models)); + // @ts-ignore + // this.models = this.layerModel.buildModels(); this.layerModelNeedUpdate = false; } this.models.forEach((model) => diff --git a/packages/layers/src/heatmap/models/grid.ts b/packages/layers/src/heatmap/models/grid.ts index 72caec2971..a631dbcf09 100644 --- a/packages/layers/src/heatmap/models/grid.ts +++ b/packages/layers/src/heatmap/models/grid.ts @@ -29,27 +29,32 @@ export default class GridModel extends BaseModel { }; } - public initModels(): IModel[] { - return this.buildModels(); + public initModels(callbackModel: (models: IModel[]) => void) { + this.buildModels(callbackModel); } - public buildModels(): IModel[] { + public buildModels(callbackModel: (models: IModel[]) => void) { const { mask = false, maskInside = true, } = this.layer.getLayerConfig() as IHeatMapLayerStyleOptions; - return [ - this.layer.buildLayerModel({ - moduleName: 'gridheatmap', + this.layer + .buildLayerModel({ + moduleName: 'heatmapGrid', vertexShader: heatmapGridVert, fragmentShader: heatmapGridFrag, triangulation: HeatmapGridTriangulation, - depth: { enable: false }, primitive: gl.TRIANGLES, - blend: this.getBlend(), + depth: { enable: false }, stencil: getMask(mask, maskInside), - }), - ]; + }) + .then((model) => { + callbackModel([model]); + }) + .catch((err) => { + console.warn(err); + callbackModel([]); + }); } protected registerBuiltinAttributes() { this.styleAttributeService.registerStyleAttribute({ diff --git a/packages/layers/src/heatmap/models/grid3d.ts b/packages/layers/src/heatmap/models/grid3d.ts index 3a62566951..fa8f839657 100644 --- a/packages/layers/src/heatmap/models/grid3d.ts +++ b/packages/layers/src/heatmap/models/grid3d.ts @@ -29,26 +29,33 @@ export default class Grid3DModel extends BaseModel { }; } - public initModels(): IModel[] { - return this.buildModels(); + public initModels(callbackModel: (models: IModel[]) => void) { + this.buildModels(callbackModel); } - public buildModels(): IModel[] { + public buildModels(callbackModel: (models: IModel[]) => void) { const { mask = false, maskInside = true, } = this.layer.getLayerConfig() as IHeatMapLayerStyleOptions; - return [ - this.layer.buildLayerModel({ - moduleName: 'grid3dheatmap', + this.layer + .buildLayerModel({ + moduleName: 'heatmapGrid3d', vertexShader: heatmapGrid3dVert, fragmentShader: heatmapGridFrag, triangulation: PointExtrudeTriangulation, + primitive: gl.TRIANGLES, depth: { enable: true }, blend: this.getBlend(), stencil: getMask(mask, maskInside), - }), - ]; + }) + .then((model) => { + callbackModel([model]); + }) + .catch((err) => { + console.warn(err); + callbackModel([]); + }); } protected registerBuiltinAttributes() { // point layer size; diff --git a/packages/layers/src/heatmap/models/heatmap.ts b/packages/layers/src/heatmap/models/heatmap.ts index f244dc5ec5..39d3e3b4ee 100644 --- a/packages/layers/src/heatmap/models/heatmap.ts +++ b/packages/layers/src/heatmap/models/heatmap.ts @@ -60,7 +60,7 @@ export default class HeatMapModel extends BaseModel { throw new Error('Method not implemented.'); } - public initModels(): IModel[] { + public async initModels(callbackModel: (models: IModel[]) => void) { const { createFramebuffer, clear, @@ -74,7 +74,7 @@ export default class HeatMapModel extends BaseModel { const shapeType = shapeAttr?.scale?.field || 'heatmap'; this.shapeType = shapeType as string; // 生成热力图密度图 - this.intensityModel = this.buildHeatMapIntensity(); + this.intensityModel = await this.buildHeatMapIntensity(); // 渲染到屏幕 this.colorModel = shapeType === 'heatmap' @@ -98,11 +98,11 @@ export default class HeatMapModel extends BaseModel { this.updateColorTexture(); - return [this.intensityModel, this.colorModel]; + callbackModel([this.intensityModel, this.colorModel]); } - public buildModels(): IModel[] { - return this.initModels(); + public buildModels(callbackModel: (models: IModel[]) => void) { + this.initModels(callbackModel); } protected registerBuiltinAttributes() { @@ -154,10 +154,10 @@ export default class HeatMapModel extends BaseModel { }, }); } - private buildHeatMapIntensity(): IModel { + private async buildHeatMapIntensity() { this.layer.triangulation = HeatmapTriangulation; - return this.layer.buildLayerModel({ - moduleName: 'heatmapintensity', + const model = await this.layer.buildLayerModel({ + moduleName: 'heatmapIntensity', vertexShader: heatmapFramebufferVert, fragmentShader: heatmapFramebufferFrag, triangulation: HeatmapTriangulation, @@ -178,6 +178,7 @@ export default class HeatMapModel extends BaseModel { }, }, }); + return model; } private buildHeatmapColor(): IModel { @@ -241,7 +242,7 @@ export default class HeatMapModel extends BaseModel { intensity = 10, radius = 5, } = this.layer.getLayerConfig() as IHeatMapLayerStyleOptions; - this.intensityModel.draw({ + this.intensityModel?.draw({ uniforms: { u_opacity: opacity || 1.0, u_radius: radius, @@ -254,7 +255,7 @@ export default class HeatMapModel extends BaseModel { const { opacity, } = this.layer.getLayerConfig() as IHeatMapLayerStyleOptions; - this.colorModel.draw({ + this.colorModel?.draw({ uniforms: { u_opacity: opacity || 1.0, u_colorTexture: this.colorTexture, @@ -281,7 +282,7 @@ export default class HeatMapModel extends BaseModel { this.cameraService.getViewProjectionMatrixUncentered() as mat4, ); - this.colorModel.draw({ + this.colorModel?.draw({ uniforms: { u_opacity: opacity || 1.0, u_colorTexture: this.colorTexture, diff --git a/packages/layers/src/heatmap/models/hexagon.ts b/packages/layers/src/heatmap/models/hexagon.ts index 405fbdf52c..3b876b3c88 100644 --- a/packages/layers/src/heatmap/models/hexagon.ts +++ b/packages/layers/src/heatmap/models/hexagon.ts @@ -30,18 +30,18 @@ export default class HexagonModel extends BaseModel { }; } - public initModels(): IModel[] { - return this.buildModels(); + public initModels(callbackModel: (models: IModel[]) => void) { + this.buildModels(callbackModel); } - public buildModels(): IModel[] { + public buildModels(callbackModel: (models: IModel[]) => void) { const { mask = false, maskInside = true, } = this.layer.getLayerConfig() as IHeatMapLayerStyleOptions; - return [ - this.layer.buildLayerModel({ - moduleName: 'hexagonheatmap', + this.layer + .buildLayerModel({ + moduleName: 'heatmapHexagon', vertexShader: heatmapGridVert, fragmentShader: heatmapGridFrag, triangulation: HeatmapGridTriangulation, @@ -49,8 +49,14 @@ export default class HexagonModel extends BaseModel { primitive: gl.TRIANGLES, blend: this.getBlend(), stencil: getMask(mask, maskInside), - }), - ]; + }) + .then((model) => { + callbackModel([model]); + }) + .catch((err) => { + console.warn(err); + callbackModel([]); + }); } protected registerBuiltinAttributes() { this.styleAttributeService.registerStyleAttribute({ diff --git a/packages/layers/src/image/index.ts b/packages/layers/src/image/index.ts index a635ed8bc1..9e26e64ca2 100644 --- a/packages/layers/src/image/index.ts +++ b/packages/layers/src/image/index.ts @@ -6,10 +6,13 @@ export default class ImageLayer extends BaseLayer { public buildModels() { const modelType = this.getModelType(); this.layerModel = new ImageModels[modelType](this); - this.models = this.layerModel.initModels(); + this.layerModel.initModels((models) => { + this.models = models; + this.renderLayers(); + }); } public rebuildModels() { - this.models = this.layerModel.buildModels(); + this.layerModel.buildModels((models) => (this.models = models)); } protected getConfigSchema() { return { diff --git a/packages/layers/src/image/models/dataImage.ts b/packages/layers/src/image/models/dataImage.ts index c8ec6189fa..213ab384a7 100644 --- a/packages/layers/src/image/models/dataImage.ts +++ b/packages/layers/src/image/models/dataImage.ts @@ -2,6 +2,7 @@ import { AttributeType, gl, IEncodeFeature, + IModel, IModelUniform, ITexture2D, } from '@antv/l7-core'; @@ -54,7 +55,7 @@ export default class ImageDataModel extends BaseModel { u_colorTexture: this.colorTexture, }; } - public initModels() { + public initModels(callbackModel: (models: IModel[]) => void) { const { mask = false, maskInside = true, @@ -109,8 +110,8 @@ export default class ImageDataModel extends BaseModel { flipY: false, }); - return [ - this.layer.buildLayerModel({ + this.layer + .buildLayerModel({ moduleName: 'RasterImage', vertexShader: ImageVert, fragmentShader: ImageFrag, @@ -119,8 +120,14 @@ export default class ImageDataModel extends BaseModel { depth: { enable: false }, blend: this.getBlend(), stencil: getMask(mask, maskInside), - }), - ]; + }) + .then((model) => { + callbackModel([model]); + }) + .catch((err) => { + console.warn(err); + callbackModel([]); + }); } public clearModels(): void { @@ -128,8 +135,8 @@ export default class ImageDataModel extends BaseModel { this.colorTexture?.destroy(); } - public buildModels() { - return this.initModels(); + public buildModels(callbackModel: (models: IModel[]) => void) { + this.initModels(callbackModel); } protected getConfigSchema() { diff --git a/packages/layers/src/image/models/image.ts b/packages/layers/src/image/models/image.ts index 159b5465b0..cca4a28c7f 100644 --- a/packages/layers/src/image/models/image.ts +++ b/packages/layers/src/image/models/image.ts @@ -2,6 +2,7 @@ import { AttributeType, gl, IEncodeFeature, + IModel, IModelUniform, ITexture2D, } from '@antv/l7-core'; @@ -21,7 +22,8 @@ export default class ImageModel extends BaseModel { u_texture: this.texture, }; } - public initModels() { + + public initModels(callbackModel: (models: IModel[]) => void) { const { mask = false, maskInside = true, @@ -64,26 +66,31 @@ export default class ImageModel extends BaseModel { ); } - return [ - this.layer.buildLayerModel({ - moduleName: 'RasterImage', + this.layer + .buildLayerModel({ + moduleName: 'rasterImage', vertexShader: ImageVert, fragmentShader: ImageFrag, triangulation: RasterImageTriangulation, primitive: gl.TRIANGLES, depth: { enable: false }, - blend: this.getBlend(), stencil: getMask(mask, maskInside), - }), - ]; + }) + .then((model) => { + callbackModel([model]); + }) + .catch((err) => { + console.warn(err); + callbackModel([]); + }); } public clearModels(): void { this.texture?.destroy(); } - public buildModels() { - return this.initModels(); + public buildModels(callbackModel: (models: IModel[]) => void) { + this.initModels(callbackModel); } protected getConfigSchema() { diff --git a/packages/layers/src/line/index.ts b/packages/layers/src/line/index.ts index 52557b4b5a..0f9eb7994b 100644 --- a/packages/layers/src/line/index.ts +++ b/packages/layers/src/line/index.ts @@ -8,10 +8,13 @@ export default class LineLayer extends BaseLayer { public buildModels() { const shape = this.getModelType(); this.layerModel = new LineModels[shape](this); - this.models = this.layerModel.initModels(); + this.layerModel.initModels((models) => { + this.models = models; + this.renderLayers(); + }); } public rebuildModels() { - this.models = this.layerModel.buildModels(); + this.layerModel.buildModels((models) => (this.models = models)); } protected getConfigSchema() { @@ -34,7 +37,6 @@ export default class LineLayer extends BaseLayer { wall: {}, arc3d: { blend: 'additive' }, arc: { blend: 'additive' }, - arcmini: { blend: 'additive' }, greatcircle: { blend: 'additive' }, vectorline: {}, tileLine: {}, diff --git a/packages/layers/src/line/models/arc.ts b/packages/layers/src/line/models/arc.ts index bb065afff8..ab129e0526 100644 --- a/packages/layers/src/line/models/arc.ts +++ b/packages/layers/src/line/models/arc.ts @@ -129,11 +129,11 @@ export default class ArcModel extends BaseModel { }; } - public initModels(): IModel[] { + public initModels(callbackModel: (models: IModel[]) => void) { this.updateTexture(); this.iconService.on('imageUpdate', this.updateTexture); - return this.buildModels(); + this.buildModels(callbackModel); } public clearModels() { @@ -152,7 +152,7 @@ export default class ArcModel extends BaseModel { return { frag: arc_dash_frag, vert: arc_dash_vert, - type: 'dash', + type: 'Dash', }; } @@ -161,28 +161,28 @@ export default class ArcModel extends BaseModel { return { frag: arc_linear_frag, vert: arc_linear_vert, - type: 'linear', + type: 'Linear', }; } else { return { frag: arc_line_frag, vert: arc_line_vert, - type: 'normal', + type: '', }; } } - public buildModels(): IModel[] { + public buildModels(callbackModel: (models: IModel[]) => void) { const { segmentNumber = 30, mask = false, maskInside = true, } = this.layer.getLayerConfig() as ILineLayerStyleOptions; const { frag, vert, type } = this.getShaders(); - return [ - this.layer.buildLayerModel({ - // primitive: gl.POINTS, - moduleName: 'arc2dline' + type, + + this.layer + .buildLayerModel({ + moduleName: 'lineArc2d' + type, vertexShader: vert, fragmentShader: frag, triangulation: LineArcTriangulation, @@ -190,8 +190,14 @@ export default class ArcModel extends BaseModel { blend: this.getBlend(), segmentNumber, stencil: getMask(mask, maskInside), - }), - ]; + }) + .then((model) => { + callbackModel([model]); + }) + .catch((err) => { + console.warn(err); + callbackModel([]); + }); } protected registerBuiltinAttributes() { diff --git a/packages/layers/src/line/models/arc_3d.ts b/packages/layers/src/line/models/arc_3d.ts index 1fb1c7c7a4..c52839777d 100644 --- a/packages/layers/src/line/models/arc_3d.ts +++ b/packages/layers/src/line/models/arc_3d.ts @@ -123,11 +123,11 @@ export default class Arc3DModel extends BaseModel { }; } - public initModels(): IModel[] { + public initModels(callbackModel: (models: IModel[]) => void) { this.updateTexture(); this.iconService.on('imageUpdate', this.updateTexture); - return this.buildModels(); + this.buildModels(callbackModel); } public clearModels() { @@ -147,36 +147,42 @@ export default class Arc3DModel extends BaseModel { return { frag: arc3d_linear_frag, vert: arc3d_linear_vert, - type: 'linear', + type: 'Linear', }; } else { return { frag: arc3d_line_frag, vert: arc3d_line_vert, - type: 'normal', + type: '', }; } } - public buildModels(): IModel[] { + public buildModels(callbackModel: (models: IModel[]) => void) { const { segmentNumber = 30, mask = false, maskInside = true, } = this.layer.getLayerConfig() as ILineLayerStyleOptions; const { frag, vert, type } = this.getShaders(); - return [ - this.layer.buildLayerModel({ - moduleName: 'arc3Dline' + type, + + this.layer + .buildLayerModel({ + moduleName: 'lineArc3d' + type, vertexShader: vert, fragmentShader: frag, triangulation: LineArcTriangulation, blend: this.getBlend(), segmentNumber, - // primitive: gl.POINTS, stencil: getMask(mask, maskInside), - }), - ]; + }) + .then((model) => { + callbackModel([model]); + }) + .catch((err) => { + console.warn(err); + callbackModel([]); + }); } protected registerBuiltinAttributes() { // point layer size; diff --git a/packages/layers/src/line/models/arcmini.ts b/packages/layers/src/line/models/arcmini.ts deleted file mode 100644 index 02af3137d7..0000000000 --- a/packages/layers/src/line/models/arcmini.ts +++ /dev/null @@ -1,133 +0,0 @@ -import { - AttributeType, - gl, - IAnimateOption, - IEncodeFeature, - ILayerConfig, - IModel, - IModelUniform, -} from '@antv/l7-core'; -import { rgb2arr } from '@antv/l7-utils'; -import { isNumber } from 'lodash'; -import BaseModel from '../../core/BaseModel'; -import { ILineLayerStyleOptions } from '../../core/interface'; -import { LineArcTriangulation } from '../../core/triangulation'; -import line_arcmini_frag from '../shaders/line_arcmini_frag.glsl'; -import line_arcmini_vert from '../shaders/line_arcmini_vert.glsl'; - -export default class ArcMiniModel extends BaseModel { - public getUninforms(): IModelUniform { - const { - opacity = 1, - sourceColor, - targetColor, - forward = true, - segmentNumber = 30, - thetaOffset = 0.314, - } = this.layer.getLayerConfig() as ILineLayerStyleOptions; - - // 转化渐变色 - let useLinearColor = 0; // 默认不生效 - let sourceColorArr = [0, 0, 0, 0]; - let targetColorArr = [0, 0, 0, 0]; - if (sourceColor && targetColor) { - sourceColorArr = rgb2arr(sourceColor); - targetColorArr = rgb2arr(targetColor); - useLinearColor = 1; - } - - return { - u_thetaOffset: thetaOffset, - - u_opacity: isNumber(opacity) ? opacity : 1.0, - - segmentNumber, - u_blur: 0.9, - u_lineDir: forward ? 1 : -1, - - // 渐变色支持参数 - u_linearColor: useLinearColor, - u_sourceColor: sourceColorArr, - u_targetColor: targetColorArr, - }; - } - - public getAnimateUniforms(): IModelUniform { - const { animateOption } = this.layer.getLayerConfig() as ILayerConfig; - return { - u_aimate: this.animateOption2Array(animateOption as IAnimateOption), - u_time: this.layer.getLayerAnimateTime(), - }; - } - - public initModels(): IModel[] { - return this.buildModels(); - } - - public buildModels(): IModel[] { - const { - segmentNumber = 30, - } = this.layer.getLayerConfig() as ILineLayerStyleOptions; - - return [ - this.layer.buildLayerModel({ - moduleName: 'arc2dminiline', - vertexShader: line_arcmini_vert, - fragmentShader: line_arcmini_frag, - triangulation: LineArcTriangulation, - depth: { enable: false }, - blend: this.getBlend(), - segmentNumber, - }), - ]; - } - - protected registerBuiltinAttributes() { - // point layer size; - this.styleAttributeService.registerStyleAttribute({ - name: 'size', - type: AttributeType.Attribute, - descriptor: { - name: 'a_Size', - buffer: { - // give the WebGL driver a hint that this buffer may change - usage: gl.DYNAMIC_DRAW, - data: [], - type: gl.FLOAT, - }, - size: 1, - update: ( - feature: IEncodeFeature, - featureIdx: number, - vertex: number[], - attributeIdx: number, - ) => { - const { size = 1 } = feature; - return Array.isArray(size) ? [size[0]] : [size as number]; - }, - }, - }); - - this.styleAttributeService.registerStyleAttribute({ - name: 'instance', // 弧线起始点信息 - type: AttributeType.Attribute, - descriptor: { - name: 'a_Instance', - buffer: { - usage: gl.STATIC_DRAW, - data: [], - type: gl.FLOAT, - }, - size: 4, - update: ( - feature: IEncodeFeature, - featureIdx: number, - vertex: number[], - attributeIdx: number, - ) => { - return [vertex[3], vertex[4], vertex[5], vertex[6]]; - }, - }, - }); - } -} diff --git a/packages/layers/src/line/models/earthArc_3d.ts b/packages/layers/src/line/models/earthArc_3d.ts index 1fb1c7c7a4..7a0654dab6 100644 --- a/packages/layers/src/line/models/earthArc_3d.ts +++ b/packages/layers/src/line/models/earthArc_3d.ts @@ -90,7 +90,7 @@ export default class Arc3DModel extends BaseModel { } return { - u_globel: this.mapService.version === 'GLOBEL' ? 1 : 0, + u_globel: 1, u_globel_radius: EARTH_RADIUS, // 地球半径 u_global_height: globalArcHeight, @@ -123,11 +123,11 @@ export default class Arc3DModel extends BaseModel { }; } - public initModels(): IModel[] { + public initModels(callbackModel: (models: IModel[]) => void) { this.updateTexture(); this.iconService.on('imageUpdate', this.updateTexture); - return this.buildModels(); + this.buildModels(callbackModel); } public clearModels() { @@ -147,36 +147,42 @@ export default class Arc3DModel extends BaseModel { return { frag: arc3d_linear_frag, vert: arc3d_linear_vert, - type: 'linear', + type: 'Linear', }; } else { return { frag: arc3d_line_frag, vert: arc3d_line_vert, - type: 'normal', + type: '', }; } } - public buildModels(): IModel[] { + public buildModels(callbackModel: (models: IModel[]) => void) { const { segmentNumber = 30, mask = false, maskInside = true, } = this.layer.getLayerConfig() as ILineLayerStyleOptions; const { frag, vert, type } = this.getShaders(); - return [ - this.layer.buildLayerModel({ - moduleName: 'arc3Dline' + type, + this.layer + .buildLayerModel({ + moduleName: 'lineEarthArc3d' + type, vertexShader: vert, fragmentShader: frag, triangulation: LineArcTriangulation, + depth: { enable: true }, blend: this.getBlend(), segmentNumber, - // primitive: gl.POINTS, stencil: getMask(mask, maskInside), - }), - ]; + }) + .then((model) => { + callbackModel([model]); + }) + .catch((err) => { + console.warn(err); + callbackModel([]); + }); } protected registerBuiltinAttributes() { // point layer size; diff --git a/packages/layers/src/line/models/great_circle.ts b/packages/layers/src/line/models/great_circle.ts index c7d8234f6c..bd1de86f4b 100644 --- a/packages/layers/src/line/models/great_circle.ts +++ b/packages/layers/src/line/models/great_circle.ts @@ -112,11 +112,11 @@ export default class GreatCircleModel extends BaseModel { }; } - public initModels(): IModel[] { + public initModels(callbackModel: (models: IModel[]) => void) { this.updateTexture(); this.iconService.on('imageUpdate', this.updateTexture); - return this.buildModels(); + this.buildModels(callbackModel); } public clearModels() { @@ -125,22 +125,28 @@ export default class GreatCircleModel extends BaseModel { this.iconService.off('imageUpdate', this.updateTexture); } - public buildModels(): IModel[] { + public buildModels(callbackModel: (models: IModel[]) => void) { const { mask = false, maskInside = true, } = this.layer.getLayerConfig() as ILineLayerStyleOptions; - return [ - this.layer.buildLayerModel({ - moduleName: 'greatcircleline', + this.layer + .buildLayerModel({ + moduleName: 'lineGreatCircle', vertexShader: line_arc2d_vert, fragmentShader: line_arc_frag, triangulation: LineArcTriangulation, depth: { enable: false }, blend: this.getBlend(), stencil: getMask(mask, maskInside), - }), - ]; + }) + .then((model) => { + callbackModel([model]); + }) + .catch((err) => { + console.warn(err); + callbackModel([]); + }); } protected registerBuiltinAttributes() { this.styleAttributeService.registerStyleAttribute({ diff --git a/packages/layers/src/line/models/half.ts b/packages/layers/src/line/models/half.ts index 7b7df78dba..c92d9aca1e 100644 --- a/packages/layers/src/line/models/half.ts +++ b/packages/layers/src/line/models/half.ts @@ -84,15 +84,15 @@ export default class LineModel extends BaseModel { }; } - public initModels(): IModel[] { - return this.buildModels(); + public initModels(callbackModel: (models: IModel[]) => void) { + this.buildModels(callbackModel); } public clearModels() { this.dataTexture?.destroy(); } - public buildModels(): IModel[] { + public async buildModels(callbackModel: (models: IModel[]) => void) { const { mask = false, maskInside = true, @@ -100,18 +100,24 @@ export default class LineModel extends BaseModel { } = this.layer.getLayerConfig() as ILineLayerStyleOptions; const { frag, vert } = this.getShaders(); this.layer.triangulation = LineTriangulation; - return [ - this.layer.buildLayerModel({ - moduleName: 'line_half', + + this.layer + .buildLayerModel({ + moduleName: 'lineHalf', vertexShader: vert, fragmentShader: frag, triangulation: LineTriangulation, - primitive: gl.TRIANGLES, - blend: this.getBlend(), depth: { enable: depth }, + blend: this.getBlend(), stencil: getMask(mask, maskInside), - }), - ]; + }) + .then((model) => { + callbackModel([model]); + }) + .catch((err) => { + console.warn(err); + callbackModel([]); + }); } /** diff --git a/packages/layers/src/line/models/index.ts b/packages/layers/src/line/models/index.ts index 4bc5a6af45..7e59b0a9e8 100644 --- a/packages/layers/src/line/models/index.ts +++ b/packages/layers/src/line/models/index.ts @@ -1,7 +1,6 @@ import LineTileModel from '../../tile/models/tileModel'; import ArcModel from './arc'; import Arc3DModel from './arc_3d'; -import ArcMiniModel from './arcmini'; import EarthArc3DModel from './earthArc_3d'; import GreatCircleModel from './great_circle'; import LineHalfModel from './half'; @@ -13,7 +12,6 @@ import LineWallModel from './wall'; export type LineModelType = | 'arc' - | 'arcmini' | 'arc3d' | 'greatcircle' | 'wall' @@ -27,7 +25,6 @@ export type LineModelType = const LineModels: { [key in LineModelType]: any } = { arc: ArcModel, - arcmini: ArcMiniModel, arc3d: Arc3DModel, greatcircle: GreatCircleModel, wall: LineWallModel, diff --git a/packages/layers/src/line/models/line.ts b/packages/layers/src/line/models/line.ts index e461d36876..b1c54d6368 100644 --- a/packages/layers/src/line/models/line.ts +++ b/packages/layers/src/line/models/line.ts @@ -9,11 +9,11 @@ import { IModelUniform, ITexture2D, } from '@antv/l7-core'; -import { getMask, rgb2arr } from '@antv/l7-utils'; +import { getMask, LineTriangulation, rgb2arr } from '@antv/l7-utils'; import { isNumber } from 'lodash'; import BaseModel from '../../core/BaseModel'; import { ILineLayerStyleOptions } from '../../core/interface'; -import { LineTriangulation } from '../../core/triangulation'; +// import { LineTriangulation } from '../../core/triangulation'; // dash line shader import line_dash_frag from '../shaders/dash/line_dash_frag.glsl'; import line_dash_vert from '../shaders/dash/line_dash_vert.glsl'; @@ -143,11 +143,11 @@ export default class LineModel extends BaseModel { }; } - public initModels(): IModel[] { + public initModels(callbackModel: (models: IModel[]) => void) { this.updateTexture(); this.iconService.on('imageUpdate', this.updateTexture); - return this.buildModels(); + this.buildModels(callbackModel); } public clearModels() { @@ -156,27 +156,39 @@ export default class LineModel extends BaseModel { this.iconService.off('imageUpdate', this.updateTexture); } - public buildModels(): IModel[] { + public buildModels(callbackModel: (models: IModel[]) => void) { const { mask = false, maskInside = true, depth = false, + workerEnabled = false, + enablePicking, } = this.layer.getLayerConfig() as ILineLayerStyleOptions; const { frag, vert, type } = this.getShaders(); this.layer.triangulation = LineTriangulation; - return [ - this.layer.buildLayerModel({ - moduleName: 'line_' + type, + this.layer + .buildLayerModel({ + moduleName: 'line' + type, vertexShader: vert, fragmentShader: frag, triangulation: LineTriangulation, - primitive: gl.TRIANGLES, - blend: this.getBlend(), depth: { enable: depth }, - // depth: { enable: true }, + blend: this.getBlend(), stencil: getMask(mask, maskInside), - }), - ]; + workerEnabled, + workerOptions: { + modelType: 'line' + type, + enablePicking, + iconMap: this.iconService.getIconMap(), + }, + }) + .then((model) => { + callbackModel([model]); + }) + .catch((err) => { + console.warn(err); + callbackModel([]); + }); } /** @@ -194,7 +206,7 @@ export default class LineModel extends BaseModel { return { frag: line_dash_frag, vert: line_dash_vert, - type: 'dash', + type: 'Dash', }; } @@ -203,13 +215,13 @@ export default class LineModel extends BaseModel { return { frag: linear_line_frag, vert: line_vert, - type: 'linear', + type: 'Linear', }; } else { return { frag: line_frag, vert: line_vert, - type: 'normal', + type: '', }; } } diff --git a/packages/layers/src/line/models/linearline.ts b/packages/layers/src/line/models/linearline.ts index 59c6c80ea6..993100d8c7 100644 --- a/packages/layers/src/line/models/linearline.ts +++ b/packages/layers/src/line/models/linearline.ts @@ -74,9 +74,9 @@ export default class LinearLineModel extends BaseModel { }; } - public initModels(): IModel[] { + public initModels(callbackModel: (models: IModel[]) => void) { this.updateTexture(); - return this.buildModels(); + this.buildModels(callbackModel); } public clearModels() { @@ -84,38 +84,32 @@ export default class LinearLineModel extends BaseModel { this.dataTexture?.destroy(); } - public buildModels(): IModel[] { + public buildModels(callbackModel: (models: IModel[]) => void) { const { mask = false, maskInside = true, depth = false, } = this.layer.getLayerConfig() as ILineLayerStyleOptions; - const { frag, vert, type } = this.getShaders(); - this.layer.triangulation = LineTriangulation; - return [ - this.layer.buildLayerModel({ - moduleName: 'line_' + type, - vertexShader: vert, - fragmentShader: frag, - triangulation: LineTriangulation, - primitive: gl.TRIANGLES, - blend: this.getBlend(), - depth: { enable: depth }, - stencil: getMask(mask, maskInside), - }), - ]; - } - /** - * 根据参数获取不同的 shader 代码 - * @returns - */ - public getShaders(): { frag: string; vert: string; type: string } { - return { - frag: linear_line_frag, - vert: linear_line_vert, - type: 'linear_rampColors', - }; + this.layer.triangulation = LineTriangulation; + + this.layer + .buildLayerModel({ + moduleName: 'lineRampColors', + vertexShader: linear_line_vert, + fragmentShader: linear_line_frag, + triangulation: LineTriangulation, + depth: { enable: depth }, + blend: this.getBlend(), + stencil: getMask(mask, maskInside), + }) + .then((model) => { + callbackModel([model]); + }) + .catch((err) => { + console.warn(err); + callbackModel([]); + }); } protected registerBuiltinAttributes() { diff --git a/packages/layers/src/line/models/simpleLine.ts b/packages/layers/src/line/models/simpleLine.ts index 38cc21c08a..19ff3df987 100644 --- a/packages/layers/src/line/models/simpleLine.ts +++ b/packages/layers/src/line/models/simpleLine.ts @@ -78,8 +78,8 @@ export default class SimpleLineModel extends BaseModel { }; } - public initModels(): IModel[] { - return this.buildModels(); + public initModels(callbackModel: (models: IModel[]) => void) { + this.buildModels(callbackModel); } public clearModels() { @@ -96,36 +96,43 @@ export default class SimpleLineModel extends BaseModel { return { frag: simle_linear_frag, vert: simple_line_vert, - type: 'simple_linear', + type: 'lineSimpleLinear', }; } else { return { frag: simple_line_frag, vert: simple_line_vert, - type: 'simple_normal', + type: 'lineSimpleNormal', }; } } - public buildModels(): IModel[] { + public buildModels(callbackModel: (models: IModel[]) => void) { const { mask = false, maskInside = true, } = this.layer.getLayerConfig() as ILineLayerStyleOptions; const { frag, vert, type } = this.getShaders(); - return [ - this.layer.buildLayerModel({ + + this.layer + .buildLayerModel({ moduleName: type, vertexShader: vert, fragmentShader: frag, triangulation: SimpleLineTriangulation, - primitive: gl.LINES, // gl.LINES gl.TRIANGLES - blend: this.getBlend(), + primitive: gl.LINES, depth: { enable: false }, + blend: this.getBlend(), stencil: getMask(mask, maskInside), - }), - ]; + }) + .then((model) => { + callbackModel([model]); + }) + .catch((err) => { + console.warn(err); + callbackModel([]); + }); } protected registerBuiltinAttributes() { this.styleAttributeService.registerStyleAttribute({ diff --git a/packages/layers/src/line/models/tile.ts b/packages/layers/src/line/models/tile.ts index c2a615dc1a..ab87517505 100644 --- a/packages/layers/src/line/models/tile.ts +++ b/packages/layers/src/line/models/tile.ts @@ -103,11 +103,11 @@ export default class LineModel extends BaseModel { }; } - public initModels(): IModel[] { + public initModels(callbackModel: (models: IModel[]) => void) { this.updateTexture(); this.iconService.on('imageUpdate', this.updateTexture); - return this.buildModels(); + this.buildModels(callbackModel); } public clearModels() { @@ -116,39 +116,33 @@ export default class LineModel extends BaseModel { this.iconService.off('imageUpdate', this.updateTexture); } - public buildModels(): IModel[] { + public async buildModels(callbackModel: (models: IModel[]) => void) { const { mask = false, maskInside = true, depth = false, } = this.layer.getLayerConfig() as ILineLayerStyleOptions; - const { frag, vert, type } = this.getShaders(); + this.layer.triangulation = LineTriangulation; - return [ - this.layer.buildLayerModel({ - moduleName: type, - vertexShader: vert, - fragmentShader: frag, + + this.layer + .buildLayerModel({ + moduleName: 'lineTile', + vertexShader: line_tile_vert, + fragmentShader: line_tile_frag, triangulation: LineTriangulation, - primitive: gl.TRIANGLES, blend: this.getBlend(), depth: { enable: depth }, // depth: { enable: true }, stencil: getMask(mask, maskInside), - }), - ]; - } - - /** - * 根据参数获取不同的 shader 代码 - * @returns - */ - public getShaders(): { frag: string; vert: string; type: string } { - return { - frag: line_tile_frag, - vert: line_tile_vert, - type: 'line_tile', - }; + }) + .then((model) => { + callbackModel([model]); + }) + .catch((err) => { + console.warn(err); + callbackModel([]); + }); } protected registerBuiltinAttributes() { diff --git a/packages/layers/src/line/models/wall.ts b/packages/layers/src/line/models/wall.ts index c7a60f5b3a..6b3c1794e2 100644 --- a/packages/layers/src/line/models/wall.ts +++ b/packages/layers/src/line/models/wall.ts @@ -103,11 +103,11 @@ export default class LineWallModel extends BaseModel { }; } - public initModels(): IModel[] { + public initModels(callbackModel: (models: IModel[]) => void) { this.updateTexture(); this.iconService.on('imageUpdate', this.updateTexture); - return this.buildModels(); + this.buildModels(callbackModel); } public clearModels() { @@ -116,18 +116,23 @@ export default class LineWallModel extends BaseModel { this.iconService.off('imageUpdate', this.updateTexture); } - public buildModels(): IModel[] { - return [ - this.layer.buildLayerModel({ - moduleName: 'linewall', + public buildModels(callbackModel: (models: IModel[]) => void) { + this.layer + .buildLayerModel({ + moduleName: 'lineWall', vertexShader: line_vert, fragmentShader: line_frag, triangulation: LineTriangulation, - primitive: gl.TRIANGLES, - blend: this.getBlend(), depth: { enable: false }, - }), - ]; + blend: this.getBlend(), + }) + .then((model) => { + callbackModel([model]); + }) + .catch((err) => { + console.warn(err); + callbackModel([]); + }); } protected registerBuiltinAttributes() { this.styleAttributeService.registerStyleAttribute({ diff --git a/packages/layers/src/line/shaders/line_arcmini_frag.glsl b/packages/layers/src/line/shaders/line_arcmini_frag.glsl deleted file mode 100644 index b091e2d355..0000000000 --- a/packages/layers/src/line/shaders/line_arcmini_frag.glsl +++ /dev/null @@ -1,40 +0,0 @@ -#define Animate 0.0 - -uniform float u_opacity; -uniform float u_blur : 0.9; -// varying vec2 v_normal; -varying vec4 v_color; - -uniform float u_time; -uniform vec4 u_aimate: [ 0, 2., 1.0, 0.2 ]; - -uniform float segmentNumber; -varying float v_distance_ratio; - -uniform float u_linearColor: 0; -uniform vec4 u_sourceColor; -uniform vec4 u_targetColor; - -#pragma include "picking" - -void main() { - - // 设置弧线的底色 - if(u_linearColor == 1.0) { // 使用渐变颜色 - gl_FragColor = mix(u_sourceColor, u_targetColor, v_distance_ratio); - } else { // 使用 color 方法传入的颜色 - gl_FragColor = v_color; - } - - - gl_FragColor.a *= u_opacity; - - if(u_aimate.x == Animate) { - float animateSpeed = u_time / u_aimate.y; // 运动速度 - float alpha =1.0 - fract( mod(1.0- v_distance_ratio, u_aimate.z)* (1.0/ u_aimate.z) + u_time / u_aimate.y); - alpha = (alpha + u_aimate.w -1.0) / u_aimate.w; - // alpha = smoothstep(0., 1., alpha); - alpha = clamp(alpha, 0.0, 1.0); - gl_FragColor.a *= alpha; - } -} \ No newline at end of file diff --git a/packages/layers/src/line/shaders/line_arcmini_vert.glsl b/packages/layers/src/line/shaders/line_arcmini_vert.glsl deleted file mode 100644 index 2b1019288e..0000000000 --- a/packages/layers/src/line/shaders/line_arcmini_vert.glsl +++ /dev/null @@ -1,101 +0,0 @@ -#define Animate 0.0 - -attribute vec4 a_Color; -attribute vec3 a_Position; -attribute vec4 a_Instance; -attribute float a_Size; -uniform mat4 u_ModelMatrix; -uniform mat4 u_Mvp; -uniform float segmentNumber; -uniform vec4 u_aimate: [ 0, 2., 1.0, 0.2 ]; -varying vec4 v_color; - -uniform float u_lineDir: 1.0; - -// 偏移量 -uniform float u_thetaOffset: 0.314; - -uniform float u_opacity: 1.0; -varying float v_distance_ratio; - -#pragma include "projection" -#pragma include "project" -#pragma include "picking" - -float bezier3(vec3 arr, float t) { - float ut = 1. - t; - return (arr.x * ut + arr.y * t) * ut + (arr.y * ut + arr.z * t) * t; -} -vec2 midPoint(vec2 source, vec2 target) { - vec2 center = target - source; - float r = length(center); - float theta = atan(center.y, center.x); - float thetaOffset = u_thetaOffset; - float r2 = r / 2.0 / cos(thetaOffset); - float theta2 = theta + thetaOffset; - vec2 mid = vec2(r2*cos(theta2) + source.x, r2*sin(theta2) + source.y); - if(u_lineDir == 1.0) { // 正向 - return mid; - } else { // 逆向 - // (mid + vmin)/2 = (s + t)/2 - vec2 vmid = source + target - mid; - return vmid; - } - // return mid; -} -float getSegmentRatio(float index) { - return smoothstep(0.0, 1.0, index / (segmentNumber - 1.)); -} -vec2 interpolate (vec2 source, vec2 target, float t) { - // if the angularDist is PI, linear interpolation is applied. otherwise, use spherical interpolation - vec2 mid = midPoint(source, target); - vec3 x = vec3(source.x, mid.x, target.x); - vec3 y = vec3(source.y, mid.y, target.y); - return vec2(bezier3(x ,t), bezier3(y,t)); -} -vec2 getExtrusionOffset(vec2 line_clipspace, float offset_direction) { - // normalized direction of the line - vec2 dir_screenspace = normalize(line_clipspace); - // rotate by 90 degrees - dir_screenspace = vec2(-dir_screenspace.y, dir_screenspace.x); - vec2 offset = dir_screenspace * offset_direction * setPickingSize(a_Size) / 2.0; - return offset; -} -vec2 getNormal(vec2 line_clipspace, float offset_direction) { - // normalized direction of the line - vec2 dir_screenspace = normalize(line_clipspace); - // rotate by 90 degrees - dir_screenspace = vec2(-dir_screenspace.y, dir_screenspace.x); - return reverse_offset_normal(vec3(dir_screenspace,1.0)).xy * sign(offset_direction); -} - -void main() { - v_color = a_Color; - - vec2 source = a_Instance.rg; // 起始点 - vec2 target = a_Instance.ba; // 终点 - float segmentIndex = a_Position.x; - float segmentRatio = getSegmentRatio(segmentIndex); - - float indexDir = mix(-1.0, 1.0, step(segmentIndex, 0.0)); - float nextSegmentRatio = getSegmentRatio(segmentIndex + indexDir); - - v_distance_ratio = segmentIndex / segmentNumber; - - if(u_aimate.x == Animate && u_lineDir != 1.0) { - v_distance_ratio = 1.0 - v_distance_ratio; - } - - vec4 curr = project_position(vec4(interpolate(source, target, segmentRatio), 0.0, 1.0)); - vec4 next = project_position(vec4(interpolate(source, target, nextSegmentRatio), 0.0, 1.0)); - // v_normal = getNormal((next.xy - curr.xy) * indexDir, a_Position.y); - //unProjCustomCoord - - vec2 offset = project_pixel(getExtrusionOffset((next.xy - curr.xy) * indexDir, a_Position.y)); - - if(u_CoordinateSystem == COORDINATE_SYSTEM_P20_2) { // gaode2.x - gl_Position = u_Mvp * (vec4(curr.xy + offset, 0, 1.0)); - } else { - gl_Position = project_common_position_to_clipspace(vec4(curr.xy + offset, 0, 1.0)); - } -} diff --git a/packages/layers/src/mask/index.ts b/packages/layers/src/mask/index.ts index d8d6b982b1..f6955905b8 100644 --- a/packages/layers/src/mask/index.ts +++ b/packages/layers/src/mask/index.ts @@ -7,10 +7,13 @@ export default class MaskLayer extends BaseLayer { public buildModels() { const shape = this.getModelType(); this.layerModel = new MaskModels[shape](this); - this.models = this.layerModel.initModels(); + this.layerModel.initModels((models) => { + this.models = models; + this.renderLayers(); + }); } public rebuildModels() { - this.models = this.layerModel.buildModels(); + this.layerModel.buildModels((models) => (this.models = models)); } protected getConfigSchema() { return { diff --git a/packages/layers/src/mask/models/fill.ts b/packages/layers/src/mask/models/fill.ts index 2d27520774..3b9362f277 100644 --- a/packages/layers/src/mask/models/fill.ts +++ b/packages/layers/src/mask/models/fill.ts @@ -16,20 +16,19 @@ export default class MaskModel extends BaseModel { }; } - public initModels(): IModel[] { - return this.buildModels(); + public initModels(callbackModel: (models: IModel[]) => void) { + this.buildModels(callbackModel); } - public buildModels(): IModel[] { - return [ - this.layer.buildLayerModel({ + public async buildModels(callbackModel: (models: IModel[]) => void) { + this.layer + .buildLayerModel({ moduleName: 'mask', vertexShader: mask_vert, fragmentShader: mask_frag, triangulation: polygonTriangulation, - blend: this.getBlend(), depth: { enable: false }, - + blend: this.getBlend(), stencil: { enable: true, mask: 0xff, @@ -44,8 +43,14 @@ export default class MaskModel extends BaseModel { zpass: gl.REPLACE, }, }, - }), - ]; + }) + .then((model) => { + callbackModel([model]); + }) + .catch((err) => { + console.warn(err); + callbackModel([]); + }); } public clearModels() { diff --git a/packages/layers/src/plugins/DataMappingPlugin.ts b/packages/layers/src/plugins/DataMappingPlugin.ts index 6934d4f90e..726298e2d6 100644 --- a/packages/layers/src/plugins/DataMappingPlugin.ts +++ b/packages/layers/src/plugins/DataMappingPlugin.ts @@ -38,24 +38,43 @@ export default class DataMappingPlugin implements ILayerPlugin { ) { layer.hooks.init.tap('DataMappingPlugin', () => { // 初始化重新生成 map - this.generateMaping(layer, { styleAttributeService }); + const source = layer.getSource(); + if (source.inited) { + this.generateMaping(layer, { styleAttributeService }); + } else { + source.once('sourceUpdate', () => { + this.generateMaping(layer, { styleAttributeService }); + }); + } + // this.generateMaping(layer, { styleAttributeService }); }); layer.hooks.beforeRenderData.tap('DataMappingPlugin', () => { layer.dataState.dataMappingNeedUpdate = false; - this.generateMaping(layer, { styleAttributeService }); + const source = layer.getSource(); + if (source.inited) { + this.generateMaping(layer, { styleAttributeService }); + } else { + source.once('sourceUpdate', () => { + this.generateMaping(layer, { styleAttributeService }); + }); + } + + // this.generateMaping(layer, { styleAttributeService }); + return true; }); // remapping before render layer.hooks.beforeRender.tap('DataMappingPlugin', () => { - if (layer.layerModelNeedUpdate) { + const source = layer.getSource(); + if (layer.layerModelNeedUpdate || !source || !source.inited) { return; } const bottomColor = layer.getBottomColor(); const attributes = styleAttributeService.getLayerStyleAttributes() || []; const filter = styleAttributeService.getLayerStyleAttribute('filter'); - const { dataArray } = layer.getSource().data; + const { dataArray } = source.data; const attributesToRemapping = attributes.filter( (attribute) => attribute.needRemapping, // 如果filter变化 diff --git a/packages/layers/src/plugins/DataSourcePlugin.ts b/packages/layers/src/plugins/DataSourcePlugin.ts index c480bb2ae6..5f9dd42ad3 100644 --- a/packages/layers/src/plugins/DataSourcePlugin.ts +++ b/packages/layers/src/plugins/DataSourcePlugin.ts @@ -5,7 +5,11 @@ import { IMapService, TYPES, } from '@antv/l7-core'; -import Source, { DEFAULT_DATA, DEFAULT_PARSER } from '@antv/l7-source'; +import Source, { + DEFAULT_DATA, + DEFAULT_PARSER, + DEFAULT_SOURCE, +} from '@antv/l7-source'; import { injectable } from 'inversify'; import 'reflect-metadata'; @@ -15,17 +19,28 @@ export default class DataSourcePlugin implements ILayerPlugin { public apply(layer: ILayer) { this.mapService = layer.getContainer().get(TYPES.IMapService); layer.hooks.init.tap('DataSourcePlugin', () => { - const source = layer.getSource(); + let source = layer.getSource(); if (!source) { // TODO: 允许用户不使用 layer 的 source 方法,在这里传入一个默认的替换的默认数据 - const { data, options } = layer.sourceOption || { + const defaultSourceConfig = DEFAULT_SOURCE[ + layer.type as 'PointLayer' | 'LineLayer' + ] || { data: DEFAULT_DATA, options: DEFAULT_PARSER, }; - layer.setSource(new Source(data, options)); + const { data, options } = layer.sourceOption || defaultSourceConfig; + source = new Source(data, options); + layer.setSource(source); } - - this.updateClusterData(layer); + if (source.inited) { + this.updateClusterData(layer); + } else { + source.once('sourceUpdate', () => { + this.updateClusterData(layer); + // TODO: layer.hooks.init.call(); + }); + } + // this.updateClusterData(layer); }); // 检测数据是否需要更新 diff --git a/packages/layers/src/plugins/LayerModelPlugin.ts b/packages/layers/src/plugins/LayerModelPlugin.ts index acb6624cfa..3b053236fb 100644 --- a/packages/layers/src/plugins/LayerModelPlugin.ts +++ b/packages/layers/src/plugins/LayerModelPlugin.ts @@ -6,23 +6,45 @@ import 'reflect-metadata'; */ @injectable() export default class LayerModelPlugin implements ILayerPlugin { + public initLayerModel(layer: ILayer) { + // 更新Model 配置项 + layer.prepareBuildModel(); + // 初始化 Model + layer.buildModels(); + // emit layer model loaded + layer.emit('modelLoaded', null); + layer.styleNeedUpdate = false; + } + + public prepareLayerModel(layer: ILayer) { + // 更新Model 配置项 + layer.prepareBuildModel(); + layer.clearModels(); + // 初始化 Model + layer.buildModels(); + // emit layer model loaded + layer.emit('modelLoaded', null); + layer.layerModelNeedUpdate = false; + } + public apply(layer: ILayer) { layer.hooks.init.tap('LayerModelPlugin', () => { - // 更新Model 配置项 - layer.prepareBuildModel(); - // 初始化 Model - layer.buildModels(); - layer.styleNeedUpdate = false; + layer.inited = true; + const source = layer.getSource(); + if (source.inited) { + this.initLayerModel(layer); + } }); layer.hooks.beforeRenderData.tap('DataSourcePlugin', () => { - // 更新Model 配置项 - layer.prepareBuildModel(); - - layer.clearModels(); - // 初始化 Model - layer.buildModels(); - layer.layerModelNeedUpdate = false; + const source = layer.getSource(); + if (source.inited) { + this.prepareLayerModel(layer); + } else { + source.once('sourceUpdate', () => { + this.prepareLayerModel(layer); + }); + } return false; }); } diff --git a/packages/layers/src/plugins/PixelPickingPlugin.ts b/packages/layers/src/plugins/PixelPickingPlugin.ts index cd899f660c..43600d9d24 100644 --- a/packages/layers/src/plugins/PixelPickingPlugin.ts +++ b/packages/layers/src/plugins/PixelPickingPlugin.ts @@ -35,8 +35,8 @@ export default class PixelPickingPlugin implements ILayerPlugin { ) { // TODO: 由于 Shader 目前无法根据是否开启拾取进行内容修改,因此即使不开启也需要生成 a_PickingColor layer.hooks.init.tap('PixelPickingPlugin', () => { - // const { enablePicking, enableMultiPassRenderer } = layer.getLayerConfig(); - const enablePicking = true; + const { enablePicking, enableMultiPassRenderer } = layer.getLayerConfig(); + // const enablePicking = true; styleAttributeService.registerStyleAttribute({ name: 'pickingColor', type: AttributeType.Attribute, diff --git a/packages/layers/src/point/index.ts b/packages/layers/src/point/index.ts index 3358f7d494..7492b53e69 100644 --- a/packages/layers/src/point/index.ts +++ b/packages/layers/src/point/index.ts @@ -8,10 +8,14 @@ export default class PointLayer extends BaseLayer { public buildModels() { const modelType = this.getModelType(); this.layerModel = new PointModels[modelType](this); - this.models = this.layerModel.initModels(); + this.layerModel.initModels((models) => { + this.models = models; + this.layerService.updateLayerRenderList(); + this.renderLayers(); + }); } public rebuildModels() { - this.models = this.layerModel.buildModels(); + this.layerModel.buildModels((models) => (this.models = models)); } /** @@ -62,7 +66,6 @@ export default class PointLayer extends BaseLayer { fill: { blend: 'normal' }, extrude: {}, image: {}, - icon: {}, text: { blend: 'normal', }, @@ -84,7 +87,6 @@ export default class PointLayer extends BaseLayer { 'simplePoint', 'extrude', 'text', - 'icon', 'vectorpoint', 'tile', 'earthFill', @@ -93,9 +95,7 @@ export default class PointLayer extends BaseLayer { if (this.layerSource.parser.type === 'mvt') { return 'vectorpoint'; } - if (this.layerType && PointTypes.includes(this.layerType)) { - return this.layerType as PointType; - } + // pointlayer // 2D、 3d、 shape、image、text、normal、 const layerData = this.getEncodedData(); @@ -104,8 +104,8 @@ export default class PointLayer extends BaseLayer { const item = layerData.find((fe: IEncodeFeature) => { return fe.hasOwnProperty('shape'); }); + if (!item) { - // return 'normal'; return this.getModelTypeWillEmptyData(); } else { const shape = item.shape; @@ -118,21 +118,26 @@ export default class PointLayer extends BaseLayer { if (shape === 'radar') { return 'radar'; } - if (shape === 'fillImage') { + if (this.layerType === 'fillImage') { return 'fillImage'; } if (shape2d?.indexOf(shape as string) !== -1) { - return 'fill'; + if (this.mapService.version === 'GLOBEL') { + return 'earthFill'; + } else { + return 'fill'; + } } if (shape3d?.indexOf(shape as string) !== -1) { - return 'extrude'; + if (this.mapService.version === 'GLOBEL') { + return 'earthExtrude'; + } else { + return 'extrude'; + } } if (iconMap.hasOwnProperty(shape as string)) { return 'image'; } - if (this.fontService.getGlyph(shape as string) !== '') { - return 'icon'; - } return 'text'; } } diff --git a/packages/layers/src/point/models/earthExtrude.ts b/packages/layers/src/point/models/earthExtrude.ts index 03474379fa..b227d3bf3f 100644 --- a/packages/layers/src/point/models/earthExtrude.ts +++ b/packages/layers/src/point/models/earthExtrude.ts @@ -5,13 +5,12 @@ import { ILayerConfig, IModel, } from '@antv/l7-core'; -import { getCullFace, rgb2arr } from '@antv/l7-utils'; +import { calculateCentroid, getCullFace, rgb2arr } from '@antv/l7-utils'; import { isNumber } from 'lodash'; import BaseModel from '../../core/BaseModel'; import { IPointLayerStyleOptions } from '../../core/interface'; import { PointExtrudeTriangulation } from '../../core/triangulation'; import { lglt2xyz } from '../../earth/utils'; -import { calculateCentroid } from '../../utils/geo'; import pointExtrudeFrag from '../shaders/earth/extrude_frag.glsl'; import pointExtrudeVert from '../shaders/earth/extrude_vert.glsl'; @@ -130,33 +129,37 @@ export default class ExtrudeModel extends BaseModel { u_lightEnable: Number(lightEnable), }; } - public initModels(): IModel[] { - return this.buildModels(); + public initModels(callbackModel: (models: IModel[]) => void) { + this.buildModels(callbackModel); } - public buildModels(): IModel[] { + public buildModels(callbackModel: (models: IModel[]) => void) { // GAODE1.x GAODE2.x MAPBOX const { - depth = true, animateOption: { repeat = 1 }, } = this.layer.getLayerConfig() as ILayerConfig; this.raiserepeat = repeat; - return [ - this.layer.buildLayerModel({ - moduleName: 'pointExtrude2', + + this.layer + .buildLayerModel({ + moduleName: 'pointEarthExtrude', vertexShader: pointExtrudeVert, fragmentShader: pointExtrudeFrag, triangulation: PointExtrudeTriangulation, - blend: this.getBlend(), + depth: { enable: true }, cull: { enable: true, face: getCullFace(this.mapService.version), }, - depth: { - enable: depth, - }, - }), - ]; + blend: this.getBlend(), + }) + .then((model) => { + callbackModel([model]); + }) + .catch((err) => { + console.warn(err); + callbackModel([]); + }); } public clearModels() { this.dataTexture?.destroy(); diff --git a/packages/layers/src/point/models/earthFill.ts b/packages/layers/src/point/models/earthFill.ts index 61f847a8c0..d83c078112 100644 --- a/packages/layers/src/point/models/earthFill.ts +++ b/packages/layers/src/point/models/earthFill.ts @@ -99,35 +99,29 @@ export default class FillModel extends BaseModel { }; } - public initModels(): IModel[] { - return this.buildModels(); + public initModels(callbackModel: (models: IModel[]) => void) { + this.buildModels(callbackModel); } - public buildModels(): IModel[] { - const { frag, vert, type } = this.getShaders(); + public buildModels(callbackModel: (models: IModel[]) => void) { this.layer.triangulation = GlobelPointFillTriangulation; - return [ - this.layer.buildLayerModel({ - moduleName: 'pointfill_' + type, - vertexShader: vert, - fragmentShader: frag, + this.layer + .buildLayerModel({ + moduleName: 'pointEarthFill', + vertexShader: pointFillVert, + fragmentShader: pointFillFrag, triangulation: GlobelPointFillTriangulation, depth: { enable: true }, - blend: this.getBlend(), - }), - ]; - } - /** - * 根据 animateOption 的值返回对应的 shader 代码 - * @returns - */ - public getShaders(): { frag: string; vert: string; type: string } { - return { - frag: pointFillFrag, - vert: pointFillVert, - type: 'point_earth_fill', - }; + blend: this.getBlend(), + }) + .then((model) => { + callbackModel([model]); + }) + .catch((err) => { + console.warn(err); + callbackModel([]); + }); } public clearModels() { diff --git a/packages/layers/src/point/models/extrude.ts b/packages/layers/src/point/models/extrude.ts index 62a55779e1..b75d4fd9ac 100644 --- a/packages/layers/src/point/models/extrude.ts +++ b/packages/layers/src/point/models/extrude.ts @@ -5,12 +5,11 @@ import { ILayerConfig, IModel, } from '@antv/l7-core'; -import { getCullFace, rgb2arr } from '@antv/l7-utils'; +import { calculateCentroid, getCullFace, rgb2arr } from '@antv/l7-utils'; import { isNumber } from 'lodash'; import BaseModel from '../../core/BaseModel'; import { IPointLayerStyleOptions } from '../../core/interface'; import { PointExtrudeTriangulation } from '../../core/triangulation'; -import { calculateCentroid } from '../../utils/geo'; import pointExtrudeFrag from '../shaders/extrude/extrude_frag.glsl'; import pointExtrudeVert from '../shaders/extrude/extrude_vert.glsl'; @@ -128,20 +127,21 @@ export default class ExtrudeModel extends BaseModel { u_lightEnable: Number(lightEnable), }; } - public initModels(): IModel[] { - return this.buildModels(); + public initModels(callbackModel: (models: IModel[]) => void) { + this.buildModels(callbackModel); } - public buildModels(): IModel[] { + public async buildModels(callbackModel: (models: IModel[]) => void) { // GAODE1.x GAODE2.x MAPBOX const { depth = true, animateOption: { repeat = 1 }, } = this.layer.getLayerConfig() as ILayerConfig; this.raiserepeat = repeat; - return [ - this.layer.buildLayerModel({ - moduleName: 'pointExtrude2', + + this.layer + .buildLayerModel({ + moduleName: 'pointExtrude', vertexShader: pointExtrudeVert, fragmentShader: pointExtrudeFrag, triangulation: PointExtrudeTriangulation, @@ -153,8 +153,14 @@ export default class ExtrudeModel extends BaseModel { depth: { enable: depth, }, - }), - ]; + }) + .then((model) => { + callbackModel([model]); + }) + .catch((err) => { + console.warn(err); + callbackModel([]); + }); } public clearModels() { this.dataTexture?.destroy(); diff --git a/packages/layers/src/point/models/fill.ts b/packages/layers/src/point/models/fill.ts index 40b7a19a62..8a4efa771e 100644 --- a/packages/layers/src/point/models/fill.ts +++ b/packages/layers/src/point/models/fill.ts @@ -9,11 +9,11 @@ import { IModel, IModelUniform, } from '@antv/l7-core'; -import { $window, getMask } from '@antv/l7-utils'; +import { $window, getMask, PointFillTriangulation } from '@antv/l7-utils'; import { isNumber } from 'lodash'; import BaseModel from '../../core/BaseModel'; import { IPointLayerStyleOptions } from '../../core/interface'; -import { PointFillTriangulation } from '../../core/triangulation'; +// import { PointFillTriangulation } from '../../core/triangulation'; // animate pointLayer shader - support animate import waveFillFrag from '../shaders/animate/wave_frag.glsl'; // static pointLayer shader - not support animate @@ -21,6 +21,7 @@ import pointFillFrag from '../shaders/fill_frag.glsl'; import pointFillVert from '../shaders/fill_vert.glsl'; import { Version } from '@antv/l7-maps'; + export default class FillModel extends BaseModel { private meter2coord: number = 1; private meteryScale: number = 1; // 兼容 mapbox @@ -130,10 +131,9 @@ export default class FillModel extends BaseModel { ); } - public initModels(): IModel[] { + public initModels(callbackModel: (models: IModel[]) => void) { this.updateUnit('l7size'); - - return this.buildModels(); + this.buildModels(callbackModel); } /** @@ -186,28 +186,44 @@ export default class FillModel extends BaseModel { } } - public buildModels(): IModel[] { + public async buildModels(callbackModel: (models: IModel[]) => void) { const { mask = false, maskInside = true, animateOption = { enable: false }, + workerEnabled = false, + enablePicking, + shape2d, } = this.layer.getLayerConfig() as Partial< ILayerConfig & IPointLayerStyleOptions >; const { frag, vert, type } = this.getShaders(animateOption); this.layer.triangulation = PointFillTriangulation; - return [ - this.layer.buildLayerModel({ - moduleName: 'pointfill_' + type, + + this.layer + .buildLayerModel({ + moduleName: type, vertexShader: vert, fragmentShader: frag, triangulation: PointFillTriangulation, depth: { enable: false }, blend: this.getBlend(), stencil: getMask(mask, maskInside), - }), - ]; + workerEnabled, + workerOptions: { + modelType: type, + enablePicking, + shape2d, + }, + }) + .then((model) => { + callbackModel([model]); + }) + .catch((err) => { + console.warn(err); + callbackModel([]); + }); } /** @@ -223,20 +239,20 @@ export default class FillModel extends BaseModel { return { frag: waveFillFrag, vert: pointFillVert, - type: 'wave', + type: 'pointWave', }; default: return { frag: waveFillFrag, vert: pointFillVert, - type: 'wave', + type: 'pointWave', }; } } else { return { frag: pointFillFrag, vert: pointFillVert, - type: 'normal', + type: 'pointFill', }; } } @@ -250,6 +266,8 @@ export default class FillModel extends BaseModel { return [option.enable ? 0 : 1.0, option.speed || 1, option.rings || 3, 0]; } protected registerBuiltinAttributes() { + const shape2d = this.layer.getLayerConfig().shape2d as string[]; + this.styleAttributeService.registerStyleAttribute({ name: 'extrude', type: AttributeType.Attribute, @@ -299,7 +317,7 @@ export default class FillModel extends BaseModel { attributeIdx: number, ) => { const { size = 5 } = feature; - return Array.isArray(size) ? [size[0]] : [size as number]; + return Array.isArray(size) ? [size[0]] : [size]; }, }, }); @@ -324,7 +342,6 @@ export default class FillModel extends BaseModel { attributeIdx: number, ) => { const { shape = 2 } = feature; - const shape2d = this.layer.getLayerConfig().shape2d as string[]; const shapeIndex = shape2d.indexOf(shape as string); return [shapeIndex]; }, diff --git a/packages/layers/src/point/models/fillmage.ts b/packages/layers/src/point/models/fillmage.ts index 802bba3006..2e71f737c1 100644 --- a/packages/layers/src/point/models/fillmage.ts +++ b/packages/layers/src/point/models/fillmage.ts @@ -127,7 +127,7 @@ export default class FillImageModel extends BaseModel { ); } - public initModels(): IModel[] { + public initModels(callbackModel: (models: IModel[]) => void) { this.updateTexture(); this.iconService.on('imageUpdate', this.updateTexture); @@ -144,7 +144,7 @@ export default class FillImageModel extends BaseModel { this.calMeter2Coord(); } - return this.buildModels(); + this.buildModels(callbackModel); } /** @@ -189,17 +189,17 @@ export default class FillImageModel extends BaseModel { } } - public buildModels(): IModel[] { + public buildModels(callbackModel: (models: IModel[]) => void) { const { mask = false, maskInside = true, } = this.layer.getLayerConfig() as IPointLayerStyleOptions; - const { frag, vert, type } = this.getShaders(); - return [ - this.layer.buildLayerModel({ - moduleName: type, - vertexShader: vert, - fragmentShader: frag, + + this.layer + .buildLayerModel({ + moduleName: 'pointFillImage', + vertexShader: pointFillVert, + fragmentShader: pointFillFrag, triangulation: PointFillTriangulation, depth: { enable: false }, blend: this.getBlend(), @@ -208,16 +208,14 @@ export default class FillImageModel extends BaseModel { enable: true, face: getCullFace(this.mapService.version), }, - }), - ]; - } - - public getShaders(): { frag: string; vert: string; type: string } { - return { - frag: pointFillFrag, - vert: pointFillVert, - type: 'point_fillImage', - }; + }) + .then((model) => { + callbackModel([model]); + }) + .catch((err) => { + console.warn(err); + callbackModel([]); + }); } public clearModels() { diff --git a/packages/layers/src/point/models/icon-font.ts b/packages/layers/src/point/models/icon-font.ts deleted file mode 100644 index c558ad22b2..0000000000 --- a/packages/layers/src/point/models/icon-font.ts +++ /dev/null @@ -1,146 +0,0 @@ -import { - AttributeType, - gl, - IEncodeFeature, - IModel, - IModelUniform, - ITexture2D, -} from '@antv/l7-core'; - -import BaseModel from '../../core/BaseModel'; -import { PointImageTriangulation } from '../../core/triangulation'; -import pointImageFrag from '../shaders/image_frag.glsl'; -import pointImageVert from '../shaders/image_vert.glsl'; -interface IIconIFontStyleOptions { - opacity: number; - fontWeight: string; - fontFamily: string; -} - -export default class IconeModel extends BaseModel { - private texture: ITexture2D; - - public getUninforms(): IModelUniform { - const { opacity } = this.layer.getLayerConfig() as IIconIFontStyleOptions; - return { - u_opacity: opacity || 1.0, - u_texture: this.texture, - u_textSize: [1024, this.iconService.canvasHeight || 128], - }; - } - - public initModels(): IModel[] { - this.initIconFontGlyphs(); - this.registerBuiltinAttributes(); - this.updateTexture(); - this.iconService.on('imageUpdate', () => { - this.updateTexture(); - this.layer.render(); // TODO 调用全局render - }); - return [ - this.layer.buildLayerModel({ - moduleName: 'pointiconImage', - vertexShader: pointImageVert, - fragmentShader: pointImageFrag, - triangulation: PointImageTriangulation, - primitive: gl.POINTS, - depth: { enable: false }, - blend: this.getBlend(), - }), - ]; - } - - public clearModels() { - this.dataTexture?.destroy(); - } - - protected registerBuiltinAttributes() { - // point layer size; - this.styleAttributeService.registerStyleAttribute({ - name: 'size', - type: AttributeType.Attribute, - descriptor: { - name: 'a_Size', - buffer: { - // give the WebGL driver a hint that this buffer may change - usage: gl.DYNAMIC_DRAW, - data: [], - type: gl.FLOAT, - }, - size: 1, - update: ( - feature: IEncodeFeature, - featureIdx: number, - vertex: number[], - attributeIdx: number, - ) => { - const { size } = feature; - return Array.isArray(size) ? [size[0]] : [size as number]; - }, - }, - }); - - // point layer size; - this.styleAttributeService.registerStyleAttribute({ - name: 'uv', - type: AttributeType.Attribute, - descriptor: { - name: 'a_Uv', - buffer: { - // give the WebGL driver a hint that this buffer may change - usage: gl.DYNAMIC_DRAW, - data: [], - type: gl.FLOAT, - }, - size: 2, - update: ( - feature: IEncodeFeature, - featureIdx: number, - vertex: number[], - attributeIdx: number, - ) => { - const { mapping } = this.fontService; - const { shape } = feature; - const icon = this.fontService.getGlyph(shape as string); - const { x, y } = mapping[icon]; - return [x, y]; - }, - }, - }); - } - - private updateTexture() { - const { createTexture2D } = this.rendererService; - const { canvas } = this.fontService; - this.texture = createTexture2D({ - data: canvas, - mag: gl.LINEAR, - min: gl.LINEAR, - width: canvas.width, - height: canvas.height, - }); - } - - private initIconFontGlyphs() { - const { - fontWeight = 'normal', - fontFamily = 'sans-serif', - } = this.layer.getLayerConfig() as IIconIFontStyleOptions; - const data = this.layer.getEncodedData(); - const characterSet: string[] = []; - data.forEach((item: IEncodeFeature) => { - let { shape = '' } = item; - shape = shape.toString(); - const icon = this.fontService.getGlyph(shape); - if (characterSet.indexOf(icon) === -1) { - characterSet.push(icon); - } - }); - this.fontService.setFontOptions({ - characterSet, - fontWeight, - fontFamily, - fontSize: 48, - }); - } -} diff --git a/packages/layers/src/point/models/image.ts b/packages/layers/src/point/models/image.ts index f7b2aff2a8..b4d6964d53 100644 --- a/packages/layers/src/point/models/image.ts +++ b/packages/layers/src/point/models/image.ts @@ -76,11 +76,11 @@ export default class ImageModel extends BaseModel { }; } - public initModels(): IModel[] { + public initModels(callbackModel: (models: IModel[]) => void) { this.registerBuiltinAttributes(); this.updateTexture(); this.iconService.on('imageUpdate', this.updateTexture); - return this.buildModels(); + this.buildModels(callbackModel); } public clearModels() { @@ -89,23 +89,30 @@ export default class ImageModel extends BaseModel { this.iconService.off('imageUpdate', this.updateTexture); } - public buildModels(): IModel[] { + public buildModels(callbackModel: (models: IModel[]) => void) { const { mask = false, maskInside = true, } = this.layer.getLayerConfig() as IPointLayerStyleOptions; - return [ - this.layer.buildLayerModel({ + + this.layer + .buildLayerModel({ moduleName: 'pointImage', vertexShader: pointImageVert, fragmentShader: pointImageFrag, triangulation: PointImageTriangulation, - primitive: gl.POINTS, depth: { enable: false }, + primitive: gl.POINTS, blend: this.getBlend(), stencil: getMask(mask, maskInside), - }), - ]; + }) + .then((model) => { + callbackModel([model]); + }) + .catch((err) => { + console.warn(err); + callbackModel([]); + }); } protected registerBuiltinAttributes() { // point layer size; diff --git a/packages/layers/src/point/models/index.ts b/packages/layers/src/point/models/index.ts index 2e17487d3b..217a7fbe76 100644 --- a/packages/layers/src/point/models/index.ts +++ b/packages/layers/src/point/models/index.ts @@ -5,7 +5,6 @@ import EarthFillModel from './earthFill'; import ExtrudeModel from './extrude'; import FillModel from './fill'; import FillImageModel from './fillmage'; -import IconModel from './icon-font'; import IMageModel from './image'; import NormalModel from './normal'; import Radar from './radar'; @@ -22,7 +21,6 @@ export type PointType = | 'simplePoint' | 'extrude' | 'text' - | 'icon' | 'vectorpoint' | 'tile' | 'earthFill' @@ -37,7 +35,6 @@ const PointModels: { [key in PointType]: any } = { simplePoint: SimplePopint, extrude: ExtrudeModel, text: TextModel, - icon: IconModel, vectorpoint: PointTileModel, tile: TileFillModel, earthFill: EarthFillModel, diff --git a/packages/layers/src/point/models/normal.ts b/packages/layers/src/point/models/normal.ts index 5eee353f13..11a1da0f0c 100644 --- a/packages/layers/src/point/models/normal.ts +++ b/packages/layers/src/point/models/normal.ts @@ -83,19 +83,20 @@ export default class NormalModel extends BaseModel { }; } - public initModels(): IModel[] { - return this.buildModels(); + public initModels(callbackModel: (models: IModel[]) => void) { + this.buildModels(callbackModel); } - public buildModels(): IModel[] { + public buildModels(callbackModel: (models: IModel[]) => void) { const { mask = false, maskInside = true, } = this.layer.getLayerConfig() as IPointLayerStyleOptions; this.layer.triangulation = PointTriangulation; - return [ - this.layer.buildLayerModel({ - moduleName: 'normalpoint', + + this.layer + .buildLayerModel({ + moduleName: 'pointNormal', vertexShader: normalVert, fragmentShader: normalFrag, triangulation: PointTriangulation, @@ -103,8 +104,14 @@ export default class NormalModel extends BaseModel { primitive: gl.POINTS, blend: this.getBlend(), stencil: getMask(mask, maskInside), - }), - ]; + }) + .then((model) => { + callbackModel([model]); + }) + .catch((err) => { + console.warn(err); + callbackModel([]); + }); } public clearModels() { diff --git a/packages/layers/src/point/models/radar.ts b/packages/layers/src/point/models/radar.ts index 969ee79f68..73c957cd6b 100644 --- a/packages/layers/src/point/models/radar.ts +++ b/packages/layers/src/point/models/radar.ts @@ -9,7 +9,7 @@ import { IModel, IModelUniform, } from '@antv/l7-core'; -import { getCullFace, getMask } from '@antv/l7-utils'; +import { getMask } from '@antv/l7-utils'; import { isNumber } from 'lodash'; import BaseModel from '../../core/BaseModel'; import { IPointLayerStyleOptions } from '../../core/interface'; @@ -106,7 +106,7 @@ export default class RadarModel extends BaseModel { ); } - public initModels(): IModel[] { + public initModels(callbackModel: (models: IModel[]) => void) { const { unit = 'l7size', } = this.layer.getLayerConfig() as IPointLayerStyleOptions; @@ -120,7 +120,7 @@ export default class RadarModel extends BaseModel { this.calMeter2Coord(); } - return this.buildModels(); + this.buildModels(callbackModel); } /** @@ -165,36 +165,29 @@ export default class RadarModel extends BaseModel { } } - public buildModels(): IModel[] { + public buildModels(callbackModel: (models: IModel[]) => void) { const { mask = false, maskInside = true, } = this.layer.getLayerConfig() as IPointLayerStyleOptions; - const { frag, vert, type } = this.getShaders(); - return [ - this.layer.buildLayerModel({ - moduleName: type, - vertexShader: vert, - fragmentShader: frag, + this.layer + .buildLayerModel({ + moduleName: 'pointRadar', + vertexShader: pointFillVert, + fragmentShader: pointFillFrag, triangulation: PointFillTriangulation, depth: { enable: false }, blend: this.getBlend(), stencil: getMask(mask, maskInside), - }), - ]; - } - - /** - * 根据 animateOption 的值返回对应的 shader 代码 - * @returns - */ - public getShaders(): { frag: string; vert: string; type: string } { - return { - frag: pointFillFrag, - vert: pointFillVert, - type: 'point_radar', - }; + }) + .then((model) => { + callbackModel([model]); + }) + .catch((err) => { + console.warn(err); + callbackModel([]); + }); } public clearModels() { diff --git a/packages/layers/src/point/models/simplePoint.ts b/packages/layers/src/point/models/simplePoint.ts index 863bd8b4c8..d19bbe7cb4 100644 --- a/packages/layers/src/point/models/simplePoint.ts +++ b/packages/layers/src/point/models/simplePoint.ts @@ -93,19 +93,20 @@ export default class SimplePointModel extends BaseModel { }; } - public initModels(): IModel[] { - return this.buildModels(); + public initModels(callbackModel: (models: IModel[]) => void) { + this.buildModels(callbackModel); } - public buildModels(): IModel[] { + public buildModels(callbackModel: (models: IModel[]) => void) { const { mask = false, maskInside = true, } = this.layer.getLayerConfig() as IPointLayerStyleOptions; this.layer.triangulation = PointTriangulation; - return [ - this.layer.buildLayerModel({ - moduleName: 'simplepoint', + + this.layer + .buildLayerModel({ + moduleName: 'pointSimple', vertexShader: simplePointVert, fragmentShader: simplePointFrag, triangulation: PointTriangulation, @@ -113,8 +114,14 @@ export default class SimplePointModel extends BaseModel { primitive: gl.POINTS, blend: this.getBlend(), stencil: getMask(mask, maskInside), - }), - ]; + }) + .then((model) => { + callbackModel([model]); + }) + .catch((err) => { + console.warn(err); + callbackModel([]); + }); } public clearModels() { diff --git a/packages/layers/src/point/models/text.ts b/packages/layers/src/point/models/text.ts index b0192b05be..ace9357245 100644 --- a/packages/layers/src/point/models/text.ts +++ b/packages/layers/src/point/models/text.ts @@ -6,12 +6,16 @@ import { IModelUniform, ITexture2D, } from '@antv/l7-core'; -import { boundsContains, getMask, padBounds } from '@antv/l7-utils'; +import { + boundsContains, + calculateCentroid, + getMask, + padBounds, +} from '@antv/l7-utils'; import { isNumber } from 'lodash'; import BaseModel from '../../core/BaseModel'; import { IPointLayerStyleOptions } from '../../core/interface'; import CollisionIndex from '../../utils/collision-index'; -import { calculateCentroid } from '../../utils/geo'; import { getGlyphQuads, IGlyphQuad, @@ -172,8 +176,8 @@ export default class TextModel extends BaseModel { }; } - public initModels(): IModel[] { - this.layer.on('remapping', this.buildModels); + public initModels(callbackModel: (models: IModel[]) => void) { + this.layer.on('remapping', this.mapping); this.extent = this.textExtent(); const { textAnchor = 'center', @@ -183,20 +187,18 @@ export default class TextModel extends BaseModel { textAnchor, textAllowOverlap, }; - return this.buildModels(); + this.buildModels(callbackModel); } - public buildModels = () => { + public buildModels = async (callbackModel: (models: IModel[]) => void) => { const { mask = false, maskInside = true, } = this.layer.getLayerConfig() as IPointLayerStyleOptions; - this.initGlyph(); - this.updateTexture(); - this.filterGlyphs(); - this.reBuildModel(); - return [ - this.layer.buildLayerModel({ + this.mapping(); + + this.layer + .buildLayerModel({ moduleName: 'pointText', vertexShader: textVert, fragmentShader: textFrag, @@ -204,8 +206,14 @@ export default class TextModel extends BaseModel { depth: { enable: false }, blend: this.getBlend(), stencil: getMask(mask, maskInside), - }), - ]; + }) + .then((model) => { + callbackModel([model]); + }) + .catch((err) => { + console.warn(err); + callbackModel([]); + }); }; public needUpdate() { const { @@ -229,7 +237,7 @@ export default class TextModel extends BaseModel { public clearModels() { this.texture?.destroy(); this.dataTexture?.destroy(); - this.layer.off('remapping', this.buildModels); + this.layer.off('remapping', this.mapping); } protected registerBuiltinAttributes() { this.styleAttributeService.registerStyleAttribute({ @@ -326,6 +334,13 @@ export default class TextModel extends BaseModel { }, }); } + + private mapping = () => { + this.initGlyph(); + this.updateTexture(); + this.filterGlyphs(); + this.reBuildModel(); + }; private textExtent(): [[number, number], [number, number]] { const bounds = this.mapService.getBounds(); return padBounds(bounds, 0.5); @@ -519,8 +534,8 @@ export default class TextModel extends BaseModel { maskInside = true, } = this.layer.getLayerConfig() as IPointLayerStyleOptions; this.filterGlyphs(); - this.layer.models = [ - this.layer.buildLayerModel({ + this.layer + .buildLayerModel({ moduleName: 'pointText', vertexShader: textVert, fragmentShader: textFrag, @@ -528,7 +543,14 @@ export default class TextModel extends BaseModel { depth: { enable: false }, blend: this.getBlend(), stencil: getMask(mask, maskInside), - }), - ]; + }) + .then((model) => { + this.layer.models = [model]; + this.layer.renderLayers(); + }) + .catch((err) => { + console.warn(err); + this.layer.models = []; + }); } } diff --git a/packages/layers/src/point/models/tile.ts b/packages/layers/src/point/models/tile.ts index dad0629029..281fd48c81 100644 --- a/packages/layers/src/point/models/tile.ts +++ b/packages/layers/src/point/models/tile.ts @@ -112,7 +112,7 @@ export default class FillModel extends BaseModel { ); } - public initModels(): IModel[] { + public initModels(callbackModel: (models: IModel[]) => void) { const { unit = 'l7size', } = this.layer.getLayerConfig() as IPointLayerStyleOptions; @@ -126,7 +126,7 @@ export default class FillModel extends BaseModel { this.calMeter2Coord(); } - return this.buildModels(); + this.buildModels(callbackModel); } /** @@ -171,44 +171,41 @@ export default class FillModel extends BaseModel { } } - public buildModels(): IModel[] { + public buildModels(callbackModel: (models: IModel[]) => void) { const { mask = false, maskInside = true, + workerEnabled = false, } = this.layer.getLayerConfig() as Partial< ILayerConfig & IPointLayerStyleOptions >; - const { frag, vert, type } = this.getShaders(); this.layer.triangulation = PointFillTriangulation; - return [ - this.layer.buildLayerModel({ - // primitive: gl.POINTS, - moduleName: type, - vertexShader: vert, - fragmentShader: frag, + this.layer + .buildLayerModel({ + moduleName: 'pointTile', + vertexShader: point_tile_vert, + fragmentShader: point_tile_frag, triangulation: PointFillTriangulation, depth: { enable: false }, - blend: this.getBlend(), - stencil: getMask(mask, maskInside), cull: { enable: true, face: getCullFace(this.mapService.version), }, - }), - ]; - } - - /** - * 根据 animateOption 的值返回对应的 shader 代码 - * @returns - */ - public getShaders(): { frag: string; vert: string; type: string } { - return { - frag: point_tile_frag, - vert: point_tile_vert, - type: 'point_fill_tile', - }; + blend: this.getBlend(), + stencil: getMask(mask, maskInside), + workerEnabled, + workerOptions: { + modelType: 'pointTile', + }, + }) + .then((model) => { + callbackModel([model]); + }) + .catch((err) => { + console.warn(err); + callbackModel([]); + }); } public clearModels() { diff --git a/packages/layers/src/polygon/index.ts b/packages/layers/src/polygon/index.ts index 3aac6fe8fe..089d0f5509 100644 --- a/packages/layers/src/polygon/index.ts +++ b/packages/layers/src/polygon/index.ts @@ -8,10 +8,13 @@ export default class PolygonLayer extends BaseLayer { public buildModels() { const shape = this.getModelType(); this.layerModel = new PolygonModels[shape](this); - this.models = this.layerModel.initModels(); + this.layerModel.initModels((models) => { + this.models = models; + this.renderLayers(); + }); } public rebuildModels() { - this.models = this.layerModel.buildModels(); + this.layerModel.buildModels((models) => (this.models = models)); } protected getConfigSchema() { return { diff --git a/packages/layers/src/polygon/models/extrude.ts b/packages/layers/src/polygon/models/extrude.ts index 3f35210347..0dd1d710b7 100644 --- a/packages/layers/src/polygon/models/extrude.ts +++ b/packages/layers/src/polygon/models/extrude.ts @@ -93,28 +93,33 @@ export default class ExtrudeModel extends BaseModel { }; } - public initModels(): IModel[] { + public initModels(callbackModel: (models: IModel[]) => void) { this.loadTexture(); - return this.buildModels(); + this.buildModels(callbackModel); } - public buildModels(): IModel[] { + public buildModels(callbackModel: (models: IModel[]) => void) { const { mask = false, maskInside = true, } = this.layer.getLayerConfig() as IPolygonLayerStyleOptions; const { frag, vert, type } = this.getShaders(); - - return [ - this.layer.buildLayerModel({ + this.layer + .buildLayerModel({ moduleName: type, vertexShader: vert, fragmentShader: frag, triangulation: PolygonExtrudeTriangulation, stencil: getMask(mask, maskInside), - }), - ]; + }) + .then((model) => { + callbackModel([model]); + }) + .catch((err) => { + console.warn(err); + callbackModel([]); + }); } public getShaders() { diff --git a/packages/layers/src/polygon/models/fill.ts b/packages/layers/src/polygon/models/fill.ts index 2a4eac2a60..5952591200 100644 --- a/packages/layers/src/polygon/models/fill.ts +++ b/packages/layers/src/polygon/models/fill.ts @@ -2,17 +2,15 @@ import { AttributeType, gl, IEncodeFeature, + ILayerConfig, IModel, Triangulation, } from '@antv/l7-core'; -import { getMask } from '@antv/l7-utils'; +import { getMask, polygonFillTriangulation } from '@antv/l7-utils'; import { isNumber } from 'lodash'; import BaseModel from '../../core/BaseModel'; import { IPolygonLayerStyleOptions } from '../../core/interface'; -import { - polygonTriangulation, - polygonTriangulationWithCenter, -} from '../../core/triangulation'; +import { polygonTriangulationWithCenter } from '../../core/triangulation'; import polygon_frag from '../shaders/polygon_frag.glsl'; import polygon_linear_frag from '../shaders/polygon_linear_frag.glsl'; import polygon_linear_vert from '../shaders/polygon_linear_vert.glsl'; @@ -69,28 +67,44 @@ export default class FillModel extends BaseModel { }; } - public initModels(): IModel[] { - return this.buildModels(); + public initModels(callbackModel: (models: IModel[]) => void) { + this.buildModels(callbackModel); } - public buildModels(): IModel[] { + public buildModels(callbackModel: (models: IModel[]) => void) { const { frag, vert, triangulation, type } = this.getModelParams(); const { mask = false, maskInside = true, - } = this.layer.getLayerConfig() as IPolygonLayerStyleOptions; + workerEnabled = false, + enablePicking, + } = this.layer.getLayerConfig() as Partial< + ILayerConfig & IPolygonLayerStyleOptions + >; this.layer.triangulation = triangulation; - return [ - this.layer.buildLayerModel({ + this.layer + .buildLayerModel({ moduleName: type, vertexShader: vert, fragmentShader: frag, triangulation, - blend: this.getBlend(), + primitive: gl.TRIANGLES, depth: { enable: false }, + blend: this.getBlend(), stencil: getMask(mask, maskInside), - }), - ]; + workerEnabled, + workerOptions: { + modelType: type, + enablePicking, + }, + }) + .then((model) => { + callbackModel([model]); + }) + .catch((err) => { + console.warn(err); + callbackModel([]); + }); } public clearModels() { @@ -147,15 +161,15 @@ export default class FillModel extends BaseModel { return { frag: polygon_linear_frag, vert: polygon_linear_vert, - type: 'polygon_linear', + type: 'polygonLinear', triangulation: polygonTriangulationWithCenter, }; } else { return { frag: polygon_frag, vert: polygon_vert, - type: 'polygon_fill', - triangulation: polygonTriangulation, + type: 'polygonFill', + triangulation: polygonFillTriangulation, }; } } diff --git a/packages/layers/src/polygon/models/ocean.ts b/packages/layers/src/polygon/models/ocean.ts index 683f78ec6e..e8b883d88b 100644 --- a/packages/layers/src/polygon/models/ocean.ts +++ b/packages/layers/src/polygon/models/ocean.ts @@ -70,26 +70,33 @@ export default class OceanModel extends BaseModel { }; } - public initModels(): IModel[] { + public initModels(callbackModel: (models: IModel[]) => void) { this.loadTexture(); - return this.buildModels(); + this.buildModels(callbackModel); } - public buildModels(): IModel[] { + public buildModels(callbackModel: (models: IModel[]) => void) { const { mask = false, maskInside = true, } = this.layer.getLayerConfig() as IPolygonLayerStyleOptions; - return [ - this.layer.buildLayerModel({ - moduleName: 'polygon_ocean', + this.layer + .buildLayerModel({ + moduleName: 'polygonOcean', vertexShader: ocean_vert, fragmentShader: ocean_frag, triangulation: polygonTriangulation, + primitive: gl.TRIANGLES, depth: { enable: false }, stencil: getMask(mask, maskInside), - }), - ]; + }) + .then((model) => { + callbackModel([model]); + }) + .catch((err) => { + console.warn(err); + callbackModel([]); + }); } public clearModels() { diff --git a/packages/layers/src/polygon/models/tile.ts b/packages/layers/src/polygon/models/tile.ts index 93a497f9fd..fc2b6df5dd 100644 --- a/packages/layers/src/polygon/models/tile.ts +++ b/packages/layers/src/polygon/models/tile.ts @@ -53,28 +53,34 @@ export default class FillModel extends BaseModel { }; } - public initModels(): IModel[] { - return this.buildModels(); + public initModels(callbackModel: (models: IModel[]) => void) { + this.buildModels(callbackModel); } - public buildModels(): IModel[] { - const { frag, vert, triangulation, type } = this.getModelParams(); + public buildModels(callbackModel: (models: IModel[]) => void) { const { mask = false, maskInside = true, } = this.layer.getLayerConfig() as IPolygonLayerStyleOptions; - this.layer.triangulation = triangulation; - return [ - this.layer.buildLayerModel({ - moduleName: type, - vertexShader: vert, - fragmentShader: frag, - triangulation, - blend: this.getBlend(), + this.layer.triangulation = polygonTriangulation; + this.layer + .buildLayerModel({ + moduleName: 'polygonTile', + vertexShader: polygon_tile_vert, + fragmentShader: polygon_tile_frag, + triangulation: polygonTriangulation, + primitive: gl.TRIANGLES, depth: { enable: false }, + blend: this.getBlend(), stencil: getMask(mask, maskInside), - }), - ]; + }) + .then((model) => { + callbackModel([model]); + }) + .catch((err) => { + console.warn(err); + callbackModel([]); + }); } public clearModels() { @@ -84,18 +90,4 @@ export default class FillModel extends BaseModel { protected registerBuiltinAttributes() { // } - - private getModelParams(): { - frag: string; - vert: string; - type: string; - triangulation: Triangulation; - } { - return { - frag: polygon_tile_frag, - vert: polygon_tile_vert, - type: 'polygon_tile', - triangulation: polygonTriangulation, - }; - } } diff --git a/packages/layers/src/polygon/models/water.ts b/packages/layers/src/polygon/models/water.ts index 8e92ca5cc7..0a4c52e29c 100644 --- a/packages/layers/src/polygon/models/water.ts +++ b/packages/layers/src/polygon/models/water.ts @@ -64,26 +64,33 @@ export default class WaterModel extends BaseModel { }; } - public initModels(): IModel[] { + public initModels(callbackModel: (models: IModel[]) => void) { this.loadTexture(); - return this.buildModels(); + this.buildModels(callbackModel); } - public buildModels(): IModel[] { + public buildModels(callbackModel: (models: IModel[]) => void) { const { mask = false, maskInside = true, } = this.layer.getLayerConfig() as IPolygonLayerStyleOptions; - return [ - this.layer.buildLayerModel({ - moduleName: 'polygon_water', + this.layer + .buildLayerModel({ + moduleName: 'polygonWater', vertexShader: water_vert, fragmentShader: water_frag, triangulation: polygonTriangulation, + primitive: gl.TRIANGLES, depth: { enable: false }, stencil: getMask(mask, maskInside), - }), - ]; + }) + .then((model) => { + callbackModel([model]); + }) + .catch((err) => { + console.warn(err); + callbackModel([]); + }); } public clearModels() { diff --git a/packages/layers/src/raster/image.ts b/packages/layers/src/raster/image.ts deleted file mode 100644 index 0722b79a59..0000000000 --- a/packages/layers/src/raster/image.ts +++ /dev/null @@ -1,106 +0,0 @@ -// import { -// AttributeType, -// gl, -// IEncodeFeature, -// ILayer, -// ITexture2D, -// } from '@antv/l7-core'; -// import BaseLayer from '../core/BaseLayer'; -// import { RasterImageTriangulation } from '../core/triangulation'; -// import rasterImageFrag from './shaders/image_frag.glsl'; -// import rasterImageVert from './shaders/image_vert.glsl'; -// interface IRaterLayerStyleOptions { -// opacity: number; -// } - -// export default class ImageLayer extends BaseLayer { -// public type: string = 'ImageLayer'; -// protected texture: ITexture2D; - -// protected getConfigSchema() { -// return { -// properties: { -// opacity: { -// type: 'number', -// minimum: 0, -// maximum: 1, -// }, -// }, -// }; -// } - -// protected renderModels() { -// const { opacity } = this.getLayerConfig(); -// if (this.texture) { -// this.models.forEach((model) => -// model.draw({ -// uniforms: { -// u_opacity: opacity || 1, -// u_texture: this.texture, -// }, -// }), -// ); -// } - -// return this; -// } - -// public buildModels() { -// this.registerBuiltinAttributes(); -// const source = this.getSource(); -// const { createTexture2D } = this.rendererService; -// source.data.images.then((imageData: HTMLImageElement[]) => { -// this.texture = createTexture2D({ -// data: imageData[0], -// width: imageData[0].width, -// height: imageData[0].height, -// }); -// this.renderModels(); -// }); -// this.models = [ -// this.buildLayerModel({ -// moduleName: 'RasterImage', -// vertexShader: rasterImageVert, -// fragmentShader: rasterImageFrag, -// triangulation: RasterImageTriangulation, -// primitive: gl.TRIANGLES, -// depth: { enable: false }, -// blend: { -// enable: true, -// func: { -// srcRGB: gl.SRC_ALPHA, -// srcAlpha: 1, -// dstRGB: gl.ONE_MINUS_SRC_ALPHA, -// dstAlpha: 1, -// }, -// }, -// }), -// ]; -// } - -// private registerBuiltinAttributes() { -// // point layer size; -// this.styleAttributeService.registerStyleAttribute({ -// name: 'uv', -// type: AttributeType.Attribute, -// descriptor: { -// name: 'a_Uv', -// buffer: { -// // give the WebGL driver a hint that this buffer may change -// usage: gl.DYNAMIC_DRAW, -// data: [], -// type: gl.FLOAT, -// }, -// size: 2, -// update: ( -// feature: IEncodeFeature, -// featureIdx: number, -// vertex: number[], -// attributeIdx: number, -// ) => { -// return [vertex[3], vertex[4]]; -// }, -// }, -// }); -// } -// } diff --git a/packages/layers/src/raster/index.ts b/packages/layers/src/raster/index.ts index f86c6d4b91..754eec0c51 100644 --- a/packages/layers/src/raster/index.ts +++ b/packages/layers/src/raster/index.ts @@ -6,10 +6,13 @@ export default class RaterLayer extends BaseLayer { public buildModels() { const modelType = this.getModelType(); this.layerModel = new RasterModels[modelType](this); - this.models = this.layerModel.initModels(); + this.layerModel.initModels((models) => { + this.models = models; + this.renderLayers(); + }); } public rebuildModels() { - this.models = this.layerModel.buildModels(); + this.layerModel.buildModels((models) => (this.models = models)); } protected getConfigSchema() { return { diff --git a/packages/layers/src/raster/models/raster.ts b/packages/layers/src/raster/models/raster.ts index ba604ec8f0..4c7766ad26 100644 --- a/packages/layers/src/raster/models/raster.ts +++ b/packages/layers/src/raster/models/raster.ts @@ -2,6 +2,7 @@ import { AttributeType, gl, IEncodeFeature, + IModel, ITexture2D, lazyInject, TYPES, @@ -42,7 +43,7 @@ export default class RasterModel extends BaseModel { }; } - public initModels() { + public initModels(callbackModel: (models: IModel[]) => void) { const { mask = false, maskInside = true, @@ -69,22 +70,28 @@ export default class RasterModel extends BaseModel { height: imageData.height, flipY: false, }); - return [ - this.layer.buildLayerModel({ - moduleName: 'RasterImageData', + + this.layer + .buildLayerModel({ + moduleName: 'rasterImageData', vertexShader: rasterVert, fragmentShader: rasterFrag, triangulation: RasterImageTriangulation, primitive: gl.TRIANGLES, depth: { enable: false }, - blend: this.getBlend(), stencil: getMask(mask, maskInside), - }), - ]; + }) + .then((model) => { + callbackModel([model]); + }) + .catch((err) => { + console.warn(err); + callbackModel([]); + }); } - public buildModels() { - return this.initModels(); + public buildModels(callbackModel: (models: IModel[]) => void) { + this.initModels(callbackModel); } public clearModels(): void { diff --git a/packages/layers/src/raster/raster2d.ts b/packages/layers/src/raster/raster2d.ts deleted file mode 100644 index 1820ba87ba..0000000000 --- a/packages/layers/src/raster/raster2d.ts +++ /dev/null @@ -1,118 +0,0 @@ -import { AttributeType, gl, IEncodeFeature, ITexture2D } from '@antv/l7-core'; -import { generateColorRamp, IColorRamp } from '@antv/l7-utils'; -import BaseLayer from '../core/BaseLayer'; -import { RasterImageTriangulation } from '../core/triangulation'; -import rasterImageFrag from './shaders/raster_2d_frag.glsl'; -import rasterImageVert from './shaders/raster_2d_vert.glsl'; -interface IRasterLayerStyleOptions { - opacity: number; - min: number; - max: number; - rampColors: IColorRamp; -} - -export default class Raster2dLayer extends BaseLayer { - public type: string = 'RasterLayer'; - protected rasterTexture: ITexture2D; - protected colorTexture: ITexture2D; - - public buildModels() { - this.registerBuiltinAttributes(); - const source = this.getSource(); - const { createTexture2D } = this.rendererService; - const parserDataItem = this.getSource().data.dataArray[0]; - this.rasterTexture = createTexture2D({ - data: parserDataItem.data, - width: parserDataItem.width, - height: parserDataItem.height, - format: gl.LUMINANCE, - type: gl.FLOAT, - aniso: 4, - }); - const { rampColors } = this.getLayerConfig(); - const imageData = generateColorRamp(rampColors as IColorRamp); - this.colorTexture = createTexture2D({ - data: imageData.data, - width: imageData.width, - height: imageData.height, - flipY: false, - }); - this.models = [ - this.buildLayerModel({ - moduleName: 'Raster3DImage', - vertexShader: rasterImageVert, - fragmentShader: rasterImageFrag, - triangulation: RasterImageTriangulation, - primitive: gl.TRIANGLES, - depth: { enable: false }, - blend: { - enable: true, - func: { - srcRGB: gl.SRC_ALPHA, - srcAlpha: 1, - dstRGB: gl.ONE_MINUS_SRC_ALPHA, - dstAlpha: 1, - }, - }, - }), - ]; - } - public renderModels() { - const { opacity } = this.getLayerConfig(); - const parserDataItem = this.getSource().data.dataArray[0]; - const { min, max } = parserDataItem; - if (this.rasterTexture) { - this.models.forEach((model) => - model.draw({ - uniforms: { - u_opacity: opacity || 1, - u_texture: this.rasterTexture, - u_min: min, - u_max: max, - u_colorTexture: this.colorTexture, - }, - }), - ); - } - - return this; - } - - protected getConfigSchema() { - return { - properties: { - opacity: { - type: 'number', - minimum: 0, - maximum: 1, - }, - }, - }; - } - - private registerBuiltinAttributes() { - // point layer size; - this.styleAttributeService.registerStyleAttribute({ - name: 'uv', - type: AttributeType.Attribute, - descriptor: { - name: 'a_Uv', - buffer: { - // give the WebGL driver a hint that this buffer may change - usage: gl.DYNAMIC_DRAW, - data: [], - type: gl.FLOAT, - }, - size: 2, - update: ( - feature: IEncodeFeature, - featureIdx: number, - vertex: number[], - attributeIdx: number, - ) => { - return [vertex[3], vertex[4]]; - }, - }, - }); - } -} diff --git a/packages/layers/src/tile/manager/tileLayerManager.ts b/packages/layers/src/tile/manager/tileLayerManager.ts index be208dbc7f..903b3b2d63 100644 --- a/packages/layers/src/tile/manager/tileLayerManager.ts +++ b/packages/layers/src/tile/manager/tileLayerManager.ts @@ -150,6 +150,7 @@ export class TileLayerManager implements ITileLayerManager { positions: [0, 0.25, 0.5, 0.75, 1.0], }, featureId = 'id', + workerEnabled = false, sourceLayer, pixelConstant = 0, @@ -197,6 +198,8 @@ export class TileLayerManager implements ITileLayerManager { domain, rampColors, rampColorsData: this.rampColorsData, + // worker + workerEnabled, pixelConstant, pixelConstantR, diff --git a/packages/layers/src/tile/manager/tilePickerManager.ts b/packages/layers/src/tile/manager/tilePickerManager.ts index aae59a0f36..aaa8cb0fff 100644 --- a/packages/layers/src/tile/manager/tilePickerManager.ts +++ b/packages/layers/src/tile/manager/tilePickerManager.ts @@ -50,6 +50,7 @@ export default class TilePickManager extends EventEmitter framebuffer: null, }); layer.masks.map((m: ILayer) => { + m.hooks.beforeRenderData.call(); m.hooks.beforeRender.call(); m.render(); m.hooks.afterRender.call(); diff --git a/packages/layers/src/tile/tileFactory/base.ts b/packages/layers/src/tile/tileFactory/base.ts index 8ed24e330a..06fc03c65d 100644 --- a/packages/layers/src/tile/tileFactory/base.ts +++ b/packages/layers/src/tile/tileFactory/base.ts @@ -129,10 +129,6 @@ export default class TileFactory implements ITileFactory { // set scale this.setScale(layer); - // console.log(this.parentLayer.getScaleOptions()) - // console.log() - - // console.log(this.parentLayer.tileLayer.scaleCfg) // set scale attribute field this.setStyleAttributeField(layer, 'shape', shape); diff --git a/packages/layers/src/tile/tileFactory/point.ts b/packages/layers/src/tile/tileFactory/point.ts index 69e66fdad8..2c1b1dc2a7 100644 --- a/packages/layers/src/tile/tileFactory/point.ts +++ b/packages/layers/src/tile/tileFactory/point.ts @@ -23,14 +23,12 @@ export default class VectorPolygonTile extends TileFactory { layerIDList: [], }; } - const layer = this.createLayer({ tile, initOptions, vectorTileLayer, source: source as Source, }); - return { layers: [layer], layerIDList: [layer.id], diff --git a/packages/layers/src/tile/tileFactory/rasterDataLayer.ts b/packages/layers/src/tile/tileFactory/rasterDataLayer.ts index c2afa386b9..36bebcd234 100644 --- a/packages/layers/src/tile/tileFactory/rasterDataLayer.ts +++ b/packages/layers/src/tile/tileFactory/rasterDataLayer.ts @@ -9,11 +9,14 @@ export default class RasterTiffLayer extends BaseLayer< public buildModels() { const model = this.getModelType(); this.layerModel = new model(this); - this.models = this.layerModel.initModels(); + this.layerModel.initModels((models) => { + this.models = models; + this.renderLayers(); + }); } public rebuildModels() { - this.models = this.layerModel.buildModels(); + this.layerModel.buildModels((models) => (this.models = models)); } protected getModelType() { diff --git a/packages/layers/src/tile/tileFactory/vectorLayer.ts b/packages/layers/src/tile/tileFactory/vectorLayer.ts index f764fcaeeb..841a42d076 100644 --- a/packages/layers/src/tile/tileFactory/vectorLayer.ts +++ b/packages/layers/src/tile/tileFactory/vectorLayer.ts @@ -31,11 +31,14 @@ export default class VectorLayer extends BaseLayer< public buildModels() { const model = this.getModelType(); this.layerModel = new model(this); - this.models = this.layerModel.initModels(); + this.layerModel.initModels((models) => { + this.models = models; + this.renderLayers(); + }); } public rebuildModels() { - this.models = this.layerModel.buildModels(); + this.layerModel.buildModels((models) => (this.models = models)); } protected getModelType() { diff --git a/packages/layers/src/utils/geo.ts b/packages/layers/src/utils/geo.ts deleted file mode 100644 index 366ce9dc8d..0000000000 --- a/packages/layers/src/utils/geo.ts +++ /dev/null @@ -1,60 +0,0 @@ -type Position = number[]; -import { isNumber } from 'lodash'; -export function calculateCentroid( - coord: Position | Position[] | Position[][], -): Position { - // let pos = coord as Position; - if (isNumber(coord[0])) { - return coord as Position; - } else if (isNumber(coord[0][0])) { - throw new Error('当前数据不支持标注'); - } else if (isNumber(coord[0][0][0])) { - const coords = coord as Position[][]; - let xSum = 0; - let ySum = 0; - let len = 0; - coords.forEach((coor: Position[]) => { - coor.forEach((pos) => { - xSum += pos[0]; - ySum += pos[1]; - len++; - }); - }); - return [xSum / len, ySum / len, 0]; - } else { - throw new Error('当前数据不支持标注'); - } -} - -/** - * 计算 - * @param points - * @returns - */ -export function calculatePointsCenterAndRadius(points: number[]) { - let maxX = points[0]; - let maxY = points[1]; - let minX = points[0]; - let minY = points[1]; - let xCount = 0; - let yCount = 0; - let pCount = 0; - - for (let i = 0; i < points.length; i += 2) { - const x = points[i]; - const y = points[i + 1]; - if (x && y) { - maxX = Math.max(x, maxX); - maxY = Math.max(y, maxY); - minX = Math.min(x, minX); - minY = Math.min(y, minY); - xCount += x; - yCount += y; - pCount++; - } - } - return { - center: [xCount / pCount, yCount / pCount], - radius: Math.sqrt(Math.pow(maxX - minX, 2) + Math.pow(maxY - minY, 2)) / 2, - }; -} diff --git a/packages/layers/src/wind/index.ts b/packages/layers/src/wind/index.ts index c4e00b62da..4ccab5b618 100644 --- a/packages/layers/src/wind/index.ts +++ b/packages/layers/src/wind/index.ts @@ -6,10 +6,13 @@ export default class WindLayer extends BaseLayer { public buildModels() { const modelType = this.getModelType(); this.layerModel = new WindModels[modelType](this); - this.models = this.layerModel.initModels(); + this.layerModel.initModels((models) => { + this.models = models; + this.renderLayers(); + }); } public rebuildModels() { - this.models = this.layerModel.buildModels(); + this.layerModel.buildModels((models) => (this.models = models)); } public renderModels() { diff --git a/packages/layers/src/wind/models/wind.ts b/packages/layers/src/wind/models/wind.ts index dc0979f7d5..ff2707ccd4 100644 --- a/packages/layers/src/wind/models/wind.ts +++ b/packages/layers/src/wind/models/wind.ts @@ -50,7 +50,7 @@ export default class WindModel extends BaseModel { throw new Error('Method not implemented.'); } - public initModels() { + public initModels(callbackModel: (models: IModel[]) => void) { const { uMin = -21.32, uMax = 26.8, @@ -114,18 +114,24 @@ export default class WindModel extends BaseModel { this.layerService.renderLayers(); }); - this.colorModel = this.layer.buildLayerModel({ - moduleName: 'WindLayer', - vertexShader: WindVert, - fragmentShader: WindFrag, - triangulation: RasterImageTriangulation, - primitive: gl.TRIANGLES, - depth: { enable: false }, - blend: this.getBlend(), - stencil: getMask(mask, maskInside), - }); - - return [this.colorModel]; + this.layer + .buildLayerModel({ + moduleName: 'wind', + vertexShader: WindVert, + fragmentShader: WindFrag, + triangulation: RasterImageTriangulation, + primitive: gl.TRIANGLES, + depth: { enable: false }, + blend: this.getBlend(), + }) + .then((model) => { + this.colorModel = model; + callbackModel([model]); + }) + .catch((err) => { + console.warn(err); + callbackModel([]); + }); } public getWindSize() { @@ -143,8 +149,8 @@ export default class WindModel extends BaseModel { return { imageWidth, imageHeight }; } - public buildModels() { - return this.initModels(); + public buildModels(callbackModel: (models: IModel[]) => void) { + this.initModels(callbackModel); } public clearModels(): void { @@ -254,7 +260,8 @@ export default class WindModel extends BaseModel { m.render(); m.hooks.afterRender.call(); }); - this.colorModel.draw({ + + this.colorModel?.draw({ uniforms: { u_opacity: opacity || 1.0, u_texture: this.texture, diff --git a/packages/map/package.json b/packages/map/package.json index bb80994b4a..886efd1a6c 100644 --- a/packages/map/package.json +++ b/packages/map/package.json @@ -27,9 +27,9 @@ "tsc": "tsc --project tsconfig.build.json", "clean": "rimraf dist; rimraf es; rimraf lib;", "build": "run-p build:*", - "build:cjs": "BABEL_ENV=cjs babel src --root-mode upward --out-dir lib --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments", - "build:esm": "BABEL_ENV=esm babel src --root-mode upward --out-dir es --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments", - "watch": "BABEL_ENV=cjs babel src --watch --root-mode upward --out-dir lib --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments", + "build:cjs": "cross-env BABEL_ENV=cjs NODE_ENV=production babel src --root-mode upward --out-dir lib --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments", + "build:esm": "cross-env BABEL_ENV=esm NODE_ENV=production babel src --root-mode upward --out-dir es --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments", + "watch": "cross-env BABEL_ENV=cjs NODE_ENV=production babel src --watch --root-mode upward --out-dir lib --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments", "test": "jest" }, "bugs": { diff --git a/packages/maps/package.json b/packages/maps/package.json index 728d2e45a8..0054282d10 100644 --- a/packages/maps/package.json +++ b/packages/maps/package.json @@ -18,9 +18,9 @@ "tsc": "tsc --project tsconfig.build.json", "clean": "rimraf dist; rimraf es; rimraf lib;", "build": "run-p build:*", - "build:cjs": "BABEL_ENV=cjs babel src --root-mode upward --out-dir lib --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments", - "build:esm": "BABEL_ENV=esm babel src --root-mode upward --out-dir es --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments", - "watch": "BABEL_ENV=cjs babel src --watch --root-mode upward --out-dir lib --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments", + "build:cjs": "cross-env BABEL_ENV=cjs NODE_ENV=production babel src --root-mode upward --out-dir lib --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments", + "build:esm": "cross-env BABEL_ENV=esm NODE_ENV=production babel src --root-mode upward --out-dir es --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments", + "watch": "cross-env BABEL_ENV=cjs NODE_ENV=production babel src --watch --root-mode upward --out-dir lib --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments", "sync": "tnpm sync" }, "author": "xiaoiver", diff --git a/packages/mini/package.json b/packages/mini/package.json index e3ad017147..c2c764cb55 100644 --- a/packages/mini/package.json +++ b/packages/mini/package.json @@ -17,9 +17,9 @@ "tsc": "tsc --project tsconfig.build.json", "clean": "rimraf dist; rimraf es; rimraf lib;", "build": "run-p build:*", - "build:cjs": "BABEL_ENV=cjs babel src --root-mode upward --out-dir lib --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments", - "build:esm": "BABEL_ENV=esm babel src --root-mode upward --out-dir es --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments", - "watch": "BABEL_ENV=cjs babel src --watch --root-mode upward --out-dir lib --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments", + "build:cjs": "cross-env BABEL_ENV=cjs NODE_ENV=production babel src --root-mode upward --out-dir lib --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments", + "build:esm": "cross-env BABEL_ENV=esm NODE_ENV=production babel src --root-mode upward --out-dir es --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments", + "watch": "cross-env BABEL_ENV=cjs NODE_ENV=production babel src --watch --root-mode upward --out-dir lib --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments", "sync": "tnpm sync" }, "author": "antv", diff --git a/packages/renderer/package.json b/packages/renderer/package.json index 8c72893d2b..d66f63d3c8 100644 --- a/packages/renderer/package.json +++ b/packages/renderer/package.json @@ -15,9 +15,9 @@ "tsc": "tsc --project tsconfig.build.json", "clean": "rimraf dist; rimraf es; rimraf lib;", "build": "run-p build:*", - "build:cjs": "BABEL_ENV=cjs babel src --root-mode upward --out-dir lib --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments", - "build:esm": "BABEL_ENV=esm babel src --root-mode upward --out-dir es --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments", - "watch": "BABEL_ENV=cjs babel src --watch --root-mode upward --out-dir lib --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments", + "build:cjs": "cross-env BABEL_ENV=cjs NODE_ENV=production NODE_ENV=production babel src --root-mode upward --out-dir lib --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments", + "build:esm": "cross-env BABEL_ENV=esm NODE_ENV=production NODE_ENV=production babel src --root-mode upward --out-dir es --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments", + "watch": "cross-env BABEL_ENV=cjs NODE_ENV=production NODE_ENV=production babel src --watch --root-mode upward --out-dir lib --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments", "sync": "tnpm sync" }, "author": "xiaoiver", diff --git a/packages/scene/package.json b/packages/scene/package.json index f414656150..da7ec75763 100644 --- a/packages/scene/package.json +++ b/packages/scene/package.json @@ -15,9 +15,9 @@ "tsc": "tsc --project tsconfig.build.json", "clean": "rimraf dist; rimraf es; rimraf lib;", "build": "run-p build:*", - "build:cjs": "BABEL_ENV=cjs babel src --root-mode upward --out-dir lib --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments", - "build:esm": "BABEL_ENV=esm babel src --root-mode upward --out-dir es --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments", - "watch": "BABEL_ENV=cjs babel src --watch --root-mode upward --out-dir lib --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments", + "build:cjs": "cross-env BABEL_ENV=cjs NODE_ENV=production babel src --root-mode upward --out-dir lib --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments", + "build:esm": "cross-env BABEL_ENV=esm NODE_ENV=production babel src --root-mode upward --out-dir es --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments", + "watch": "cross-env BABEL_ENV=cjs NODE_ENV=production babel src --watch --root-mode upward --out-dir lib --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments", "sync": "tnpm sync" }, "author": "xiaoiver", diff --git a/packages/source/package.json b/packages/source/package.json index 074ef7ac3b..7aec61b71f 100644 --- a/packages/source/package.json +++ b/packages/source/package.json @@ -15,9 +15,9 @@ "tsc": "tsc --project tsconfig.build.json", "clean": "rimraf dist; rimraf es; rimraf lib;", "build": "run-p build:*", - "build:cjs": "BABEL_ENV=cjs babel src --root-mode upward --out-dir lib --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments", - "build:esm": "BABEL_ENV=esm babel src --root-mode upward --out-dir es --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments", - "watch": "BABEL_ENV=cjs babel src --watch --root-mode upward --out-dir lib --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments", + "build:cjs": "cross-env BABEL_ENV=cjs NODE_ENV=production babel src --root-mode upward --out-dir lib --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments", + "build:esm": "cross-env BABEL_ENV=esm NODE_ENV=production babel src --root-mode upward --out-dir es --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments", + "watch": "cross-env BABEL_ENV=cjs NODE_ENV=production babel src --watch --root-mode upward --out-dir lib --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments", "lint:ts": "run-p -c lint:ts-*", "test": "jest", "sync": "tnpm sync" diff --git a/packages/source/src/index.ts b/packages/source/src/index.ts index e951743583..2d7063b771 100644 --- a/packages/source/src/index.ts +++ b/packages/source/src/index.ts @@ -2,7 +2,7 @@ import { registerParser, registerTransform } from './factory'; import csv from './parser/csv'; import geojson from './parser/geojson'; import image from './parser/image'; -import json, { defaultData, defaultParser } from './parser/json'; +import json, { defaultData, defaultParser, defaultSource } from './parser/json'; import mapboxVectorTile from './parser/mvt'; import raster from './parser/raster'; import rasterTile from './parser/raster-tile'; @@ -37,6 +37,7 @@ export { export * from './interface'; +export const DEFAULT_SOURCE = defaultSource; export const DEFAULT_DATA = defaultData; export const DEFAULT_PARSER = defaultParser; diff --git a/packages/source/src/parser/json.ts b/packages/source/src/parser/json.ts index 5d0596bb01..c1baa293d0 100644 --- a/packages/source/src/parser/json.ts +++ b/packages/source/src/parser/json.ts @@ -53,6 +53,38 @@ export default function json(data: IJsonData, cfg: IParserCfg): IParserData { }; } +export const defaultSource = { + PointLayer: { + data: [], + options: { + parser: { + type: 'json', + x: 'lng', + y: 'lat', + }, + }, + }, + LineLayer: { + data: [ + { + lng1: 100, + lat1: 30.0, + lng2: 130, + lat2: 30, + }, + ], + options: { + parser: { + type: 'json', + x: 'lng1', + y: 'lat1', + x1: 'lng2', + y1: 'lat2', + }, + }, + }, +}; + // TODO: 提供默认数据和解析器 export const defaultData = [ { diff --git a/packages/source/src/source.ts b/packages/source/src/source.ts index eff19a2097..295d917594 100644 --- a/packages/source/src/source.ts +++ b/packages/source/src/source.ts @@ -34,6 +34,7 @@ function mergeCustomizer(objValue: any, srcValue: any) { } export default class Source extends EventEmitter implements ISource { + public inited: boolean = false; public data: IParserData; public center: [number, number]; // 数据范围 @@ -75,15 +76,6 @@ export default class Source extends EventEmitter implements ISource { this.originData = data; this.initCfg(cfg); - this.hooks.init.tap('parser', () => { - this.excuteParser(); - }); - this.hooks.init.tap('cluster', () => { - this.initCluster(); - }); - this.hooks.init.tap('transform', () => { - this.executeTrans(); - }); this.init(); } @@ -188,7 +180,6 @@ export default class Source extends EventEmitter implements ISource { this.dataArrayChanged = false; this.initCfg(options); this.init(); - this.emit('update'); } public destroy() { @@ -200,6 +191,19 @@ export default class Source extends EventEmitter implements ISource { this.tileset?.destroy(); } + private handleData() { + return new Promise((resolve, reject) => { + try { + this.excuteParser(); + this.initCluster(); + this.executeTrans(); + resolve({}); + } catch (err) { + reject(err); + } + }); + } + private initCfg(option?: ISourceCFG) { this.cfg = mergeWith(this.cfg, option, mergeCustomizer); const cfg = this.cfg; @@ -222,7 +226,12 @@ export default class Source extends EventEmitter implements ISource { } private init() { - this.hooks.init.call(this); + // this.hooks.init.call(this); + this.inited = false; + this.handleData().then(() => { + this.inited = true; + this.emit('sourceUpdate'); + }); } /** diff --git a/packages/three/package.json b/packages/three/package.json index 60eca49271..74ffaa0283 100644 --- a/packages/three/package.json +++ b/packages/three/package.json @@ -31,9 +31,9 @@ "tsc": "tsc --project tsconfig.build.json", "clean": "rimraf dist; rimraf es; rimraf lib;", "build": "run-p build:*", - "build:cjs": "BABEL_ENV=cjs babel src --root-mode upward --out-dir lib --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments", - "build:esm": "BABEL_ENV=esm babel src --root-mode upward --out-dir es --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments", - "watch": "BABEL_ENV=cjs babel src --watch --root-mode upward --out-dir lib --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments", + "build:cjs": "cross-env BABEL_ENV=cjs NODE_ENV=production babel src --root-mode upward --out-dir lib --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments", + "build:esm": "cross-env BABEL_ENV=esm NODE_ENV=production babel src --root-mode upward --out-dir es --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments", + "watch": "cross-env BABEL_ENV=cjs NODE_ENV=production babel src --watch --root-mode upward --out-dir lib --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments", "build:cdn": "yarn rollup -c", "lint:ts": "run-p -c lint:ts-*", "test": "jest", diff --git a/packages/utils/package.json b/packages/utils/package.json index 32e4153736..e927e7a13f 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -9,15 +9,16 @@ "files": [ "lib", "es", + "dist", "README.md" ], "scripts": { "tsc": "tsc --project tsconfig.build.json", "clean": "rimraf dist; rimraf es; rimraf lib;", "build": "run-p build:*", - "build:cjs": "BABEL_ENV=cjs babel src --root-mode upward --out-dir lib --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments", - "build:esm": "BABEL_ENV=esm babel src --root-mode upward --out-dir es --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments", - "watch": "BABEL_ENV=cjs babel src --watch --root-mode upward --out-dir lib --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments", + "build:cjs": "cross-env BABEL_ENV=cjs NODE_ENV=production babel src --root-mode upward --out-dir lib --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments", + "build:esm": "cross-env BABEL_ENV=esm NODE_ENV=production babel src --root-mode upward --out-dir es --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments", + "watch": "cross-env BABEL_ENV=cjs NODE_ENV=production babel src --watch --root-mode upward --out-dir lib --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments", "sync": "tnpm sync" }, "author": "lzxue", @@ -26,10 +27,13 @@ "@babel/runtime": "^7.7.7", "@turf/bbox-polygon": "^6.5.0", "@turf/helpers": "^6.1.4", - "d3-color": "^1.4.0" + "d3-color": "^1.4.0", + "web-worker-helper": "^0.0.3", + "earcut": "^2.2.1" }, "devDependencies": { - "@types/d3-color": "^1.2.2" + "@types/d3-color": "^1.2.2", + "@types/earcut": "^2.1.0" }, "gitHead": "684ba4eb806a798713496d3fc0b4d1e17517dc31", "publishConfig": { diff --git a/packages/utils/src/geo.ts b/packages/utils/src/geo.ts index 464e263e38..dfb1618932 100644 --- a/packages/utils/src/geo.ts +++ b/packages/utils/src/geo.ts @@ -6,6 +6,7 @@ import { radiansToLength, Units, } from '@turf/helpers'; +import { isNumber } from './math'; export type IBounds = [[number, number], [number, number]]; interface ILngLat { @@ -357,3 +358,66 @@ export function flow(coords: Point[], time: number = 100) { }); return path; } + +type Position = number[]; + +export function calculateCentroid( + coord: Position | Position[] | Position[][], +): Position { + // let pos = coord as Position; + if (isNumber(coord[0])) { + return coord as Position; + // @ts-ignore + } else if (isNumber(coord[0][0])) { + throw new Error('当前数据不支持标注'); + // @ts-ignore + } else if (isNumber(coord[0][0][0])) { + const coords = coord as Position[][]; + let xSum = 0; + let ySum = 0; + let len = 0; + coords.forEach((coor: Position[]) => { + coor.forEach((pos) => { + xSum += pos[0]; + ySum += pos[1]; + len++; + }); + }); + return [xSum / len, ySum / len, 0]; + } else { + throw new Error('当前数据不支持标注'); + } +} + +/** + * 计算 + * @param points + * @returns + */ +export function calculatePointsCenterAndRadius(points: number[]) { + let maxX = points[0]; + let maxY = points[1]; + let minX = points[0]; + let minY = points[1]; + let xCount = 0; + let yCount = 0; + let pCount = 0; + + for (let i = 0; i < points.length; i += 2) { + const x = points[i]; + const y = points[i + 1]; + if (x && y) { + maxX = Math.max(x, maxX); + maxY = Math.max(y, maxY); + minX = Math.min(x, minX); + minY = Math.min(y, minY); + xCount += x; + yCount += y; + pCount++; + } + } + return { + center: [xCount / pCount, yCount / pCount], + radius: Math.sqrt(Math.pow(maxX - minX, 2) + Math.pow(maxY - minY, 2)) / 2, + }; +} diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts index ca457a70c5..74055a7c30 100644 --- a/packages/utils/src/index.ts +++ b/packages/utils/src/index.ts @@ -14,6 +14,8 @@ export * from './event'; export * from './color'; export * from './anchor'; export * from './stencli'; +export * from './worker-helper'; export * from './cull'; export * from './env'; export * from './tileset-manager'; +export * from './workers/triangulation'; diff --git a/packages/utils/src/math.ts b/packages/utils/src/math.ts new file mode 100644 index 0000000000..f98e5617c8 --- /dev/null +++ b/packages/utils/src/math.ts @@ -0,0 +1,3 @@ +export function isNumber(n: any) { + return typeof n === 'number'; +} diff --git a/packages/utils/src/worker-helper/index.ts b/packages/utils/src/worker-helper/index.ts new file mode 100644 index 0000000000..5733fe9f6f --- /dev/null +++ b/packages/utils/src/worker-helper/index.ts @@ -0,0 +1,44 @@ +import { WorkerFarm } from 'web-worker-helper'; +// @ts-ignore +import WorkerInlineSource from '../../dist/l7-utils.worker.js'; +import { WorkerSourceMap } from '../workers'; +import { getWorkerSource, registerWorkerSource } from './worker-map'; + +export { WorkerSourceMap }; + +const L7_WORKER_NAME = 'l7-worker'; +const WORKER_MAX_CONCURRENCY = 3; +const WORKER_REUSE = true; + +export function setL7WorkerSource(workerSource: string) { + registerWorkerSource(L7_WORKER_NAME, workerSource); +} + +function getL7WorkerSource(): string { + const workerSource = getWorkerSource(L7_WORKER_NAME); + + if (!workerSource) { + throw new Error(`get worker failed by workerName: ${L7_WORKER_NAME}.`); + } + + return workerSource; +} + +export async function executeWorkerTask(workerType: string, data: any) { + const source = getL7WorkerSource(); + const workerFarm = WorkerFarm.getWorkerFarm({ + maxConcurrency: WORKER_MAX_CONCURRENCY, + reuseWorkers: WORKER_REUSE, + }); + const workerPool = workerFarm.getWorkerPool({ name: L7_WORKER_NAME, source }); + const job = await workerPool.startJob(L7_WORKER_NAME, (myJob, type, myData) => + myJob.done(myData), + ); + + job.postMessage('process', { input: { workerType, data } }); + + const result = await job.result; + return result.result; +} + +setL7WorkerSource(WorkerInlineSource); diff --git a/packages/utils/src/worker-helper/worker-map.ts b/packages/utils/src/worker-helper/worker-map.ts new file mode 100644 index 0000000000..63ecf27ba8 --- /dev/null +++ b/packages/utils/src/worker-helper/worker-map.ts @@ -0,0 +1,10 @@ +const WorkerSourceMap = new Map(); + +export function registerWorkerSource(workerName: string, workerSource: string) { + WorkerSourceMap.set(workerName, workerSource); +} + +export function getWorkerSource(workerName: string) { + const workerSource = WorkerSourceMap.get(workerName); + return workerSource; +} diff --git a/packages/utils/src/workers/commonFeatureFunc.ts b/packages/utils/src/workers/commonFeatureFunc.ts new file mode 100644 index 0000000000..696f254024 --- /dev/null +++ b/packages/utils/src/workers/commonFeatureFunc.ts @@ -0,0 +1,30 @@ +import { IEncodeFeature, IVertexAttributeDescriptor } from '@antv/l7-core'; + +export function a_Color(feature: IEncodeFeature, featureIdx: number) { + const { color } = feature; + return !color || !color.length ? [1, 1, 1, 1] : color; +} + +export function a_Position( + feature: IEncodeFeature, + featureIdx: number, + vertex: number[], +) { + return vertex.length === 2 + ? [vertex[0], vertex[1], 0] + : [vertex[0], vertex[1], vertex[2]]; +} + +export function a_filter(feature: IEncodeFeature, featureIdx: number) { + const { filter } = feature; + return filter ? [1] : [0]; +} + +export function a_vertexId( + feature: IEncodeFeature, + featureIdx: number, + vertex: number[], + attributeIdx: number, +) { + return [featureIdx]; +} diff --git a/packages/utils/src/workers/extrude_polyline.ts b/packages/utils/src/workers/extrude_polyline.ts new file mode 100644 index 0000000000..60cc74642f --- /dev/null +++ b/packages/utils/src/workers/extrude_polyline.ts @@ -0,0 +1,866 @@ +import { vec2, vec3 } from 'gl-matrix'; +import { aProjectFlat } from '../geo'; +const tmp = vec2.create(); +const capEnd = vec2.create(); +const lineA = vec2.create(); +const lineB = vec2.create(); +const tangent = vec2.create(); + +export function computeMiter( + lineTangent: vec2, + miter: vec2, + start: vec2, + end: vec2, + halfThick: number, +): [number, vec2] { + vec2.add(lineTangent, start, end); + vec2.normalize(lineTangent, lineTangent); + miter = vec2.fromValues(-lineTangent[1], lineTangent[0]); + const tmpvec = vec2.fromValues(-start[1], start[0]); + return [halfThick / vec2.dot(miter, tmpvec), miter]; +} +export function computeNormal(out: vec2, dir: vec2) { + return vec2.set(out, -dir[1], dir[0]); +} + +export function direction(out: vec2, a: vec2, b: vec2) { + vec2.sub(out, a, b); + vec2.normalize(out, out); + return out; +} + +function isPointEqual(a: vec2, b: vec2) { + return a[0] === b[0] && a[1] === b[1]; +} + +function getArrayUnique(matrix: number[][]) { + const map = new Map(); + for (let i = 0; i < matrix.length; i++) { + const key = matrix[0].toString() + '-' + matrix[1].toString(); + if (map.get(key)) { + matrix.splice(i, 1); + i++; + } else { + map.set(key, key); + } + } + return matrix; +} + +export interface IExtrudeLineOption { + join: string; + cap: string; + dash: boolean; + closed: boolean; + indexOffset: number; + miterLimit: number; + thickness: number; +} +export default class ExtrudePolyline { + public complex: { + positions: number[]; + indices: number[]; + normals: number[]; + startIndex: number; + indexes: number[]; + }; + private join: string; + private cap: string; + private miterLimit: number; + private thickness: number; + private normal: vec2 | null; + private lastFlip: number = -1; + private miter: vec2 = vec2.fromValues(0, 0); + private started: boolean = false; + private dash: boolean = false; + private totalDistance: number = 0; + private currentIndex: number = 0; + + constructor(opts: Partial = {}) { + this.join = opts.join || 'miter'; + this.cap = opts.cap || 'butt'; + this.miterLimit = opts.miterLimit || 10; + this.thickness = opts.thickness || 1; + this.dash = opts.dash || false; + this.complex = { + positions: [], + indices: [], + normals: [], + startIndex: 0, + indexes: [], + }; + } + + public extrude_gaode2(points: number[][], originPoints: number[][]) { + const complex = this.complex; + if (points.length <= 1) { + return complex; + } + this.lastFlip = -1; + this.started = false; + this.normal = null; + this.totalDistance = 0; + // 去除数组里重复的点 + // points = getArrayUnique(points); + const total = points.length; + let count = complex.startIndex; + for (let i = 1; i < total; i++) { + const last = points[i - 1]; + last.push(originPoints[i - 1][2] ?? 0); + // @ts-ignore + const originLast = originPoints[i - 1] as vec3; + + const cur = points[i]; + cur.push(originPoints[i][2] ?? 0); + // @ts-ignore + const originCur = originPoints[i] as vec3; + + const next = + i < points.length - 1 + ? [...points[i + 1], originPoints[i + 1][2] ?? 0] + : null; + const originNext = + i < originPoints.length - 1 ? originPoints[i + 1] : null; + + const amt = this.segment_gaode2( + complex, + count, + // @ts-ignore + last as vec3, + // @ts-ignore + cur as vec3, + // @ts-ignore + next as vec3, + // @ts-ignore + originLast, + originCur, + // @ts-ignore + originNext as vec3, + ); + count += amt; + } + if (this.dash) { + for (let i = 0; i < complex.positions.length / 6; i++) { + complex.positions[i * 6 + 5] = this.totalDistance; + } + } + complex.startIndex = complex.positions.length / 6; + return complex; + } + public simpleExtrude_gaode2(points: number[][], originPoints: number[][]) { + const complex = this.complex; + if (points.length <= 1) { + return complex; + } + this.lastFlip = -1; + this.started = false; + this.normal = null; + this.totalDistance = 0; + // 去除数组里重复的点 + // points = getArrayUnique(points); + const total = points.length; + let count = complex.startIndex; + for (let i = 1; i < total; i++) { + const last = points[i - 1]; + last.push(originPoints[i - 1][2] ?? 0); + // @ts-ignore + const originLast = originPoints[i - 1] as vec3; + + const cur = points[i]; + cur.push(originPoints[i][2] ?? 0); + // @ts-ignore + const originCur = originPoints[i] as vec3; + + const next = + i < points.length - 1 + ? [...points[i + 1], originPoints[i + 1][2] ?? 0] + : null; + const originNext = + i < originPoints.length - 1 ? originPoints[i + 1] : null; + + const amt = this.simpleSegment( + complex, + count, + // @ts-ignore + last as vec3, + // @ts-ignore + cur as vec3, + // @ts-ignore + next as vec3, + // @ts-ignore + originLast, + originCur, + // @ts-ignore + originNext as vec3, + ); + count += amt; + } + if (this.dash) { + for (let i = 0; i < complex.positions.length / 6; i++) { + complex.positions[i * 6 + 5] = this.totalDistance; + } + } + complex.startIndex = complex.positions.length / 6; + return complex; + } + public extrude(points: number[][]) { + const complex = this.complex; + if (points.length <= 1) { + return complex; + } + this.lastFlip = -1; + this.started = false; + this.normal = null; + this.totalDistance = 0; + // 去除数组里重复的点 + // points = getArrayUnique(points); + const total = points.length; + let count = complex.startIndex; + for (let i = 1; i < total; i++) { + const last = points[i - 1] as vec3; + const cur = points[i] as vec3; + const next = i < points.length - 1 ? points[i + 1] : null; + const amt = this.segment(complex, count, last, cur, next as vec3); + count += amt; + } + if (this.dash) { + for (let i = 0; i < complex.positions.length / 6; i++) { + complex.positions[i * 6 + 5] = this.totalDistance; + } + } + complex.startIndex = complex.positions.length / 6; + return complex; + } + public simpleExtrude(points: number[][]) { + const complex = this.complex; + if (points.length <= 1) { + return complex; + } + this.lastFlip = -1; + this.started = false; + this.normal = null; + this.totalDistance = 0; + + const total = points.length; + let count = complex.startIndex; + for (let i = 1; i < total; i++) { + const last = points[i - 1] as vec3; + const cur = points[i] as vec3; + const next = i < points.length - 1 ? points[i + 1] : null; + const amt = this.simpleSegment(complex, count, last, cur, next as vec3); + count += amt; + } + + if (this.dash) { + for (let i = 0; i < complex.positions.length / 6; i++) { + complex.positions[i * 6 + 5] = this.totalDistance; + } + } + complex.startIndex = complex.positions.length / 6; + return complex; + } + private segment_gaode2( + complex: any, + index: number, + last: vec3, + cur: vec3, + next: vec3, + originLast: vec3, + originCur: vec3, + originNext: vec3, + ) { + let count = 0; + const indices = complex.indices; + const positions = complex.positions; + const normals = complex.normals; + const capSquare = this.cap === 'square'; + const joinBevel = this.join === 'bevel'; + const flatCur = aProjectFlat([originCur[0], originCur[1]]) as [ + number, + number, + ]; + const flatLast = aProjectFlat([originLast[0], originLast[1]]) as [ + number, + number, + ]; + // @ts-ignore + direction(lineA, cur as vec3, last as vec3); + let segmentDistance = 0; + if (this.dash) { + // @ts-ignore + segmentDistance = this.lineSegmentDistance(flatCur, flatLast); + this.totalDistance += segmentDistance; + } + + if (!this.normal) { + this.normal = vec2.create(); + computeNormal(this.normal, lineA); + } + if (!this.started) { + this.started = true; + + // if the end cap is type square, we can just push the verts out a bit + if (capSquare) { + // vec2.scaleAndAdd(capEnd, last, lineA, -this.thickness); + const out1 = vec2.create(); + const out2 = vec2.create(); + vec2.add(out1, this.normal, lineA); + vec2.add(out2, this.normal, lineA); + normals.push(out2[0], out2[1], 0); + normals.push(out1[0], out1[1], 0); + positions.push( + last[0], + last[1], + last[2] | 0, + this.totalDistance - segmentDistance, + -this.thickness, + last[2] | 0, + ); + this.complex.indexes.push(this.currentIndex); + positions.push( + last[0], + last[1], + last[2] | 0, + this.totalDistance - segmentDistance, + this.thickness, + last[2] | 0, + ); + this.complex.indexes.push(this.currentIndex); + this.currentIndex++; + } else { + this.extrusions( + positions, + normals, + last, + this.normal, + this.thickness, + this.totalDistance - segmentDistance, + ); + } + } + + indices.push(index + 0, index + 1, index + 2); + + if (!next) { + computeNormal(this.normal, lineA); + if (capSquare) { + const out1 = vec2.create(); + const out2 = vec2.create(); + vec2.sub(out2, lineA, this.normal); + vec2.add(out1, lineA, this.normal); + + normals.push(out2[0], out2[1], 0); + normals.push(out1[0], out1[1], 0); + + positions.push( + cur[0], + cur[1], + cur[2] | 0, + this.totalDistance, + this.thickness, + cur[2] | 0, + ); + this.complex.indexes.push(this.currentIndex); + positions.push( + cur[0], + cur[1], + cur[2] | 0, + this.totalDistance, + this.thickness, + cur[2] | 0, + ); + this.complex.indexes.push(this.currentIndex); + this.currentIndex++; + } else { + this.extrusions( + positions, + normals, + cur, + this.normal, + this.thickness, + this.totalDistance, + ); + } + indices.push( + ...(this.lastFlip === 1 + ? [index, index + 2, index + 3] + : [index + 2, index + 1, index + 3]), + ); + count += 2; + } else { + // @ts-ignore + if (isPointEqual(cur as vec2, next as vec2)) { + vec2.add( + // @ts-ignore + next as vec2, + // @ts-ignore + cur as vec2, + vec2.normalize( + // @ts-ignore + next as vec2, + // @ts-ignore + vec2.subtract(next as vec2, cur as vec2, last as vec2), + ), + ); + } + // @ts-ignore + direction(lineB, next as vec2, cur as vec2); + // stores tangent & miter + + const [miterLen, miter] = computeMiter( + tangent, + vec2.create(), + lineA, + lineB, + this.thickness, + ); + // normal(tmp, lineA) + + // get orientation + let flip = vec2.dot(tangent, this.normal) < 0 ? -1 : 1; + let bevel = joinBevel; + if (!bevel && this.join === 'miter') { + const limit = miterLen; + if (limit > this.miterLimit) { + bevel = true; + } + } + + if (bevel) { + normals.push(this.normal[0], this.normal[1], 0); + normals.push(miter[0], miter[1], 0); + + positions.push( + cur[0], + cur[1], + cur[2] | 0, + this.totalDistance, + -this.thickness * flip, + cur[2] | 0, + ); + this.complex.indexes.push(this.currentIndex); + positions.push( + cur[0], + cur[1], + cur[2] | 0, + this.totalDistance, + this.thickness * flip, + cur[2] | 0, + ); + this.complex.indexes.push(this.currentIndex); + this.currentIndex++; + indices.push( + ...(this.lastFlip !== -flip + ? [index, index + 2, index + 3] + : [index + 2, index + 1, index + 3]), + ); + + // now add the bevel triangle + indices.push(index + 2, index + 3, index + 4); + + computeNormal(tmp, lineB); + vec2.copy(this.normal, tmp); // store normal for next round + normals.push(this.normal[0], this.normal[1], 0); + positions.push( + cur[0], + cur[1], + cur[2] | 0, + this.totalDistance, + -this.thickness * flip, + cur[2] | 0, + ); + this.complex.indexes.push(this.currentIndex); + this.currentIndex++; + count += 3; + } else { + this.extrusions( + positions, + normals, + cur, + miter, + miterLen, + this.totalDistance, + ); + indices.push( + ...(this.lastFlip === 1 + ? [index, index + 2, index + 3] + : [index + 2, index + 1, index + 3]), + ); + + flip = -1; + + // the miter is now the normal for our next join + vec2.copy(this.normal, miter); + count += 2; + } + this.lastFlip = flip; + } + return count; + } + private simpleSegment( + complex: any, + index: number, + last: vec3, + cur: vec3, + next: vec3, + ) { + let count = 0; + const indices = complex.indices; + const positions = complex.positions; + const normals = complex.normals; + const flatCur = aProjectFlat([cur[0], cur[1]]) as [number, number]; + const flatLast = aProjectFlat([last[0], last[1]]) as [number, number]; + // @ts-ignore + direction(lineA, flatCur, flatLast); + let segmentDistance = 0; + if (this.dash) { + // @ts-ignore + segmentDistance = this.lineSegmentDistance(flatCur, flatLast); + this.totalDistance += segmentDistance; + } + + if (!this.normal) { + this.normal = vec2.create(); + computeNormal(this.normal, lineA); + } + if (!this.started) { + this.started = true; + + this.extrusions( + positions, + normals, + last, + this.normal, + this.thickness, + this.totalDistance - segmentDistance, + ); + } + + indices.push(index + 0, index + 1, index + 2); + + if (!next) { + computeNormal(this.normal, lineA); + this.extrusions( + positions, + normals, + cur, + this.normal, + this.thickness, + this.totalDistance, + ); + + indices.push( + ...(this.lastFlip === 1 + ? [index, index + 2, index + 3] + : [index + 2, index + 1, index + 3]), + ); + count += 2; + } else { + const flatNext = aProjectFlat([next[0], next[1]]) as [number, number]; + if (isPointEqual(flatCur, flatNext)) { + vec2.add( + flatNext, + flatCur, + vec2.normalize(flatNext, vec2.subtract(flatNext, flatCur, flatLast)), + ); + } + direction(lineB, flatNext, flatCur); + + // stores tangent & miter + + const [miterLen, miter] = computeMiter( + tangent, + vec2.create(), + lineA, + lineB, + this.thickness, + ); + // normal(tmp, lineA) + + // get orientation + let flip = vec2.dot(tangent, this.normal) < 0 ? -1 : 1; + this.extrusions( + positions, + normals, + cur, + miter, + miterLen, + this.totalDistance, + ); + indices.push( + ...(this.lastFlip === 1 + ? [index, index + 2, index + 3] + : [index + 2, index + 1, index + 3]), + ); + + flip = -1; + + // the miter is now the normal for our next join + vec2.copy(this.normal, miter); + count += 2; + this.lastFlip = flip; + } + return count; + } + private segment( + complex: any, + index: number, + last: vec3, + cur: vec3, + next: vec3, + ) { + let count = 0; + const indices = complex.indices; + const positions = complex.positions; + const normals = complex.normals; + const capSquare = this.cap === 'square'; + const joinBevel = this.join === 'bevel'; + const flatCur = aProjectFlat([cur[0], cur[1]]) as [number, number]; + const flatLast = aProjectFlat([last[0], last[1]]) as [number, number]; + // @ts-ignore + direction(lineA, flatCur, flatLast); + let segmentDistance = 0; + if (this.dash) { + // @ts-ignore + segmentDistance = this.lineSegmentDistance(flatCur, flatLast); + this.totalDistance += segmentDistance; + } + + if (!this.normal) { + this.normal = vec2.create(); + computeNormal(this.normal, lineA); + } + if (!this.started) { + this.started = true; + + // if the end cap is type square, we can just push the verts out a bit + if (capSquare) { + // vec2.scaleAndAdd(capEnd, last, lineA, -this.thickness); + const out1 = vec2.create(); + const out2 = vec2.create(); + vec2.add(out1, this.normal, lineA); + vec2.add(out2, this.normal, lineA); + normals.push(out2[0], out2[1], 0); + normals.push(out1[0], out1[1], 0); + positions.push( + last[0], + last[1], + last[2] | 0, + this.totalDistance - segmentDistance, + -this.thickness, + last[2] | 0, + ); + this.complex.indexes.push(this.currentIndex); + positions.push( + last[0], + last[1], + last[2] | 0, + this.totalDistance - segmentDistance, + this.thickness, + last[2] | 0, + ); + this.complex.indexes.push(this.currentIndex); + this.currentIndex++; + // this.extrusions(positions, normals, last, out, this.thickness); + // last = capEnd; + } else { + this.extrusions( + positions, + normals, + last, + this.normal, + this.thickness, + this.totalDistance - segmentDistance, + ); + } + } + + indices.push(index + 0, index + 1, index + 2); + + if (!next) { + computeNormal(this.normal, lineA); + if (capSquare) { + // vec2.scaleAndAdd(capEnd, cur, lineA, this.thickness); + // cur = capEnd; + const out1 = vec2.create(); + const out2 = vec2.create(); + vec2.sub(out2, lineA, this.normal); + vec2.add(out1, lineA, this.normal); + // this.extrusions(positions, normals, cur, out, this.thickness); + normals.push(out2[0], out2[1], 0); + normals.push(out1[0], out1[1], 0); + positions.push( + cur[0], + cur[1], + cur[2] | 0, + this.totalDistance, + this.thickness, + cur[2] | 0, + ); + this.complex.indexes.push(this.currentIndex); + positions.push( + cur[0], + cur[1], + cur[2] | 0, + this.totalDistance, + this.thickness, + cur[2] | 0, + ); + this.complex.indexes.push(this.currentIndex); + this.currentIndex++; + } else { + this.extrusions( + positions, + normals, + cur, + this.normal, + this.thickness, + this.totalDistance, + ); + } + + // this.extrusions(positions, normals, cur, this.normal, this.thickness); + indices.push( + ...(this.lastFlip === 1 + ? [index, index + 2, index + 3] + : [index + 2, index + 1, index + 3]), + ); + count += 2; + } else { + const flatNext = aProjectFlat([next[0], next[1]]) as [number, number]; + if (isPointEqual(flatCur, flatNext)) { + vec2.add( + flatNext, + flatCur, + vec2.normalize(flatNext, vec2.subtract(flatNext, flatCur, flatLast)), + ); + } + direction(lineB, flatNext, flatCur); + + // stores tangent & miter + + const [miterLen, miter] = computeMiter( + tangent, + vec2.create(), + lineA, + lineB, + this.thickness, + ); + // normal(tmp, lineA) + + // get orientation + let flip = vec2.dot(tangent, this.normal) < 0 ? -1 : 1; + let bevel = joinBevel; + if (!bevel && this.join === 'miter') { + const limit = miterLen; + if (limit > this.miterLimit) { + bevel = true; + } + } + + if (bevel) { + normals.push(this.normal[0], this.normal[1], 0); + normals.push(miter[0], miter[1], 0); + positions.push( + cur[0], + cur[1], + cur[2] | 0, + this.totalDistance, + -this.thickness * flip, + cur[2] | 0, + ); + this.complex.indexes.push(this.currentIndex); + positions.push( + cur[0], + cur[1], + cur[2] | 0, + this.totalDistance, + this.thickness * flip, + cur[2] | 0, + ); + this.complex.indexes.push(this.currentIndex); + this.currentIndex++; + indices.push( + ...(this.lastFlip !== -flip + ? [index, index + 2, index + 3] + : [index + 2, index + 1, index + 3]), + ); + + // now add the bevel triangle + indices.push(index + 2, index + 3, index + 4); + + computeNormal(tmp, lineB); + vec2.copy(this.normal, tmp); // store normal for next round + normals.push(this.normal[0], this.normal[1], 0); + positions.push( + cur[0], + cur[1], + cur[2] | 0, + this.totalDistance, + -this.thickness * flip, + cur[2] | 0, + ); + this.complex.indexes.push(this.currentIndex); + this.currentIndex++; + count += 3; + } else { + this.extrusions( + positions, + normals, + cur, + miter, + miterLen, + this.totalDistance, + ); + indices.push( + ...(this.lastFlip === 1 + ? [index, index + 2, index + 3] + : [index + 2, index + 1, index + 3]), + ); + + flip = -1; + + // the miter is now the normal for our next join + vec2.copy(this.normal, miter); + count += 2; + } + this.lastFlip = flip; + } + return count; + } + private extrusions( + positions: number[], + normals: number[], + point: vec3, // 顶点 + normal: vec2, // 法向量 + thickness: number, // 高度 + distanceRadio: number, + ) { + normals.push(normal[0], normal[1], 0); + normals.push(normal[0], normal[1], 0); + positions.push( + point[0], + point[1], + point[2] | 0, + distanceRadio, + -thickness, + point[2] | 0, + ); + this.complex.indexes.push(this.currentIndex); + positions.push( + point[0], + point[1], + point[2] | 0, + distanceRadio, + thickness, + point[2] | 0, + ); + this.complex.indexes.push(this.currentIndex); + this.currentIndex++; + } + private lineSegmentDistance(b1: vec3, a1: vec3) { + const dx = a1[0] - b1[0]; + const dy = a1[1] - b1[1]; + return Math.sqrt(dx * dx + dy * dy); + } +} diff --git a/packages/utils/src/workers/index.ts b/packages/utils/src/workers/index.ts new file mode 100644 index 0000000000..c98775f6fa --- /dev/null +++ b/packages/utils/src/workers/index.ts @@ -0,0 +1,30 @@ +import { createWorker } from 'web-worker-helper'; +import { lineModel } from './lineModel'; +import { pointFillModel } from './pointFillModel'; +import { polygonFillModel } from './polygonFillModel'; + +// current support worker +export const WorkerSourceMap = { + pointFill: pointFillModel, + line: lineModel, + polygonFill: polygonFillModel, +}; + +const workerTypes: Record Promise> = { + ...WorkerSourceMap, +}; + +async function worker({ workerType, data }: { workerType: string; data: any }) { + if (workerTypes[workerType]) { + return workerTypes[workerType](data); + } + + return Promise.reject( + new Error(`Worker with type "${workerType}" non-existent.`), + ); +} + +createWorker(worker); + +// export default createWorker(worker); +export { createWorker, worker }; diff --git a/packages/utils/src/workers/lineModel.ts b/packages/utils/src/workers/lineModel.ts new file mode 100644 index 0000000000..70f528034d --- /dev/null +++ b/packages/utils/src/workers/lineModel.ts @@ -0,0 +1,175 @@ +import { IEncodeFeature, IVertexAttributeDescriptor } from '@antv/l7-core'; +import { encodePickingColor } from '../color'; +import { a_Color, a_filter, a_Position, a_vertexId } from './commonFeatureFunc'; +import { LineTriangulation as triangulation } from './triangulation'; + +export const lineModel = async ({ + descriptors, + features, + enablePicking, + iconMap, +}: { + descriptors: IVertexAttributeDescriptor[]; + features: IEncodeFeature[]; + enablePicking: boolean; + iconMap: any; +}) => { + const updateFuncs = { + // fixed feature func + a_Color, + a_Position, + filter: a_filter, + a_vertexId, + a_PickingColor: (feature: IEncodeFeature, featureIdx: number) => { + const { id } = feature; + return enablePicking ? encodePickingColor(id as number) : [0, 0, 0]; + }, + + // pointFill feature func + a_DistanceAndIndex: ( + feature: IEncodeFeature, + featureIdx: number, + vertex: number[], + attributeIdx: number, + normal: number[], + vertexIndex?: number, + ) => { + return vertexIndex === undefined + ? [vertex[3], 10] + : [vertex[3], vertexIndex]; + }, + a_Total_Distance: ( + feature: IEncodeFeature, + featureIdx: number, + vertex: number[], + attributeIdx: number, + ) => { + return [vertex[5]]; + }, + a_Size: ( + feature: IEncodeFeature, + featureIdx: number, + vertex: number[], + attributeIdx: number, + ) => { + const { size: pointSize = 1 } = feature; + return Array.isArray(pointSize) + ? [pointSize[0], pointSize[1]] + : [pointSize as number, 0]; + }, + a_Normal: ( + feature: IEncodeFeature, + featureIdx: number, + vertex: number[], + attributeIdx: number, + normal: number[], + ) => { + return normal; + }, + a_Miter: ( + feature: IEncodeFeature, + featureIdx: number, + vertex: number[], + attributeIdx: number, + ) => { + return [vertex[4]]; + }, + a_iconMapUV: ( + feature: IEncodeFeature, + featureIdx: number, + vertex: number[], + attributeIdx: number, + ) => { + const { texture } = feature; + const { x, y } = iconMap[texture as string] || { x: 0, y: 0 }; + return [x, y]; + }, + }; + + const featureLayout: { + sizePerElement: number; + elements: Array<{ + featureIdx: number; + vertices: number[]; + normals: number[]; + offset: number; + indexes?: number[]; + }>; + } = { + sizePerElement: 0, + elements: [], + }; + + let verticesNum = 0; + const indices: number[] = []; + let size = 3; + features.forEach((feature: IEncodeFeature, featureIdx: number) => { + const { + indices: indicesForCurrentFeature, + vertices: verticesForCurrentFeature, + // @ts-ignore + normals: normalsForCurrentFeature, + size: vertexSize, + // @ts-ignore + indexes, + } = triangulation(feature); + indicesForCurrentFeature.forEach((i) => { + indices.push(i + verticesNum); + }); + size = vertexSize; + const verticesNumForCurrentFeature = + verticesForCurrentFeature.length / vertexSize; + + featureLayout.sizePerElement = size; + + featureLayout.elements.push({ + featureIdx, + vertices: verticesForCurrentFeature, + normals: normalsForCurrentFeature, + offset: verticesNum, + }); + + verticesNum += verticesNumForCurrentFeature; + for ( + let vertexIdx = 0; + vertexIdx < verticesNumForCurrentFeature; + vertexIdx++ + ) { + const normal = + normalsForCurrentFeature?.slice(vertexIdx * 3, vertexIdx * 3 + 3) || []; + const vertice = verticesForCurrentFeature.slice( + vertexIdx * vertexSize, + vertexIdx * vertexSize + vertexSize, + ); + + let vertexIndex = 0; + if (indexes && indexes[vertexIdx] !== undefined) { + vertexIndex = indexes[vertexIdx]; + } + + descriptors.forEach((descriptor, attributeIdx: number) => { + // @ts-ignore + if (descriptor && updateFuncs[descriptor.name]) { + // @ts-ignore + descriptor.buffer.data.push( + // @ts-ignore + ...updateFuncs[descriptor.name]( + feature, + featureIdx, + vertice, + vertexIdx, + normal, + vertexIndex, + ), + ); + } + }); + } + }); + + return { + descriptors, + featureLayout, + indices, + }; +}; diff --git a/packages/utils/src/workers/pointFillModel.ts b/packages/utils/src/workers/pointFillModel.ts new file mode 100644 index 0000000000..5d3ca5164c --- /dev/null +++ b/packages/utils/src/workers/pointFillModel.ts @@ -0,0 +1,149 @@ +import { IEncodeFeature, IVertexAttributeDescriptor } from '@antv/l7-core'; +import { encodePickingColor } from '../color'; +import { a_Color, a_filter, a_Position, a_vertexId } from './commonFeatureFunc'; +import { PointFillTriangulation as triangulation } from './triangulation'; + +export const pointFillModel = async ({ + descriptors, + features, + enablePicking, + shape2d, +}: { + descriptors: IVertexAttributeDescriptor[]; + features: IEncodeFeature[]; + enablePicking: boolean; + shape2d: string[]; +}) => { + const updateFuncs = { + // fixed feature func + a_Color, + a_Position, + filter: a_filter, + a_vertexId, + a_PickingColor: (feature: IEncodeFeature, featureIdx: number) => { + const { id } = feature; + return enablePicking ? encodePickingColor(id as number) : [0, 0, 0]; + }, + + // pointFill feature func + a_Shape: ( + feature: IEncodeFeature, + featureIdx: number, + vertex: number[], + attributeIdx: number, + ) => { + const { shape = 2 } = feature; + const shapeIndex = shape2d.indexOf(shape as string); + return [shapeIndex]; + }, + a_Extrude: ( + feature: IEncodeFeature, + featureIdx: number, + vertex: number[], + attributeIdx: number, + ) => { + const extrude = [1, 1, 0, -1, 1, 0, -1, -1, 0, 1, -1, 0]; + const extrudeIndex = (attributeIdx % 4) * 3; + return [ + extrude[extrudeIndex], + extrude[extrudeIndex + 1], + extrude[extrudeIndex + 2], + ]; + }, + a_Size: ( + feature: IEncodeFeature, + featureIdx: number, + vertex: number, + attributeIdx: number[], + ) => { + const { size: pointSize = 5 } = feature; + return Array.isArray(pointSize) ? [pointSize[0]] : [pointSize]; + }, + }; + + const featureLayout: { + sizePerElement: number; + elements: Array<{ + featureIdx: number; + vertices: number[]; + normals: number[]; + offset: number; + indexes?: number[]; + }>; + } = { + sizePerElement: 0, + elements: [], + }; + + let verticesNum = 0; + const indices: number[] = []; + let size = 3; + features.forEach((feature: IEncodeFeature, featureIdx: number) => { + const { + indices: indicesForCurrentFeature, + vertices: verticesForCurrentFeature, + // @ts-ignore + normals: normalsForCurrentFeature, + size: vertexSize, + // @ts-ignore + indexes, + } = triangulation(feature); + indicesForCurrentFeature.forEach((i) => { + indices.push(i + verticesNum); + }); + size = vertexSize; + const verticesNumForCurrentFeature = + verticesForCurrentFeature.length / vertexSize; + + featureLayout.sizePerElement = size; + + featureLayout.elements.push({ + featureIdx, + vertices: verticesForCurrentFeature, + normals: normalsForCurrentFeature, + offset: verticesNum, + }); + + verticesNum += verticesNumForCurrentFeature; + for ( + let vertexIdx = 0; + vertexIdx < verticesNumForCurrentFeature; + vertexIdx++ + ) { + const normal = + normalsForCurrentFeature?.slice(vertexIdx * 3, vertexIdx * 3 + 3) || []; + const vertice = verticesForCurrentFeature.slice( + vertexIdx * vertexSize, + vertexIdx * vertexSize + vertexSize, + ); + + let vertexIndex = 0; + if (indexes && indexes[vertexIdx] !== undefined) { + vertexIndex = indexes[vertexIdx]; + } + + descriptors.forEach((descriptor, attributeIdx: number) => { + // @ts-ignore + if (descriptor && updateFuncs[descriptor.name]) { + // @ts-ignore + descriptor.buffer.data.push( + // @ts-ignore + ...updateFuncs[descriptor.name]( + feature, + featureIdx, + vertice, + vertexIdx, + normal, + vertexIndex, + ), + ); + } + }); + } + }); + return { + descriptors, + featureLayout, + indices, + }; +}; diff --git a/packages/utils/src/workers/polygonFillModel.ts b/packages/utils/src/workers/polygonFillModel.ts new file mode 100644 index 0000000000..8d372b3439 --- /dev/null +++ b/packages/utils/src/workers/polygonFillModel.ts @@ -0,0 +1,115 @@ +import { IEncodeFeature, IVertexAttributeDescriptor } from '@antv/l7-core'; +import { encodePickingColor } from '../color'; +import { a_Color, a_filter, a_Position, a_vertexId } from './commonFeatureFunc'; +import { polygonFillTriangulation as triangulation } from './triangulation'; + +export const polygonFillModel = async ({ + descriptors, + features, + enablePicking, +}: { + descriptors: IVertexAttributeDescriptor[]; + features: IEncodeFeature[]; + enablePicking: boolean; +}) => { + const updateFuncs = { + // fixed feature func + a_Color, + a_Position, + filter: a_filter, + a_vertexId, + a_PickingColor: (feature: IEncodeFeature, featureIdx: number) => { + const { id } = feature; + return enablePicking ? encodePickingColor(id as number) : [0, 0, 0]; + }, + + // polygonFill feature func + // empty + }; + + const featureLayout: { + sizePerElement: number; + elements: Array<{ + featureIdx: number; + vertices: number[]; + normals: number[]; + offset: number; + indexes?: number[]; + }>; + } = { + sizePerElement: 0, + elements: [], + }; + + let verticesNum = 0; + const indices: number[] = []; + let size = 3; + features.forEach((feature: IEncodeFeature, featureIdx: number) => { + const { + indices: indicesForCurrentFeature, + vertices: verticesForCurrentFeature, + // @ts-ignore + normals: normalsForCurrentFeature, + size: vertexSize, + // @ts-ignore + indexes, + } = triangulation(feature); + indicesForCurrentFeature.forEach((i) => { + indices.push(i + verticesNum); + }); + size = vertexSize; + const verticesNumForCurrentFeature = + verticesForCurrentFeature.length / vertexSize; + + featureLayout.sizePerElement = size; + + featureLayout.elements.push({ + featureIdx, + vertices: verticesForCurrentFeature, + normals: normalsForCurrentFeature, + offset: verticesNum, + }); + + verticesNum += verticesNumForCurrentFeature; + for ( + let vertexIdx = 0; + vertexIdx < verticesNumForCurrentFeature; + vertexIdx++ + ) { + const normal = + normalsForCurrentFeature?.slice(vertexIdx * 3, vertexIdx * 3 + 3) || []; + const vertice = verticesForCurrentFeature.slice( + vertexIdx * vertexSize, + vertexIdx * vertexSize + vertexSize, + ); + + let vertexIndex = 0; + if (indexes && indexes[vertexIdx] !== undefined) { + vertexIndex = indexes[vertexIdx]; + } + + descriptors.forEach((descriptor, attributeIdx: number) => { + // @ts-ignore + if (descriptor && updateFuncs[descriptor.name]) { + // @ts-ignore + descriptor.buffer.data.push( + // @ts-ignore + ...updateFuncs[descriptor.name]( + feature, + featureIdx, + vertice, + vertexIdx, + normal, + vertexIndex, + ), + ); + } + }); + } + }); + return { + descriptors, + featureLayout, + indices, + }; +}; diff --git a/packages/utils/src/workers/triangulation.ts b/packages/utils/src/workers/triangulation.ts new file mode 100644 index 0000000000..7e4b8651d8 --- /dev/null +++ b/packages/utils/src/workers/triangulation.ts @@ -0,0 +1,74 @@ +import { IEncodeFeature, IVertexAttributeDescriptor } from '@antv/l7-core'; +import earcut from 'earcut'; +import { calculateCentroid } from '../geo'; +import ExtrudePolyline from './extrude_polyline'; + +export function LineTriangulation(feature: IEncodeFeature) { + const { coordinates, originCoordinates, version } = feature; + // let path = coordinates as number[][][] | number[][]; + // if (!Array.isArray(path[0][0])) { + // path = [coordinates] as number[][][]; + // } + + const line = new ExtrudePolyline({ + dash: true, + join: 'bevel', + }); + + if (version === 'GAODE2.x') { + // 处理高德2.0几何体构建 + let path1 = coordinates as number[][][] | number[][]; // 计算位置 + if (!Array.isArray(path1[0][0])) { + path1 = [coordinates] as number[][][]; + } + let path2 = originCoordinates as number[][][] | number[][]; // 计算法线 + if (!Array.isArray(path2[0][0])) { + path2 = [originCoordinates] as number[][][]; + } + + for (let i = 0; i < path1.length; i++) { + // 高德2.0在计算线时,需要使用经纬度计算发现,使用 customCoords.lnglatToCoords 计算的数据来计算顶点的位置 + const item1 = path1[i]; + const item2 = path2[i]; + line.extrude_gaode2(item1 as number[][], item2 as number[][]); + } + } else { + // 处理非高德2.0的几何体构建 + let path = coordinates as number[][][] | number[][]; + if (path[0] && !Array.isArray(path[0][0])) { + path = [coordinates] as number[][][]; + } + path.forEach((item: any) => { + line.extrude(item as number[][]); + }); + } + + const linebuffer = line.complex; + return { + vertices: linebuffer.positions, // [ x,y,z, distance, miter,total ] + indices: linebuffer.indices, + normals: linebuffer.normals, + indexes: linebuffer.indexes, + size: 6, + }; +} + +export function PointFillTriangulation(feature: IEncodeFeature) { + const coordinates = calculateCentroid(feature.coordinates); + return { + vertices: [...coordinates, ...coordinates, ...coordinates, ...coordinates], + indices: [0, 1, 2, 2, 3, 0], + size: coordinates.length, + }; +} + +export function polygonFillTriangulation(feature: IEncodeFeature) { + const { coordinates } = feature; + const flattengeo = earcut.flatten(coordinates as number[][][]); + const { vertices, dimensions, holes } = flattengeo; + return { + indices: earcut(vertices, holes, dimensions), + vertices, + size: dimensions, + }; +} diff --git a/stories/Map/components/amap2demo_image.tsx b/stories/Map/components/amap2demo_image.tsx index 4c2bf65d26..787d79dd74 100644 --- a/stories/Map/components/amap2demo_image.tsx +++ b/stories/Map/components/amap2demo_image.tsx @@ -50,11 +50,11 @@ export default class Amap2demo_image extends React.Component { }) .shape('name', ['00', '01', '02']) // .rotate('name', () => Math.random() * Math.PI) - // .rotate(Math.PI/2) - // .style({ - // // layerType: 'fillImage', - // rotation: 0, - // }) + .rotate(Math.PI / 2) + .style({ + layerType: 'fillImage', + // rotation: 90, + }) // .active({ // color: '#00f', // mix: 0.6, diff --git a/stories/Map/components/amap2demo_styleMap.tsx b/stories/Map/components/amap2demo_styleMap.tsx index 1eb7315c85..70822d4184 100644 --- a/stories/Map/components/amap2demo_styleMap.tsx +++ b/stories/Map/components/amap2demo_styleMap.tsx @@ -26,7 +26,7 @@ export default class Amap2demo_styleMap extends React.Component { ) .then((res) => res.json()) .then((data) => { - let layer = new PointLayer({}) // blend: "additive" + let layer = new PointLayer({ workerEnabled: true }) // blend: "additive" .source(data, { parser: { type: 'json', @@ -36,7 +36,6 @@ export default class Amap2demo_styleMap extends React.Component { }) .shape('circle') .color('color') - // .color('#f00') .size('value', (v) => 5 + 15 * v) .style({ // blur: 2.5, diff --git a/stories/Map/components/amap2demo_text.tsx b/stories/Map/components/amap2demo_text.tsx index f354c2bea7..40dce643dd 100644 --- a/stories/Map/components/amap2demo_text.tsx +++ b/stories/Map/components/amap2demo_text.tsx @@ -105,7 +105,7 @@ export default class Amap2demo_text extends React.Component { .color('w', ['#0e0030', '#0e0030', '#0e0030']) .style({ textAnchor: 'center', // 文本相对锚点的位置 center|left|right|top|bottom|top-left - textOffset: [0, 0], // 文本相对锚点的偏移量 [水平, 垂直] + textOffset: [10, 0], // 文本相对锚点的偏移量 [水平, 垂直] spacing: 2, // 字符间距 padding: [1, 1], // 文本包围盒 padding [水平,垂直],影响碰撞检测结果,避免相邻文本靠的太近 stroke: '#ffffff', // 描边颜色 diff --git a/stories/Map/components/bugfix.tsx b/stories/Map/components/bugfix.tsx index bbec3423a6..e3aee87f41 100644 --- a/stories/Map/components/bugfix.tsx +++ b/stories/Map/components/bugfix.tsx @@ -13,6 +13,7 @@ import { HeatmapLayer, LineLayer, Source, + PolygonLayer, } from '@antv/l7'; export default class Amap2demo extends React.Component { @@ -33,29 +34,48 @@ export default class Amap2demo extends React.Component { }, ); - let c = 0, - scene, - layer; - scene = new Scene({ + const scene = new Scene({ id: 'map', - // map: new Mapbox({ - // map: new GaodeMap({ - map: new GaodeMapV2({ - // map: new Map({ - style: 'dark', - center: [120, 30], - zoom: 4, + map: new Mapbox({ + pitch: 0, + style: 'light', + center: [-96, 37.8], + zoom: 3, }), }); - const layer = new PointLayer() - .source(source) - .shape('circle') - .size(10) - .color('#f00'); - scene.on('loaded', () => { - scene.addLayer(layer); + fetch( + 'https://gw.alipayobjects.com/os/basement_prod/d36ad90e-3902-4742-b8a2-d93f7e5dafa2.json', + ) + .then((res) => res.json()) + .then((data) => { + // console.log(data) + const color = [ + 'rgb(255,255,217)', + 'rgb(237,248,177)', + 'rgb(199,233,180)', + 'rgb(127,205,187)', + 'rgb(65,182,196)', + 'rgb(29,145,192)', + 'rgb(34,94,168)', + 'rgb(12,44,132)', + ]; + const layer = new PolygonLayer({}) + .source(data) + .scale('density', { + type: 'quantile', + }) + .color('density', color) + .shape('fill') + .active(true) + .style({ + opacity: 1.0, + }); + + scene.addLayer(layer); + console.log(layer); + }); }); } diff --git a/stories/MapPerformance/components/Map.tsx b/stories/MapPerformance/components/Points.tsx similarity index 56% rename from stories/MapPerformance/components/Map.tsx rename to stories/MapPerformance/components/Points.tsx index 74bdf476c5..bba64a861b 100644 --- a/stories/MapPerformance/components/Map.tsx +++ b/stories/MapPerformance/components/Points.tsx @@ -1,6 +1,6 @@ // @ts-nocheck // @ts-ignore -import { Scene } from '@antv/l7'; +import { Scene, Source } from '@antv/l7'; import { PointLayer } from '@antv/l7-layers'; import { GaodeMap } from '@antv/l7-maps'; import * as React from 'react'; @@ -25,13 +25,30 @@ export default class PointTest extends React.Component { // let address = 'https://gw.alipayobjects.com/os/bmw-prod/e76d89f4-aa69-4974-90b7-b236904a43b1.json' // 100 // let address = 'https://gw.alipayobjects.com/os/bmw-prod/edc8219a-b095-4451-98e9-3e387e290087.json' // 10000 // let address = 'https://gw.alipayobjects.com/os/bmw-prod/2c37f08b-3fe6-4c68-a699-dc15cfc217f1.json' // 50000 - // let address = 'https://gw.alipayobjects.com/os/bmw-prod/8adff753-64e6-4ffa-9e7b-1f3dc6f4fd76.json'; // 100000 let address = - 'https://gw.alipayobjects.com/os/bmw-prod/577a70fb-fc19-4582-83ed-7cddb7b77645.json'; // 20 0000 + 'https://gw.alipayobjects.com/os/bmw-prod/8adff753-64e6-4ffa-9e7b-1f3dc6f4fd76.json'; // 100000 + // let address = + // 'https://gw.alipayobjects.com/os/bmw-prod/577a70fb-fc19-4582-83ed-7cddb7b77645.json'; // 20 0000 fetch(address) .then((res) => res.json()) .then((data) => { - const layer = new PointLayer() + const source = new Source( + [ + { + lng: 120, + lat: 30, + }, + ], + { + parser: { + type: 'json', + x: 'lng', + y: 'lat', + }, + }, + ); + + const layer = new PointLayer({ workerEnabled: true }) .source(data, { parser: { type: 'json', @@ -39,19 +56,30 @@ export default class PointTest extends React.Component { y: 'lat', }, }) + // .source(source) .size(10) .color('#f00') - // .shape('circle') // circle simple - .shape('simple') - .style({ - opacity: 1.0, - }) - .select(true); - // .animate(true) - // .active(true); + .shape('circle') + .active(true); + scene.on('loaded', () => { - console.log('loaded'); + let t = new Date().getTime(); scene.addLayer(layer); + console.log(new Date().getTime() - t); + + // setTimeout(() => { + // layer.setData([{ + // lng: 120, lat: 30 + // }]) + // }, 2000) + + // layer.on('inited', () => { + // console.log('inited ***') + layer.setData([ + { lng: 120, lat: 30 }, + { lng: 130, lat: 30 }, + ]); + // }) }); }); } diff --git a/stories/MapPerformance/components/updataPointsTimeLine.tsx b/stories/MapPerformance/components/updataPointsTimeLine.tsx index 8b5680a7b2..8da8ff6d24 100644 --- a/stories/MapPerformance/components/updataPointsTimeLine.tsx +++ b/stories/MapPerformance/components/updataPointsTimeLine.tsx @@ -86,7 +86,9 @@ export default class Demo extends React.Component { scene.addLayer(layer); this.layer = layer; - this.getModelDatas(layer, originData, times, parser); + layer.on('modelLoaded', () => { + this.getModelDatas(layer, originData, times, parser); + }); let c = 0; let t = setInterval(() => { diff --git a/stories/MapPerformance/map.stories.tsx b/stories/MapPerformance/map.stories.tsx index 36c85599be..061363908d 100644 --- a/stories/MapPerformance/map.stories.tsx +++ b/stories/MapPerformance/map.stories.tsx @@ -8,7 +8,7 @@ import UpdateAttrAndEle_planeGeometry from './components/updateAttrAndEle_planeG import UpdateAttrTimeLine from './components/updataPointsTimeLine'; import UpdateAttrShenZhen from './components/updateAttrAndEleShenZhen'; import UpdateHeatMap from './components/updataHeatMap'; -import PointTest from './components/Map'; +import PointTest from './components/Points'; import BigLine from './components/BigLine'; import DataUpdate from './components/DataUpdate'; diff --git a/stories/layerbuild/components/Billboard.tsx b/stories/layerbuild/components/Billboard.tsx new file mode 100644 index 0000000000..a39f885ccb --- /dev/null +++ b/stories/layerbuild/components/Billboard.tsx @@ -0,0 +1,79 @@ +// @ts-nocheck +// @ts-ignore +import { Scene, Source } from '@antv/l7'; +import { GeometryLayer } from '@antv/l7-layers'; +import { GaodeMap } from '@antv/l7-maps'; +import * as React from 'react'; + +export default class Demo extends React.Component { + public async componentDidMount() { + const scene = new Scene({ + id: 'map', + map: new GaodeMap({ + pitch: 80, + style: 'dark', + center: [120, 30], + zoom: 5, + }), + }); + + scene.on('loaded', () => { + const img = new Image(); + img.crossOrigin = ''; + img.onload = () => { + let billboard = new GeometryLayer().shape('billboard').style({ + width: 90, + height: 30, + canvasWidth: 360, + canvasHeight: 120, + center: [120, 30], + drawCanvas: (canvas: HTMLCanvasElement) => { + let { width, height } = canvas; + let ctx = canvas.getContext('2d') as CanvasRenderingContext2D; + ctx.globalAlpha = 0.5; + ctx.drawImage( + img, + 0, + 0, + img.width, + img.height, + 0, + 0, + width, + height, + ); + ctx.globalAlpha = 1; + ctx.fillStyle = '#0ff'; + ctx.textAlign = 'center'; + ctx.textBaseline = 'middle'; + ctx.font = '36px Georgia'; + ctx.fillText('Hello World! 蚂蚁', width / 2, height / 2); + }, + raisingHeight: 100, + }); + billboard.active({ + color: '#0ff', + mix: 0.5, + }); + scene.addLayer(billboard); + }; + img.src = + 'https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*zMw0T6gEIZYAAAAAAAAAAAAAARQnAQ'; + }); + } + + public render() { + return ( +
+ ); + } +} diff --git a/stories/layerbuild/components/CityBuilding.tsx b/stories/layerbuild/components/CityBuilding.tsx new file mode 100644 index 0000000000..5fe3fc6f52 --- /dev/null +++ b/stories/layerbuild/components/CityBuilding.tsx @@ -0,0 +1,67 @@ +// @ts-nocheck +// @ts-ignore +import { Scene, Source } from '@antv/l7'; +import { CityBuildingLayer } from '@antv/l7-layers'; +import { GaodeMap } from '@antv/l7-maps'; +import * as React from 'react'; + +export default class Demo extends React.Component { + public async componentDidMount() { + const scene = new Scene({ + id: 'map', + map: new GaodeMap({ + center: [120.145, 30.238915], + pitch: 60, + zoom: 13.2, + }), + }); + + scene.on('loaded', () => { + fetch( + 'https://gw.alipayobjects.com/os/rmsportal/ggFwDClGjjvpSMBIrcEx.json', + ).then(async (res) => { + const pointLayer = new CityBuildingLayer(); + pointLayer + .source(await res.json()) + .size('floor', [0, 500]) + .color('rgba(242,246,250,1.0)') + .animate({ + enable: true, + }) + .active({ + color: '#0ff', + mix: 0.5, + }) + .style({ + opacity: 0.7, + baseColor: 'rgb(16, 16, 16)', + windowColor: 'rgb(30, 60, 89)', + brightColor: 'rgb(255, 176, 38)', + sweep: { + enable: true, + sweepRadius: 2, + sweepColor: '#1990FF', + sweepSpeed: 0.5, + sweepCenter: [120.145319, 30.238915], + }, + }); + scene.addLayer(pointLayer); + }); + }); + } + + public render() { + return ( +
+ ); + } +} diff --git a/stories/layerbuild/components/Heatmap.tsx b/stories/layerbuild/components/Heatmap.tsx new file mode 100644 index 0000000000..bfcc725cca --- /dev/null +++ b/stories/layerbuild/components/Heatmap.tsx @@ -0,0 +1,64 @@ +// @ts-nocheck +// @ts-ignore +import { Scene, Source } from '@antv/l7'; +import { HeatmapLayer } from '@antv/l7-layers'; +import { GaodeMap } from '@antv/l7-maps'; +import * as React from 'react'; + +export default class Demo extends React.Component { + public async componentDidMount() { + const scene = new Scene({ + id: 'map', + map: new GaodeMap({ + center: [120, 30], + pitch: 0, + zoom: 2, + }), + }); + + scene.on('loaded', () => { + fetch( + 'https://gw.alipayobjects.com/os/basement_prod/d3564b06-670f-46ea-8edb-842f7010a7c6.json', + ) + .then((res) => res.json()) + .then((data) => { + const layer = new HeatmapLayer({}) + .source(data) + .shape('heatmap') + .size('mag', [0, 1.0]) // weight映射通道 + .style({ + intensity: 2, + radius: 20, + opacity: 1.0, + rampColors: { + colors: [ + '#FF4818', + '#F7B74A', + '#FFF598', + '#F27DEB', + '#8C1EB2', + '#421EB2', + ].reverse(), + positions: [0, 0.2, 0.4, 0.6, 0.8, 1.0], + }, + }); + scene.addLayer(layer); + }); + }); + } + + public render() { + return ( +
+ ); + } +} diff --git a/stories/layerbuild/components/Heatmap3d.tsx b/stories/layerbuild/components/Heatmap3d.tsx new file mode 100644 index 0000000000..5e315cf5bf --- /dev/null +++ b/stories/layerbuild/components/Heatmap3d.tsx @@ -0,0 +1,64 @@ +// @ts-nocheck +// @ts-ignore +import { Scene, Source } from '@antv/l7'; +import { HeatmapLayer } from '@antv/l7-layers'; +import { GaodeMap } from '@antv/l7-maps'; +import * as React from 'react'; + +export default class Demo extends React.Component { + public async componentDidMount() { + const scene = new Scene({ + id: 'map', + map: new GaodeMap({ + center: [120, 30], + pitch: 0, + zoom: 2, + }), + }); + + scene.on('loaded', () => { + fetch( + 'https://gw.alipayobjects.com/os/basement_prod/d3564b06-670f-46ea-8edb-842f7010a7c6.json', + ) + .then((res) => res.json()) + .then((data) => { + const layer = new HeatmapLayer({}) + .source(data) + .shape('heatmap3d') + .size('mag', [0, 1.0]) // weight映射通道 + .style({ + intensity: 2, + radius: 20, + opacity: 1.0, + rampColors: { + colors: [ + '#FF4818', + '#F7B74A', + '#FFF598', + '#F27DEB', + '#8C1EB2', + '#421EB2', + ].reverse(), + positions: [0, 0.2, 0.4, 0.6, 0.8, 1.0], + }, + }); + scene.addLayer(layer); + }); + }); + } + + public render() { + return ( +
+ ); + } +} diff --git a/stories/layerbuild/components/HeatmapGrid.tsx b/stories/layerbuild/components/HeatmapGrid.tsx new file mode 100644 index 0000000000..7bfa7d3ffd --- /dev/null +++ b/stories/layerbuild/components/HeatmapGrid.tsx @@ -0,0 +1,85 @@ +// @ts-nocheck +// @ts-ignore +import { Scene, Source } from '@antv/l7'; +import { HeatmapLayer } from '@antv/l7-layers'; +import { GaodeMap } from '@antv/l7-maps'; +import * as React from 'react'; + +export default class Demo extends React.Component { + public async componentDidMount() { + const scene = new Scene({ + id: 'map', + map: new GaodeMap({ + center: [120, 30], + pitch: 0, + zoom: 2, + }), + }); + + scene.on('loaded', () => { + fetch( + 'https://gw.alipayobjects.com/os/basement_prod/7359a5e9-3c5e-453f-b207-bc892fb23b84.csv', + ) + .then((res) => res.text()) + .then((data) => { + const layer = new HeatmapLayer({}) + .source(data, { + parser: { + type: 'csv', + x: 'lng', + y: 'lat', + }, + transforms: [ + { + type: 'grid', + size: 20000, + field: 'v', + method: 'sum', + }, + ], + }) + .shape('square') + .style({ + coverage: 1, + angle: 0, + }) + .color( + 'count', + [ + '#0B0030', + '#100243', + '#100243', + '#1B048B', + '#051FB7', + '#0350C1', + '#0350C1', + '#0072C4', + '#0796D3', + '#2BA9DF', + '#30C7C4', + '#6BD5A0', + '#A7ECB2', + '#D0F4CA', + ].reverse(), + ); + + scene.addLayer(layer); + }); + }); + } + + public render() { + return ( +
+ ); + } +} diff --git a/stories/layerbuild/components/HeatmapGrid3d.tsx b/stories/layerbuild/components/HeatmapGrid3d.tsx new file mode 100644 index 0000000000..927430a8d6 --- /dev/null +++ b/stories/layerbuild/components/HeatmapGrid3d.tsx @@ -0,0 +1,83 @@ +// @ts-nocheck +// @ts-ignore +import { Scene, Source } from '@antv/l7'; +import { HeatmapLayer } from '@antv/l7-layers'; +import { GaodeMap } from '@antv/l7-maps'; +import * as React from 'react'; + +export default class Demo extends React.Component { + public async componentDidMount() { + const scene = new Scene({ + id: 'map', + map: new GaodeMap({ + center: [120, 30], + pitch: 40, + zoom: 9, + }), + }); + + scene.on('loaded', () => { + fetch( + 'https://gw.alipayobjects.com/os/basement_prod/a1a8158d-6fe3-424b-8e50-694ccf61c4d7.csv', + ) + .then((res) => res.text()) + .then((data) => { + const layer = new HeatmapLayer({}) + .source(data, { + parser: { + type: 'csv', + x: 'lng', + y: 'lat', + }, + transforms: [ + { + type: 'hexagon', + size: 2500, + field: 'v', + method: 'sum', + }, + ], + }) + .size('sum', (sum) => { + return sum * 200; + }) + .shape('hexagonColumn') + .style({ + coverage: 0.8, + angle: 0, + opacity: 1.0, + }) + .color('sum', [ + '#094D4A', + '#146968', + '#1D7F7E', + '#289899', + '#34B6B7', + '#4AC5AF', + '#5FD3A6', + '#7BE39E', + '#A1EDB8', + '#C3F9CC', + '#DEFAC0', + '#ECFFB1', + ]); + scene.addLayer(layer); + }); + }); + } + + public render() { + return ( +
+ ); + } +} diff --git a/stories/layerbuild/components/HeatmapHexagon.tsx b/stories/layerbuild/components/HeatmapHexagon.tsx new file mode 100644 index 0000000000..5a92e113ef --- /dev/null +++ b/stories/layerbuild/components/HeatmapHexagon.tsx @@ -0,0 +1,78 @@ +// @ts-nocheck +// @ts-ignore +import { Scene, Source } from '@antv/l7'; +import { HeatmapLayer } from '@antv/l7-layers'; +import { GaodeMap } from '@antv/l7-maps'; +import * as React from 'react'; + +export default class Demo extends React.Component { + public async componentDidMount() { + const scene = new Scene({ + id: 'map', + map: new GaodeMap({ + center: [120, 30], + pitch: 40, + zoom: 5, + }), + }); + + scene.on('loaded', () => { + fetch( + 'https://gw.alipayobjects.com/os/basement_prod/337ddbb7-aa3f-4679-ab60-d64359241955.json', + ) + .then((res) => res.json()) + .then((data) => { + const layer = new HeatmapLayer({}) + .source(data, { + transforms: [ + { + type: 'hexagon', + size: 90000, + field: 'capacity', + method: 'sum', + }, + ], + }) + .shape('hexagon') + .style({ + coverage: 0.9, + angle: 0, + opacity: 1.0, + }) + .color( + 'sum', + [ + '#3F4BBA', + '#3F4BBA', + '#3F4BBA', + '#3F4BBA', + '#3C73DA', + '#3C73DA', + '#3C73DA', + '#0F62FF', + '#0F62FF', + '#30B2E9', + '#30B2E9', + '#40C4CE', + ].reverse(), + ); + scene.addLayer(layer); + }); + }); + } + + public render() { + return ( +
+ ); + } +} diff --git a/stories/layerbuild/components/ImageLayer.tsx b/stories/layerbuild/components/ImageLayer.tsx new file mode 100644 index 0000000000..3c8b2fa484 --- /dev/null +++ b/stories/layerbuild/components/ImageLayer.tsx @@ -0,0 +1,48 @@ +// @ts-nocheck +// @ts-ignore +import { Scene, Source } from '@antv/l7'; +import { ImageLayer } from '@antv/l7-layers'; +import { GaodeMap } from '@antv/l7-maps'; +import * as React from 'react'; + +export default class Demo extends React.Component { + public async componentDidMount() { + const scene = new Scene({ + id: 'map', + map: new GaodeMap({ + center: [121.168, 30.2828], + zoom: 8, + }), + }); + + const layer = new ImageLayer({}); + layer.source( + 'https://gw.alipayobjects.com/zos/rmsportal/FnHFeFklTzKDdUESRNDv.jpg', + { + parser: { + type: 'image', + extent: [121.168, 30.2828, 121.384, 30.4219], + }, + }, + ); + + scene.on('loaded', () => { + scene.addLayer(layer); + }); + } + + public render() { + return ( +
+ ); + } +} diff --git a/stories/layerbuild/components/Line.tsx b/stories/layerbuild/components/Line.tsx new file mode 100644 index 0000000000..552b742dc8 --- /dev/null +++ b/stories/layerbuild/components/Line.tsx @@ -0,0 +1,57 @@ +// @ts-nocheck +// @ts-ignore +import { Scene, Source } from '@antv/l7'; +import { LineLayer } from '@antv/l7-layers'; +import { GaodeMap } from '@antv/l7-maps'; +import * as React from 'react'; + +export default class Demo extends React.Component { + public async componentDidMount() { + const scene = new Scene({ + id: 'map', + map: new GaodeMap({ + center: [120, 30], + pitch: 0, + zoom: 2, + }), + }); + const layer = new LineLayer({ workerEnabled: true }) + .source({ + type: 'FeatureCollection', + features: [ + { + type: 'Feature', + properties: {}, + geometry: { + type: 'LineString', + coordinates: [ + [95.625, 38.47939467327645], + [115.48828125000001, 28.92163128242129], + ], + }, + }, + ], + }) + .shape('line') + .color('#f00') + .size(5); + scene.on('loaded', () => { + scene.addLayer(layer); + }); + } + + public render() { + return ( +
+ ); + } +} diff --git a/stories/layerbuild/components/LineArc.tsx b/stories/layerbuild/components/LineArc.tsx new file mode 100644 index 0000000000..8f16eaa2cc --- /dev/null +++ b/stories/layerbuild/components/LineArc.tsx @@ -0,0 +1,57 @@ +// @ts-nocheck +// @ts-ignore +import { Scene, Source } from '@antv/l7'; +import { LineLayer } from '@antv/l7-layers'; +import { GaodeMap } from '@antv/l7-maps'; +import * as React from 'react'; + +export default class Demo extends React.Component { + public async componentDidMount() { + const scene = new Scene({ + id: 'map', + map: new GaodeMap({ + center: [120, 30], + pitch: 0, + zoom: 2, + }), + }); + const layer = new LineLayer() + .source({ + type: 'FeatureCollection', + features: [ + { + type: 'Feature', + properties: {}, + geometry: { + type: 'LineString', + coordinates: [ + [95.625, 38.47939467327645], + [115.48828125000001, 28.92163128242129], + ], + }, + }, + ], + }) + .shape('arc') + .color('#f00') + .size(5); + scene.on('loaded', () => { + scene.addLayer(layer); + }); + } + + public render() { + return ( +
+ ); + } +} diff --git a/stories/layerbuild/components/LineArc3d.tsx b/stories/layerbuild/components/LineArc3d.tsx new file mode 100644 index 0000000000..9aee212a54 --- /dev/null +++ b/stories/layerbuild/components/LineArc3d.tsx @@ -0,0 +1,57 @@ +// @ts-nocheck +// @ts-ignore +import { Scene, Source } from '@antv/l7'; +import { LineLayer } from '@antv/l7-layers'; +import { GaodeMap } from '@antv/l7-maps'; +import * as React from 'react'; + +export default class Demo extends React.Component { + public async componentDidMount() { + const scene = new Scene({ + id: 'map', + map: new GaodeMap({ + center: [120, 30], + pitch: 0, + zoom: 2, + }), + }); + const layer = new LineLayer() + .source({ + type: 'FeatureCollection', + features: [ + { + type: 'Feature', + properties: {}, + geometry: { + type: 'LineString', + coordinates: [ + [95.625, 38.47939467327645], + [115.48828125000001, 28.92163128242129], + ], + }, + }, + ], + }) + .shape('arc3d') + .color('#f00') + .size(5); + scene.on('loaded', () => { + scene.addLayer(layer); + }); + } + + public render() { + return ( +
+ ); + } +} diff --git a/stories/layerbuild/components/LineEarthArc3D.tsx b/stories/layerbuild/components/LineEarthArc3D.tsx new file mode 100644 index 0000000000..21f03e6ccd --- /dev/null +++ b/stories/layerbuild/components/LineEarthArc3D.tsx @@ -0,0 +1,93 @@ +// @ts-nocheck +// @ts-ignore +import { Scene, Source } from '@antv/l7'; +import { LineLayer, EarthLayer } from '@antv/l7-layers'; +import { GaodeMap, Earth } from '@antv/l7-maps'; +import * as React from 'react'; + +export default class Demo extends React.Component { + public async componentDidMount() { + const scene = new Scene({ + id: 'map', + map: new Earth({ + center: [120, 30], + pitch: 0, + zoom: 3, + }), + }); + + const layer = new LineLayer() + .source({ + type: 'FeatureCollection', + features: [ + { + type: 'Feature', + properties: {}, + geometry: { + type: 'LineString', + coordinates: [ + [95.625, 38.47939467327645], + [115.48828125000001, 28.92163128242129], + ], + }, + }, + ], + }) + .shape('earthArc3d') + .color('#f00') + .size(2); + const earthlayer = new EarthLayer() + .source( + 'https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*3-3NSpqRqUoAAAAAAAAAAAAAARQnAQ', + { + parser: { + type: 'image', + }, + }, + ) + .shape('base') + .style({ + globelOtions: { + ambientRatio: 0.6, // 环境光 + diffuseRatio: 0.4, // 漫反射 + specularRatio: 0.1, // 高光反射 + earthTime: 0.1, + }, + }) + .animate(true); + + const atomLayer = new EarthLayer() + .color('#2E8AE6') + .shape('atomSphere') + .style({ + opacity: 1, + }); + + const bloomLayer = new EarthLayer().color('#fff').shape('bloomSphere'); + + scene.on('loaded', () => { + scene.addLayer(earthlayer); + scene.addLayer(layer); + + scene.addLayer(atomLayer); + scene.addLayer(bloomLayer); + + earthlayer.setEarthTime(4.0); + }); + } + + public render() { + return ( +
+ ); + } +} diff --git a/stories/layerbuild/components/LineGreatCircle.tsx b/stories/layerbuild/components/LineGreatCircle.tsx new file mode 100644 index 0000000000..101185762c --- /dev/null +++ b/stories/layerbuild/components/LineGreatCircle.tsx @@ -0,0 +1,57 @@ +// @ts-nocheck +// @ts-ignore +import { Scene, Source } from '@antv/l7'; +import { LineLayer } from '@antv/l7-layers'; +import { GaodeMap } from '@antv/l7-maps'; +import * as React from 'react'; + +export default class Demo extends React.Component { + public async componentDidMount() { + const scene = new Scene({ + id: 'map', + map: new GaodeMap({ + center: [120, 30], + pitch: 0, + zoom: 2, + }), + }); + const layer = new LineLayer() + .source({ + type: 'FeatureCollection', + features: [ + { + type: 'Feature', + properties: {}, + geometry: { + type: 'LineString', + coordinates: [ + [95.625, 38.47939467327645], + [115.48828125000001, 28.92163128242129], + ], + }, + }, + ], + }) + .shape('greatcircle') + .color('#f00') + .size(5); + scene.on('loaded', () => { + scene.addLayer(layer); + }); + } + + public render() { + return ( +
+ ); + } +} diff --git a/stories/layerbuild/components/LineHalf.tsx b/stories/layerbuild/components/LineHalf.tsx new file mode 100644 index 0000000000..011523b288 --- /dev/null +++ b/stories/layerbuild/components/LineHalf.tsx @@ -0,0 +1,62 @@ +// @ts-nocheck +// @ts-ignore +import { Scene, Source } from '@antv/l7'; +import { LineLayer } from '@antv/l7-layers'; +import { GaodeMap } from '@antv/l7-maps'; +import * as React from 'react'; + +export default class Demo extends React.Component { + public async componentDidMount() { + const scene = new Scene({ + id: 'map', + map: new GaodeMap({ + center: [120, 30], + pitch: 0, + zoom: 2, + }), + }); + const layer = new LineLayer() + .source({ + type: 'FeatureCollection', + features: [ + { + type: 'Feature', + properties: {}, + geometry: { + type: 'LineString', + coordinates: [ + [95.625, 28], + [115.48828125000001, 28], + ], + }, + }, + ], + }) + .shape('halfLine') + .color('#f00') + .size(10) + .style({ + arrow: { + enable: true, + }, + }); + scene.on('loaded', () => { + scene.addLayer(layer); + }); + } + + public render() { + return ( +
+ ); + } +} diff --git a/stories/layerbuild/components/LineLinear.tsx b/stories/layerbuild/components/LineLinear.tsx new file mode 100644 index 0000000000..94ab34e074 --- /dev/null +++ b/stories/layerbuild/components/LineLinear.tsx @@ -0,0 +1,70 @@ +// @ts-nocheck +// @ts-ignore +import { Scene, Source } from '@antv/l7'; +import { LineLayer } from '@antv/l7-layers'; +import { GaodeMap } from '@antv/l7-maps'; +import * as React from 'react'; + +export default class Demo extends React.Component { + public async componentDidMount() { + const scene = new Scene({ + id: 'map', + map: new GaodeMap({ + center: [120, 30], + pitch: 0, + zoom: 2, + }), + }); + const layer = new LineLayer() + .source({ + type: 'FeatureCollection', + features: [ + { + type: 'Feature', + properties: {}, + geometry: { + type: 'LineString', + coordinates: [ + [95.625, 38.47939467327645], + [115.48828125000001, 28.92163128242129], + ], + }, + }, + ], + }) + .shape('linearline') + .color('#f00') + .size(5) + .style({ + rampColors: { + colors: [ + '#FF4818', + '#F7B74A', + '#FFF598', + '#91EABC', + '#2EA9A1', + '#206C7C', + ], + positions: [0, 0.2, 0.4, 0.6, 0.8, 1.0], + }, + }); + scene.on('loaded', () => { + scene.addLayer(layer); + }); + } + + public render() { + return ( +
+ ); + } +} diff --git a/stories/layerbuild/components/LineSimple.tsx b/stories/layerbuild/components/LineSimple.tsx new file mode 100644 index 0000000000..2103e2c3ac --- /dev/null +++ b/stories/layerbuild/components/LineSimple.tsx @@ -0,0 +1,57 @@ +// @ts-nocheck +// @ts-ignore +import { Scene, Source } from '@antv/l7'; +import { LineLayer } from '@antv/l7-layers'; +import { GaodeMap } from '@antv/l7-maps'; +import * as React from 'react'; + +export default class Demo extends React.Component { + public async componentDidMount() { + const scene = new Scene({ + id: 'map', + map: new GaodeMap({ + center: [120, 30], + pitch: 0, + zoom: 2, + }), + }); + const layer = new LineLayer() + .source({ + type: 'FeatureCollection', + features: [ + { + type: 'Feature', + properties: {}, + geometry: { + type: 'LineString', + coordinates: [ + [95.625, 38.47939467327645], + [115.48828125000001, 28.92163128242129], + ], + }, + }, + ], + }) + .shape('simple') + .color('#f00') + .size(5); + scene.on('loaded', () => { + scene.addLayer(layer); + }); + } + + public render() { + return ( +
+ ); + } +} diff --git a/stories/layerbuild/components/LineTile.tsx b/stories/layerbuild/components/LineTile.tsx new file mode 100644 index 0000000000..36466af6f3 --- /dev/null +++ b/stories/layerbuild/components/LineTile.tsx @@ -0,0 +1,61 @@ +// @ts-nocheck +// @ts-ignore +import { Scene, Source } from '@antv/l7'; +import { LineLayer } from '@antv/l7-layers'; +import { GaodeMap } from '@antv/l7-maps'; +import * as React from 'react'; + +export default class Demo extends React.Component { + public async componentDidMount() { + const scene = new Scene({ + id: 'map', + stencil: true, + map: new GaodeMap({ + center: [110.19382669582967, 30.258134], + pitch: 0, + zoom: 4, + }), + }); + + const layer = new LineLayer({ + featureId: 'COLOR', + sourceLayer: 'ecoregions2', // woods hillshade contour ecoregions ecoregions2 city + workerEnabled: true, + }); + layer + .source( + 'http://ganos.oss-cn-hangzhou.aliyuncs.com/m2/rs_l7/{z}/{x}/{y}.pbf', + { + parser: { + type: 'mvt', + tileSize: 256, + zoomOffset: 0, + maxZoom: 9, + extent: [-180, -85.051129, 179, 85.051129], + }, + }, + ) + .color('COLOR') + .size(2) + .select(true); + + scene.on('loaded', () => { + scene.addLayer(layer); + }); + } + + public render() { + return ( +
+ ); + } +} diff --git a/stories/layerbuild/components/LineWall.tsx b/stories/layerbuild/components/LineWall.tsx new file mode 100644 index 0000000000..c2dd0be401 --- /dev/null +++ b/stories/layerbuild/components/LineWall.tsx @@ -0,0 +1,57 @@ +// @ts-nocheck +// @ts-ignore +import { Scene, Source } from '@antv/l7'; +import { LineLayer } from '@antv/l7-layers'; +import { GaodeMap } from '@antv/l7-maps'; +import * as React from 'react'; + +export default class Demo extends React.Component { + public async componentDidMount() { + const scene = new Scene({ + id: 'map', + map: new GaodeMap({ + center: [105, 30], + pitch: 40, + zoom: 4, + }), + }); + const layer = new LineLayer() + .source({ + type: 'FeatureCollection', + features: [ + { + type: 'Feature', + properties: {}, + geometry: { + type: 'LineString', + coordinates: [ + [95.625, 38.47939467327645], + [115.48828125000001, 28.92163128242129], + ], + }, + }, + ], + }) + .shape('wall') + .color('#f00') + .size(40); + scene.on('loaded', () => { + scene.addLayer(layer); + }); + } + + public render() { + return ( +
+ ); + } +} diff --git a/stories/layerbuild/components/Plane.tsx b/stories/layerbuild/components/Plane.tsx new file mode 100644 index 0000000000..d422d33ecf --- /dev/null +++ b/stories/layerbuild/components/Plane.tsx @@ -0,0 +1,108 @@ +// @ts-nocheck +// @ts-ignore +import { Scene, Source } from '@antv/l7'; +import { GeometryLayer } from '@antv/l7-layers'; +import { GaodeMap } from '@antv/l7-maps'; +import * as React from 'react'; + +export default class Demo extends React.Component { + public async componentDidMount() { + const scene = new Scene({ + id: 'map', + map: new GaodeMap({ + center: [120.1025, 30.2594], + style: 'dark', + pitch: 65, + rotation: 180, + zoom: 14, + }), + }); + + let currentZoom = 14, + currentModelData = '100x100'; + + scene.on('loaded', () => { + const layer = new GeometryLayer().shape('plane').style({ + width: 0.074, + height: 0.061, + center: [120.1025, 30.2594], + widthSegments: 100, + heightSegments: 100, + terrainClipHeight: 1, + mapTexture: + 'https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*gA0NRbuOF5cAAAAAAAAAAAAAARQnAQ', + terrainTexture: + 'https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*eYFaRYlnnOUAAAAAAAAAAAAAARQnAQ', + rgb2height: (r, g, b) => { + 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); + return h; + }, + }); + scene.addLayer(layer); + + let modelData10, + modelData20 = null, + modelData100; + + layer.on('terrainImageLoaded', () => { + modelData10 = layer.createModelData([], { + widthSegments: 10, + heightSegments: 10, + }); + + modelData20 = layer.createModelData([], { + widthSegments: 20, + heightSegments: 20, + }); + + modelData100 = layer.createModelData([], { + widthSegments: 100, + heightSegments: 100, + }); + }); + + scene.on('zoom', ({ value }) => { + const zoom = Math.floor(value); + if (currentZoom !== zoom) { + if (zoom > 13) { + if (currentModelData !== '100x100') { + layer.updateModelData(modelData100); + currentModelData = '100x100'; + } + } else if (zoom > 12) { + if (currentModelData !== '20x20') { + layer.updateModelData(modelData20); + currentModelData = '20x20'; + } + } else { + if (currentModelData !== '10x10') { + layer.updateModelData(modelData10); + currentModelData = '10x10'; + } + } + currentZoom = zoom; + } + return ''; + }); + }); + } + + public render() { + return ( +
+ ); + } +} diff --git a/stories/layerbuild/components/Points.tsx b/stories/layerbuild/components/Points.tsx new file mode 100644 index 0000000000..dcfcf22e9e --- /dev/null +++ b/stories/layerbuild/components/Points.tsx @@ -0,0 +1,95 @@ +// @ts-nocheck +// @ts-ignore +import { Scene, Source } from '@antv/l7'; +import { PointLayer } from '@antv/l7-layers'; +import { GaodeMap } from '@antv/l7-maps'; +import * as React from 'react'; + +export default class Demo extends React.Component { + public async componentDidMount() { + const scene = new Scene({ + id: 'map', + map: new GaodeMap({ + center: [110.19382669582967, 30.258134], + pitch: 0, + zoom: 2, + }), + }); + + // let address = 'https://gw.alipayobjects.com/os/bmw-prod/e76d89f4-aa69-4974-90b7-b236904a43b1.json' // 100 + // let address = 'https://gw.alipayobjects.com/os/bmw-prod/edc8219a-b095-4451-98e9-3e387e290087.json' // 10000 + // let address = 'https://gw.alipayobjects.com/os/bmw-prod/2c37f08b-3fe6-4c68-a699-dc15cfc217f1.json' // 50000 + let address = + 'https://gw.alipayobjects.com/os/bmw-prod/8adff753-64e6-4ffa-9e7b-1f3dc6f4fd76.json'; // 100000 + // let address = + // 'https://gw.alipayobjects.com/os/bmw-prod/577a70fb-fc19-4582-83ed-7cddb7b77645.json'; // 20 0000 + fetch(address) + .then((res) => res.json()) + .then((data) => { + const source = new Source( + [ + { + lng: 120, + lat: 30, + }, + ], + { + parser: { + type: 'json', + x: 'lng', + y: 'lat', + }, + }, + ); + + const layer = new PointLayer({ workerEnabled: true }) + .source(data, { + parser: { + type: 'json', + x: 'lng', + y: 'lat', + }, + }) + // .source(source) + .size(10) + .color('#f00') + .shape('circle') + .active(true); + + scene.on('loaded', () => { + let t = new Date().getTime(); + scene.addLayer(layer); + console.log(new Date().getTime() - t); + + // setTimeout(() => { + // layer.setData([{ + // lng: 120, lat: 30 + // }]) + // }, 2000) + + // layer.on('inited', () => { + // console.log('inited ***') + // layer.setData([ + // { lng: 120, lat: 30 }, + // { lng: 130, lat: 30 }, + // ]); + // }) + }); + }); + } + + public render() { + return ( +
+ ); + } +} diff --git a/stories/layerbuild/components/PointsEarthExtrude.tsx b/stories/layerbuild/components/PointsEarthExtrude.tsx new file mode 100644 index 0000000000..b6bbc19ce0 --- /dev/null +++ b/stories/layerbuild/components/PointsEarthExtrude.tsx @@ -0,0 +1,106 @@ +// @ts-nocheck +// @ts-ignore +import { Scene, Source } from '@antv/l7'; +import { PointLayer, EarthLayer } from '@antv/l7-layers'; +import { GaodeMap, Earth } from '@antv/l7-maps'; +import * as React from 'react'; + +export default class Demo extends React.Component { + public async componentDidMount() { + const scene = new Scene({ + id: 'map', + map: new Earth({ + center: [120, 30], + pitch: 0, + zoom: 3, + }), + }); + + const pointlayer = new PointLayer({}) + .source( + [ + { lng: 121.61865234375, lat: 25.29437116258816 }, + { lng: 121.058349609375, lat: 25.015928763367857 }, + { lng: 120.7177734375, lat: 24.587090339209634 }, + { lng: 120.28930664062499, lat: 23.936054914599815 }, + { lng: 120.12451171875, lat: 23.553916518321625 }, + { lng: 121.124267578125, lat: 22.806567100271522 }, + { lng: 121.56372070312499, lat: 23.915970370510227 }, + { lng: 121.88232421875, lat: 24.557116164309626 }, + { lng: 121.95922851562501, lat: 25.075648445630527 }, + { lng: 109.97314453125, lat: 20.076570104545173 }, + { lng: 108.896484375, lat: 19.663280219987662 }, + { lng: 108.61083984375, lat: 18.979025953255267 }, + { lng: 108.80859375, lat: 18.47960905583197 }, + { lng: 109.599609375, lat: 18.35452552912664 }, + { lng: 110.32470703125, lat: 18.771115062337024 }, + { lng: 111.005859375, lat: 19.78738018198621 }, + { lng: 110, lat: 30 }, + ], + { + parser: { + type: 'json', + x: 'lng', + y: 'lat', + }, + }, + ) + .shape('cylinder') + .color('#f00') + .size([1, 1, 10]) + .active(true); + const earthlayer = new EarthLayer() + .source( + 'https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*3-3NSpqRqUoAAAAAAAAAAAAAARQnAQ', + { + parser: { + type: 'image', + }, + }, + ) + .shape('base') + .style({ + globelOtions: { + ambientRatio: 0.6, // 环境光 + diffuseRatio: 0.4, // 漫反射 + specularRatio: 0.1, // 高光反射 + earthTime: 0.1, + }, + }) + .animate(true); + + const atomLayer = new EarthLayer() + .color('#2E8AE6') + .shape('atomSphere') + .style({ + opacity: 1, + }); + + const bloomLayer = new EarthLayer().color('#fff').shape('bloomSphere'); + + scene.on('loaded', () => { + scene.addLayer(earthlayer); + scene.addLayer(pointlayer); + + scene.addLayer(atomLayer); + scene.addLayer(bloomLayer); + + earthlayer.setEarthTime(4.0); + }); + } + + public render() { + return ( +
+ ); + } +} diff --git a/stories/layerbuild/components/PointsEarthFill.tsx b/stories/layerbuild/components/PointsEarthFill.tsx new file mode 100644 index 0000000000..6d715afa1a --- /dev/null +++ b/stories/layerbuild/components/PointsEarthFill.tsx @@ -0,0 +1,106 @@ +// @ts-nocheck +// @ts-ignore +import { Scene, Source } from '@antv/l7'; +import { PointLayer, EarthLayer } from '@antv/l7-layers'; +import { GaodeMap, Earth } from '@antv/l7-maps'; +import * as React from 'react'; + +export default class Demo extends React.Component { + public async componentDidMount() { + const scene = new Scene({ + id: 'map', + map: new Earth({ + center: [120, 30], + pitch: 0, + zoom: 3, + }), + }); + + const pointlayer = new PointLayer({}) + .source( + [ + { lng: 121.61865234375, lat: 25.29437116258816 }, + { lng: 121.058349609375, lat: 25.015928763367857 }, + { lng: 120.7177734375, lat: 24.587090339209634 }, + { lng: 120.28930664062499, lat: 23.936054914599815 }, + { lng: 120.12451171875, lat: 23.553916518321625 }, + { lng: 121.124267578125, lat: 22.806567100271522 }, + { lng: 121.56372070312499, lat: 23.915970370510227 }, + { lng: 121.88232421875, lat: 24.557116164309626 }, + { lng: 121.95922851562501, lat: 25.075648445630527 }, + { lng: 109.97314453125, lat: 20.076570104545173 }, + { lng: 108.896484375, lat: 19.663280219987662 }, + { lng: 108.61083984375, lat: 18.979025953255267 }, + { lng: 108.80859375, lat: 18.47960905583197 }, + { lng: 109.599609375, lat: 18.35452552912664 }, + { lng: 110.32470703125, lat: 18.771115062337024 }, + { lng: 111.005859375, lat: 19.78738018198621 }, + { lng: 110, lat: 30 }, + ], + { + parser: { + type: 'json', + x: 'lng', + y: 'lat', + }, + }, + ) + .shape('circle') + .color('#f00') + .size(20) + .active(true); + const earthlayer = new EarthLayer() + .source( + 'https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*3-3NSpqRqUoAAAAAAAAAAAAAARQnAQ', + { + parser: { + type: 'image', + }, + }, + ) + .shape('base') + .style({ + globelOtions: { + ambientRatio: 0.6, // 环境光 + diffuseRatio: 0.4, // 漫反射 + specularRatio: 0.1, // 高光反射 + earthTime: 0.1, + }, + }) + .animate(true); + + const atomLayer = new EarthLayer() + .color('#2E8AE6') + .shape('atomSphere') + .style({ + opacity: 1, + }); + + const bloomLayer = new EarthLayer().color('#fff').shape('bloomSphere'); + + scene.on('loaded', () => { + scene.addLayer(earthlayer); + scene.addLayer(pointlayer); + + scene.addLayer(atomLayer); + scene.addLayer(bloomLayer); + + earthlayer.setEarthTime(4.0); + }); + } + + public render() { + return ( +
+ ); + } +} diff --git a/stories/layerbuild/components/PointsExtrude.tsx b/stories/layerbuild/components/PointsExtrude.tsx new file mode 100644 index 0000000000..f9cf1ae82e --- /dev/null +++ b/stories/layerbuild/components/PointsExtrude.tsx @@ -0,0 +1,59 @@ +// @ts-nocheck +// @ts-ignore +import { Scene, Source } from '@antv/l7'; +import { PointLayer } from '@antv/l7-layers'; +import { GaodeMap } from '@antv/l7-maps'; +import * as React from 'react'; + +export default class Demo extends React.Component { + public async componentDidMount() { + const scene = new Scene({ + id: 'map', + map: new GaodeMap({ + center: [110.19382669582967, 30.258134], + pitch: 0, + zoom: 2, + }), + }); + + const layer = new PointLayer() + .source( + [ + { + lng: 120, + lat: 30, + }, + ], + { + parser: { + type: 'json', + x: 'lng', + y: 'lat', + }, + }, + ) + .size([10, 10, 100]) + .color('#f00') + .shape('cylinder') + .active(true); + + scene.on('loaded', () => { + scene.addLayer(layer); + }); + } + + public render() { + return ( +
+ ); + } +} diff --git a/stories/layerbuild/components/PointsFillImage.tsx b/stories/layerbuild/components/PointsFillImage.tsx new file mode 100644 index 0000000000..1e0cd8d4bc --- /dev/null +++ b/stories/layerbuild/components/PointsFillImage.tsx @@ -0,0 +1,65 @@ +// @ts-nocheck +// @ts-ignore +import { Scene, Source } from '@antv/l7'; +import { PointLayer } from '@antv/l7-layers'; +import { GaodeMap } from '@antv/l7-maps'; +import * as React from 'react'; + +export default class Demo extends React.Component { + public async componentDidMount() { + const scene = new Scene({ + id: 'map', + map: new GaodeMap({ + center: [110.19382669582967, 30.258134], + pitch: 0, + zoom: 2, + }), + }); + + scene.addImage( + 'img', + 'https://gw.alipayobjects.com/mdn/rms_816329/afts/img/A*rd3kTp1VFxIAAAAAAAAAAAAAARQnAQ', + ); + const imageData = [ + { + lng: 120, + lat: 30, + img: 'img', + }, + ]; + + const layer = new PointLayer({ layerType: 'fillImage' }) + .source(imageData, { + parser: { + type: 'json', + x: 'lng', + y: 'lat', + }, + }) + .size(15) + .shape('img', ['img']) + .active({ + color: '#f00', + mix: 0.5, + }); + + scene.on('loaded', () => { + scene.addLayer(layer); + }); + } + + public render() { + return ( +
+ ); + } +} diff --git a/stories/layerbuild/components/PointsIconFont.tsx b/stories/layerbuild/components/PointsIconFont.tsx new file mode 100644 index 0000000000..7cb9942d91 --- /dev/null +++ b/stories/layerbuild/components/PointsIconFont.tsx @@ -0,0 +1,74 @@ +// @ts-nocheck +// @ts-ignore +import { Scene, Source } from '@antv/l7'; +import { PointLayer } from '@antv/l7-layers'; +import { GaodeMap } from '@antv/l7-maps'; +import * as React from 'react'; + +export default class Demo extends React.Component { + public async componentDidMount() { + const scene = new Scene({ + id: 'map', + map: new GaodeMap({ + center: [110.19382669582967, 30.258134], + pitch: 0, + zoom: 2, + }), + }); + + const fontFamily = 'iconfont'; + // 指定 iconfont 字体文件 + const fontPath = + '//at.alicdn.com/t/font_2534097_fcae9o2mxbv.woff2?t=1622200439140'; + // 全局添加资源 + scene.addFontFace(fontFamily, fontPath); + // 全局添加 iconfont 字段的映射; + scene.addIconFont('icon1', ''); + + scene.on('loaded', () => { + const imageLayer = new PointLayer() + .source( + [ + { + lng: 120, + lat: 30, + icon: 'icon1', + }, + ], + { + parser: { + type: 'json', + x: 'lng', + y: 'lat', + }, + }, + ) + .color('#44ff00') + .shape('icon', 'text') + .size(30) + .style({ + padding: [0, 0], // 文本包围盒 padding [水平,垂直],影响碰撞检测结果,避免相邻文本靠的太近 + stroke: '#ffffff', // 描边颜色 + fontFamily, + iconfont: true, + textAllowOverlap: true, + }); + scene.addLayer(imageLayer); + }); + } + + public render() { + return ( +
+ ); + } +} diff --git a/stories/layerbuild/components/PointsImage.tsx b/stories/layerbuild/components/PointsImage.tsx new file mode 100644 index 0000000000..863dd249df --- /dev/null +++ b/stories/layerbuild/components/PointsImage.tsx @@ -0,0 +1,65 @@ +// @ts-nocheck +// @ts-ignore +import { Scene, Source } from '@antv/l7'; +import { PointLayer } from '@antv/l7-layers'; +import { GaodeMap } from '@antv/l7-maps'; +import * as React from 'react'; + +export default class Demo extends React.Component { + public async componentDidMount() { + const scene = new Scene({ + id: 'map', + map: new GaodeMap({ + center: [110.19382669582967, 30.258134], + pitch: 0, + zoom: 2, + }), + }); + + scene.addImage( + 'img', + 'https://gw.alipayobjects.com/mdn/rms_816329/afts/img/A*rd3kTp1VFxIAAAAAAAAAAAAAARQnAQ', + ); + const imageData = [ + { + lng: 120, + lat: 30, + img: 'img', + }, + ]; + + const layer = new PointLayer({}) + .source(imageData, { + parser: { + type: 'json', + x: 'lng', + y: 'lat', + }, + }) + .size(15) + .shape('img', ['img']) + .active({ + color: '#f00', + mix: 0.5, + }); + + scene.on('loaded', () => { + scene.addLayer(layer); + }); + } + + public render() { + return ( +
+ ); + } +} diff --git a/stories/layerbuild/components/PointsNormal.tsx b/stories/layerbuild/components/PointsNormal.tsx new file mode 100644 index 0000000000..f371a1ade6 --- /dev/null +++ b/stories/layerbuild/components/PointsNormal.tsx @@ -0,0 +1,60 @@ +// @ts-nocheck +// @ts-ignore +import { Scene, Source } from '@antv/l7'; +import { PointLayer } from '@antv/l7-layers'; +import { GaodeMap } from '@antv/l7-maps'; +import * as React from 'react'; + +export default class Demo extends React.Component { + public async componentDidMount() { + const scene = new Scene({ + id: 'map', + map: new GaodeMap({ + center: [110.19382669582967, 30.258134], + pitch: 40, + zoom: 2, + }), + }); + + const layer = new PointLayer() + .source( + [ + { + lng: 120, + lat: 30, + t: 'text1', + }, + ], + { + parser: { + type: 'json', + x: 'lng', + y: 'lat', + }, + }, + ) + .size(15) + .color('#f00') + .shape('dot') + .active(true); + + scene.on('loaded', () => { + scene.addLayer(layer); + }); + } + + public render() { + return ( +
+ ); + } +} diff --git a/stories/layerbuild/components/PointsRadar.tsx b/stories/layerbuild/components/PointsRadar.tsx new file mode 100644 index 0000000000..47acfb60a7 --- /dev/null +++ b/stories/layerbuild/components/PointsRadar.tsx @@ -0,0 +1,61 @@ +// @ts-nocheck +// @ts-ignore +import { Scene, Source } from '@antv/l7'; +import { PointLayer } from '@antv/l7-layers'; +import { GaodeMap } from '@antv/l7-maps'; +import * as React from 'react'; + +export default class Demo extends React.Component { + public async componentDidMount() { + const scene = new Scene({ + id: 'map', + map: new GaodeMap({ + center: [110.19382669582967, 30.258134], + pitch: 0, + zoom: 2, + }), + }); + + const layer = new PointLayer() + .source( + [ + { + lng: 120, + lat: 30, + t: 'text1', + }, + ], + { + parser: { + type: 'json', + x: 'lng', + y: 'lat', + }, + }, + ) + .size(15) + .color('#f00') + .shape('radar') + .animate(true) + .active(true); + + scene.on('loaded', () => { + scene.addLayer(layer); + }); + } + + public render() { + return ( +
+ ); + } +} diff --git a/stories/layerbuild/components/PointsSimple.tsx b/stories/layerbuild/components/PointsSimple.tsx new file mode 100644 index 0000000000..4651ed0910 --- /dev/null +++ b/stories/layerbuild/components/PointsSimple.tsx @@ -0,0 +1,60 @@ +// @ts-nocheck +// @ts-ignore +import { Scene, Source } from '@antv/l7'; +import { PointLayer } from '@antv/l7-layers'; +import { GaodeMap } from '@antv/l7-maps'; +import * as React from 'react'; + +export default class Demo extends React.Component { + public async componentDidMount() { + const scene = new Scene({ + id: 'map', + map: new GaodeMap({ + center: [110.19382669582967, 30.258134], + pitch: 40, + zoom: 2, + }), + }); + + const layer = new PointLayer() + .source( + [ + { + lng: 120, + lat: 30, + t: 'text1', + }, + ], + { + parser: { + type: 'json', + x: 'lng', + y: 'lat', + }, + }, + ) + .size(15) + .color('#f00') + .shape('simple') + .active(true); + + scene.on('loaded', () => { + scene.addLayer(layer); + }); + } + + public render() { + return ( +
+ ); + } +} diff --git a/stories/layerbuild/components/PointsText.tsx b/stories/layerbuild/components/PointsText.tsx new file mode 100644 index 0000000000..cca5da7d79 --- /dev/null +++ b/stories/layerbuild/components/PointsText.tsx @@ -0,0 +1,60 @@ +// @ts-nocheck +// @ts-ignore +import { Scene, Source } from '@antv/l7'; +import { PointLayer } from '@antv/l7-layers'; +import { GaodeMap } from '@antv/l7-maps'; +import * as React from 'react'; + +export default class Demo extends React.Component { + public async componentDidMount() { + const scene = new Scene({ + id: 'map', + map: new GaodeMap({ + center: [110.19382669582967, 30.258134], + pitch: 0, + zoom: 2, + }), + }); + + const layer = new PointLayer() + .source( + [ + { + lng: 120, + lat: 30, + t: 'text1', + }, + ], + { + parser: { + type: 'json', + x: 'lng', + y: 'lat', + }, + }, + ) + .size(15) + .color('#f00') + .shape('t', 'text') + .active(true); + + scene.on('loaded', () => { + scene.addLayer(layer); + }); + } + + public render() { + return ( +
+ ); + } +} diff --git a/stories/layerbuild/components/PointsTextTile.tsx b/stories/layerbuild/components/PointsTextTile.tsx new file mode 100644 index 0000000000..55de24e84b --- /dev/null +++ b/stories/layerbuild/components/PointsTextTile.tsx @@ -0,0 +1,64 @@ +// @ts-nocheck +// @ts-ignore +import { Scene, Source } from '@antv/l7'; +import { PointLayer } from '@antv/l7-layers'; +import { GaodeMap } from '@antv/l7-maps'; +import * as React from 'react'; + +export default class Demo extends React.Component { + public async componentDidMount() { + const scene = new Scene({ + id: 'map', + map: new GaodeMap({ + center: [110.19382669582967, 30.258134], + pitch: 0, + zoom: 4, + }), + }); + + const layer = new PointLayer({ + featureId: 'COLOR', + sourceLayer: 'ecoregions2', // woods hillshade contour ecoregions ecoregions2 city + }); + layer + .source( + 'http://ganos.oss-cn-hangzhou.aliyuncs.com/m2/rs_l7/{z}/{x}/{y}.pbf', + { + parser: { + type: 'mvt', + tileSize: 256, + zoomOffset: 0, + maxZoom: 9, + extent: [-180, -85.051129, 179, 85.051129], + }, + }, + ) + .shape('NNH_NAME', 'text') + .color('COLOR') + .size(12) + .style({ + stroke: '#00f', + strokeWidth: 1, + textAllowOverlap: false, + }); + + scene.on('loaded', () => { + scene.addLayer(layer); + }); + } + + public render() { + return ( +
+ ); + } +} diff --git a/stories/layerbuild/components/PointsTile.tsx b/stories/layerbuild/components/PointsTile.tsx new file mode 100644 index 0000000000..c1aec4536e --- /dev/null +++ b/stories/layerbuild/components/PointsTile.tsx @@ -0,0 +1,60 @@ +// @ts-nocheck +// @ts-ignore +import { Scene, Source } from '@antv/l7'; +import { PointLayer } from '@antv/l7-layers'; +import { GaodeMap, Map } from '@antv/l7-maps'; +import * as React from 'react'; + +export default class Demo extends React.Component { + public async componentDidMount() { + const scene = new Scene({ + id: 'map', + map: new Map({ + center: [110.19382669582967, 30.258134], + pitch: 0, + zoom: 4, + }), + }); + + const layer = new PointLayer({ + featureId: 'COLOR', + sourceLayer: 'ecoregions2', // woods hillshade contour ecoregions ecoregions2 city + workerEnabled: true, + }); + layer + .source( + 'http://ganos.oss-cn-hangzhou.aliyuncs.com/m2/rs_l7/{z}/{x}/{y}.pbf', + { + parser: { + type: 'mvt', + tileSize: 256, + zoomOffset: 0, + maxZoom: 9, + extent: [-180, -85.051129, 179, 85.051129], + }, + }, + ) + .color('COLOR') + .size(10) + .select(true); + + scene.on('loaded', () => { + scene.addLayer(layer); + }); + } + + public render() { + return ( +
+ ); + } +} diff --git a/stories/layerbuild/components/Polygon.tsx b/stories/layerbuild/components/Polygon.tsx new file mode 100644 index 0000000000..db67ed4900 --- /dev/null +++ b/stories/layerbuild/components/Polygon.tsx @@ -0,0 +1,61 @@ +// @ts-nocheck +// @ts-ignore +import { Scene, Source } from '@antv/l7'; +import { PolygonLayer } from '@antv/l7-layers'; +import { GaodeMap } from '@antv/l7-maps'; +import * as React from 'react'; + +export default class Demo extends React.Component { + public async componentDidMount() { + const scene = new Scene({ + id: 'map', + map: new GaodeMap({ + center: [120, 30], + pitch: 0, + zoom: 2, + }), + }); + const layer = new PolygonLayer({ workerEnabled: true }) + .source({ + type: 'FeatureCollection', + features: [ + { + type: 'Feature', + properties: {}, + geometry: { + type: 'Polygon', + coordinates: [ + [ + [104.4140625, 35.460669951495305], + [98.7890625, 24.206889622398023], + [111.796875, 27.371767300523047], + [104.4140625, 35.460669951495305], + ], + ], + }, + }, + ], + }) + .shape('fill') + .color('#f00'); + + scene.on('loaded', () => { + scene.addLayer(layer); + }); + } + + public render() { + return ( +
+ ); + } +} diff --git a/stories/layerbuild/components/PolygonExtrude.tsx b/stories/layerbuild/components/PolygonExtrude.tsx new file mode 100644 index 0000000000..166bd9220f --- /dev/null +++ b/stories/layerbuild/components/PolygonExtrude.tsx @@ -0,0 +1,62 @@ +// @ts-nocheck +// @ts-ignore +import { Scene, Source } from '@antv/l7'; +import { PolygonLayer } from '@antv/l7-layers'; +import { GaodeMap } from '@antv/l7-maps'; +import * as React from 'react'; + +export default class Demo extends React.Component { + public async componentDidMount() { + const scene = new Scene({ + id: 'map', + map: new GaodeMap({ + center: [105, 30], + pitch: 40, + zoom: 5, + }), + }); + const layer = new PolygonLayer() + .source({ + type: 'FeatureCollection', + features: [ + { + type: 'Feature', + properties: {}, + geometry: { + type: 'Polygon', + coordinates: [ + [ + [104.4140625, 35.460669951495305], + [98.7890625, 24.206889622398023], + [111.796875, 27.371767300523047], + [104.4140625, 35.460669951495305], + ], + ], + }, + }, + ], + }) + .shape('extrude') + .color('#f00') + .size(1000000000); + + scene.on('loaded', () => { + scene.addLayer(layer); + }); + } + + public render() { + return ( +
+ ); + } +} diff --git a/stories/layerbuild/components/PolygonOcean.tsx b/stories/layerbuild/components/PolygonOcean.tsx new file mode 100644 index 0000000000..3bd8663ea8 --- /dev/null +++ b/stories/layerbuild/components/PolygonOcean.tsx @@ -0,0 +1,65 @@ +// @ts-nocheck +// @ts-ignore +import { Scene, Source } from '@antv/l7'; +import { PolygonLayer } from '@antv/l7-layers'; +import { GaodeMap } from '@antv/l7-maps'; +import * as React from 'react'; + +export default class Demo extends React.Component { + public async componentDidMount() { + const scene = new Scene({ + id: 'map', + map: new GaodeMap({ + center: [120, 30], + pitch: 0, + zoom: 2, + }), + }); + const layer = new PolygonLayer() + .source({ + type: 'FeatureCollection', + features: [ + { + type: 'Feature', + properties: {}, + geometry: { + type: 'Polygon', + coordinates: [ + [ + [104.4140625, 35.460669951495305], + [98.7890625, 24.206889622398023], + [111.796875, 27.371767300523047], + [104.4140625, 35.460669951495305], + ], + ], + }, + }, + ], + }) + .shape('ocean') + .animate(true) + .color('#f00') + .style({ + watercolor: '#6D99A8', + }); + + scene.on('loaded', () => { + scene.addLayer(layer); + }); + } + + public render() { + return ( +
+ ); + } +} diff --git a/stories/layerbuild/components/PolygonTile.tsx b/stories/layerbuild/components/PolygonTile.tsx new file mode 100644 index 0000000000..d2c34fbacf --- /dev/null +++ b/stories/layerbuild/components/PolygonTile.tsx @@ -0,0 +1,60 @@ +// @ts-nocheck +// @ts-ignore +import { Scene, Source } from '@antv/l7'; +import { PolygonLayer } from '@antv/l7-layers'; +import { GaodeMap } from '@antv/l7-maps'; +import * as React from 'react'; + +export default class Demo extends React.Component { + public async componentDidMount() { + const scene = new Scene({ + id: 'map', + stencil: true, + map: new GaodeMap({ + center: [110.19382669582967, 30.258134], + pitch: 0, + zoom: 4, + }), + }); + + const layer = new PolygonLayer({ + featureId: 'COLOR', + sourceLayer: 'ecoregions2', // woods hillshade contour ecoregions ecoregions2 city + workerEnabled: true, + }); + layer + .source( + 'http://ganos.oss-cn-hangzhou.aliyuncs.com/m2/rs_l7/{z}/{x}/{y}.pbf', + { + parser: { + type: 'mvt', + tileSize: 256, + zoomOffset: 0, + maxZoom: 9, + extent: [-180, -85.051129, 179, 85.051129], + }, + }, + ) + .color('COLOR') + .active(true); + + scene.on('loaded', () => { + scene.addLayer(layer); + }); + } + + public render() { + return ( +
+ ); + } +} diff --git a/stories/layerbuild/components/PolygonWater.tsx b/stories/layerbuild/components/PolygonWater.tsx new file mode 100644 index 0000000000..8c99702a48 --- /dev/null +++ b/stories/layerbuild/components/PolygonWater.tsx @@ -0,0 +1,66 @@ +// @ts-nocheck +// @ts-ignore +import { Scene, Source } from '@antv/l7'; +import { PolygonLayer } from '@antv/l7-layers'; +import { GaodeMap } from '@antv/l7-maps'; +import * as React from 'react'; + +export default class Demo extends React.Component { + public async componentDidMount() { + const scene = new Scene({ + id: 'map', + map: new GaodeMap({ + center: [120, 30], + pitch: 0, + zoom: 2, + }), + }); + const layer = new PolygonLayer() + .source({ + type: 'FeatureCollection', + features: [ + { + type: 'Feature', + properties: {}, + geometry: { + type: 'Polygon', + coordinates: [ + [ + [104.4140625, 35.460669951495305], + [98.7890625, 24.206889622398023], + [111.796875, 27.371767300523047], + [104.4140625, 35.460669951495305], + ], + ], + }, + }, + ], + }) + .shape('water') + .color('#1E90FF') + .style({ + speed: 0.4, + // waterTexture: 'https://gw.alipayobjects.com/mdn/rms_816329/afts/img/A*EojwT4VzSiYAAAAAAAAAAAAAARQnAQ' + }) + .animate(true); + + scene.on('loaded', () => { + scene.addLayer(layer); + }); + } + + public render() { + return ( +
+ ); + } +} diff --git a/stories/layerbuild/components/RasterDataTile.tsx b/stories/layerbuild/components/RasterDataTile.tsx new file mode 100644 index 0000000000..99d765cf38 --- /dev/null +++ b/stories/layerbuild/components/RasterDataTile.tsx @@ -0,0 +1,104 @@ +// @ts-nocheck +// @ts-ignore +import { Scene, Source } from '@antv/l7'; +import { RasterLayer } from '@antv/l7-layers'; +import { Map } from '@antv/l7-maps'; +import * as React from 'react'; + +export default class Demo extends React.Component { + public async componentDidMount() { + const scene = new Scene({ + id: 'map', + map: new Map({ + center: [105.732421875, 32.24997445586331], + pitch: 0, + style: 'dark', + zoom: 2, + }), + }); + + const canvas = document.createElement('canvas'); + canvas.width = 256; + canvas.height = 256; + const ctx = canvas.getContext('2d'); + + scene.on('loaded', () => { + const layer = new RasterLayer(); + layer + .source( + // 'http://webst01.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}', + // 'https://api.mapbox.com/raster/v1/mapbox.mapbox-terrain-dem-v1/{zoom}/{x}/{y}.pngraw?sku=YOUR_MAPBOX_SKU_TOKEN&access_token=pk.eyJ1IjoiMTg5Njk5NDg2MTkiLCJhIjoiY2s5OXVzdHlzMDVneDNscDVjdzVmeXl0dyJ9.81SQ5qaJS0xExYLbDZAGpQ', + 'https://api.mapbox.com/v4/mapbox.terrain-rgb/{z}/{x}/{y}.pngraw?access_token=pk.eyJ1IjoiMTg5Njk5NDg2MTkiLCJhIjoiY2s5OXVzdHlzMDVneDNscDVjdzVmeXl0dyJ9.81SQ5qaJS0xExYLbDZAGpQ', + // 'https://s2downloads.eox.at/demo/EOxCloudless/2019/rgb/{z}/{y}/{x}.tif', + // 'http://rd1yhmrzc.hn-bkt.clouddn.com/Mapnik/{z}/{x}/{y}.png', + { + parser: { + type: 'rasterTile', + dataType: 'arraybuffer', + tileSize: 256, + zoomOffset: 0, + extent: [-180, -85.051129, 179, 85.051129], + minZoom: 0, + format: async (data: any) => { + const blob: Blob = new Blob([new Uint8Array(data)], { + type: 'image/png', + }); + const img = await createImageBitmap(blob); + ctx.clearRect(0, 0, 256, 256); + ctx.drawImage(img, 0, 0, 256, 256); + let imgData = ctx.getImageData(0, 0, 256, 256).data; + let arr = []; + for (let i = 0; i < imgData.length; i += 4) { + const R = imgData[i]; + const G = imgData[i + 1]; + const B = imgData[i + 2]; + const d = -10000 + (R * 256 * 256 + G * 256 + B) * 0.1; + arr.push(d); + } + return { + rasterData: arr, + width: 256, + height: 256, + }; + }, + }, + }, + ) + .style({ + domain: [0, 1014], + clampLow: true, + rampColors: { + colors: [ + '#f7fcf5', + '#e5f5e0', + '#c7e9c0', + '#a1d99b', + '#74c476', + '#41ab5d', + '#238b45', + '#006d2c', + '#00441b', + ], + positions: [0, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 1.0], + }, + }); + + scene.addLayer(layer); + }); + } + + public render() { + return ( +
+ ); + } +} diff --git a/stories/layerbuild/components/RasterImageTile.tsx b/stories/layerbuild/components/RasterImageTile.tsx new file mode 100644 index 0000000000..8c39c149f8 --- /dev/null +++ b/stories/layerbuild/components/RasterImageTile.tsx @@ -0,0 +1,51 @@ +// @ts-nocheck +// @ts-ignore +import { Scene, Source } from '@antv/l7'; +import { RasterLayer } from '@antv/l7-layers'; +import { Map } from '@antv/l7-maps'; +import * as React from 'react'; + +export default class Demo extends React.Component { + public async componentDidMount() { + const scene = new Scene({ + id: 'map', + map: new Map({ + center: [105.732421875, 32.24997445586331], + pitch: 0, + style: 'dark', + zoom: 2, + }), + }); + + scene.on('loaded', () => { + const layer = new RasterLayer({}).source( + 'http://webst01.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}', + { + parser: { + type: 'rasterTile', + tileSize: 256, + zoomOffset: 0, + updateStrategy: 'overlap', + }, + }, + ); + + scene.addLayer(layer); + }); + } + + public render() { + return ( +
+ ); + } +} diff --git a/stories/layerbuild/components/RasterLayer.tsx b/stories/layerbuild/components/RasterLayer.tsx new file mode 100644 index 0000000000..dcb61e481c --- /dev/null +++ b/stories/layerbuild/components/RasterLayer.tsx @@ -0,0 +1,92 @@ +// @ts-nocheck +// @ts-ignore +import { Scene, Source } from '@antv/l7'; +import { ImageLayer, RasterLayer } from '@antv/l7-layers'; +import { GaodeMap } from '@antv/l7-maps'; +import * as React from 'react'; +import * as GeoTIFF from 'geotiff'; + +async function getTiffData() { + const response = await fetch( + 'https://gw.alipayobjects.com/os/rmsportal/XKgkjjGaAzRyKupCBiYW.dat', + ); + const arrayBuffer = await response.arrayBuffer(); + const tiff = await GeoTIFF.fromArrayBuffer(arrayBuffer); + const image = await tiff.getImage(); + const width = image.getWidth(); + const height = image.getHeight(); + const values = await image.readRasters(); + return { + data: values[0], + width, + height, + min: 0, + max: 8000, + }; +} + +export default class Demo extends React.Component { + public async componentDidMount() { + const scene = new Scene({ + id: 'map', + map: new GaodeMap({ + center: [121.268, 30.3628], + zoom: 3, + }), + }); + + async function addLayer() { + const tiffdata = await getTiffData(); + + const layer = new RasterLayer({}); + layer + .source(tiffdata.data, { + parser: { + type: 'raster', + width: tiffdata.width, + height: tiffdata.height, + min: 0, + max: 80, + extent: [73.482190241, 3.82501784112, 135.106618732, 57.6300459963], + }, + }) + .style({ + heightRatio: 100, + opacity: 0.8, + rampColors: { + colors: [ + '#FF4818', + '#F7B74A', + '#FFF598', + '#91EABC', + '#2EA9A1', + '#206C7C', + ].reverse(), + positions: [0, 0.2, 0.4, 0.6, 0.8, 1.0], + }, + }); + return layer; + } + + const layer = await addLayer(); + + scene.on('loaded', () => { + scene.addLayer(layer); + }); + } + + public render() { + return ( +
+ ); + } +} diff --git a/stories/layerbuild/components/SourceTest.tsx b/stories/layerbuild/components/SourceTest.tsx new file mode 100644 index 0000000000..3f4ff29cfe --- /dev/null +++ b/stories/layerbuild/components/SourceTest.tsx @@ -0,0 +1,415 @@ +// @ts-ignore +import { Scene, Source } from '@antv/l7'; +import { PointLayer } from '@antv/l7-layers'; +import { GaodeMap } from '@antv/l7-maps'; +import * as React from 'react'; + +export default class Demo extends React.Component { + private scene: Scene; + public async componentDidMount() { + const scene = new Scene({ + id: 'map', + map: new GaodeMap({ + center: [110.19382669582967, 30.258134], + pitch: 0, + zoom: 2, + }), + }); + this.scene = scene; + + // 检测方案 + // https://www.yuque.com/antv/l7/cpkdtl + // this.test1(); + // this.test2(); + // this.test3(); + // this.test4(); + // this.test5(); + // this.test6(); + // this.test7(); + // this.test8(); + // this.test9(); + this.test10(); + } + + private test1() { + const layer = new PointLayer(); + layer.source( + [ + { + lng: 120, + lat: 30, + }, + ], + { + parser: { + type: 'json', + x: 'lng', + y: 'lat', + }, + }, + ); + layer + .shape('circle') + .size(10) + .color('#f00'); + this.scene.addLayer(layer); + } + + private test2() { + const source = new Source( + [ + { + lng: 120, + lat: 30, + }, + ], + { + parser: { + type: 'json', + x: 'lng', + y: 'lat', + }, + }, + ); + const layer = new PointLayer(); + layer.source(source); + layer + .shape('circle') + .size(10) + .color('#f00'); + this.scene.addLayer(layer); + } + + private test3() { + const source = new Source( + [ + { + lng: 120, + lat: 30, + }, + ], + { + parser: { + type: 'json', + x: 'lng', + y: 'lat', + }, + }, + ); + source.on('sourceUpdate', () => { + const layer = new PointLayer(); + layer.source(source); + layer + .shape('circle') + .size(10) + .color('#f00'); + this.scene.addLayer(layer); + }); + } + + private test4() { + const layer = new PointLayer(); + layer.source( + [ + { + lng: 120, + lat: 30, + }, + ], + { + parser: { + type: 'json', + x: 'lng', + y: 'lat', + }, + }, + ); + layer + .shape('circle') + .size(10) + .color('#f00'); + layer.setData([ + { + lng: 120, + lat: 30, + }, + { + lng: 130, + lat: 30, + }, + ]); + this.scene.addLayer(layer); + } + + private test5() { + const layer = new PointLayer(); + layer.source( + [ + { + lng: 120, + lat: 30, + }, + ], + { + parser: { + type: 'json', + x: 'lng', + y: 'lat', + }, + }, + ); + layer + .shape('circle') + .size(10) + .color('#f00'); + this.scene.addLayer(layer); + setTimeout(() => { + layer.setData([ + { + lng: 120, + lat: 30, + }, + { + lng: 130, + lat: 30, + }, + ]); + }, 2000); + } + + private test6() { + const source = new Source( + [ + { + lng: 120, + lat: 30, + }, + { + lng: 130, + lat: 30, + }, + ], + { + parser: { + type: 'json', + x: 'lng', + y: 'lat', + }, + }, + ); + const layer = new PointLayer(); + layer.source( + [ + { + lng: 120, + lat: 30, + }, + ], + { + parser: { + type: 'json', + x: 'lng', + y: 'lat', + }, + }, + ); + layer + .shape('circle') + .size(10) + .color('#f00'); + layer.source(source); + this.scene.addLayer(layer); + } + + private test7() { + const source = new Source( + [ + { + lng: 120, + lat: 30, + }, + { + lng: 130, + lat: 30, + }, + ], + { + parser: { + type: 'json', + x: 'lng', + y: 'lat', + }, + }, + ); + const layer = new PointLayer(); + layer.source( + [ + { + lng: 120, + lat: 30, + }, + ], + { + parser: { + type: 'json', + x: 'lng', + y: 'lat', + }, + }, + ); + layer + .shape('circle') + .size(10) + .color('#f00'); + this.scene.addLayer(layer); + setTimeout(() => { + layer.source(source); + this.scene.render(); + }, 2000); + } + + private test8() { + const source = new Source( + [ + { + lng: 120, + lat: 30, + }, + { + lng: 130, + lat: 30, + }, + ], + { + parser: { + type: 'json', + x: 'lng', + y: 'lat', + }, + }, + ); + + const layer = new PointLayer(); + layer.source( + [ + { + lng: 120, + lat: 30, + }, + ], + { + parser: { + type: 'json', + x: 'lng', + y: 'lat', + }, + }, + ); + layer + .shape('circle') + .size(10) + .color('#f00'); + source.on('sourceUpdate', () => { + layer.source(source); + }); + this.scene.addLayer(layer); + } + + private test9() { + const source = new Source( + [ + { + lng: 120, + lat: 30, + }, + { + lng: 130, + lat: 30, + }, + ], + { + parser: { + type: 'json', + x: 'lng', + y: 'lat', + }, + }, + ); + + const layer = new PointLayer(); + layer.source( + [ + { + lng: 120, + lat: 30, + }, + ], + { + parser: { + type: 'json', + x: 'lng', + y: 'lat', + }, + }, + ); + layer + .shape('circle') + .size(10) + .color('#f00'); + source.on('sourceUpdate', () => { + setTimeout(() => { + layer.source(source); + }, 2000); + }); + this.scene.addLayer(layer); + } + + private test10() { + const source = new Source( + [ + { + lng: 120, + lat: 30, + }, + { + lng: 130, + lat: 30, + }, + ], + { + parser: { + type: 'json', + x: 'lng', + y: 'lat', + }, + }, + ); + + const layer = new PointLayer(); + layer + .shape('circle') + .size(10) + .color('#f00'); + source.on('sourceUpdate', () => { + setTimeout(() => { + layer.source(source); + }, 2000); + }); + this.scene.addLayer(layer); + } + + public render() { + return ( +
+ ); + } +} diff --git a/stories/layerbuild/components/Sprite.tsx b/stories/layerbuild/components/Sprite.tsx new file mode 100644 index 0000000000..d655b1e8e4 --- /dev/null +++ b/stories/layerbuild/components/Sprite.tsx @@ -0,0 +1,53 @@ +// @ts-nocheck +// @ts-ignore +import { Scene, Source } from '@antv/l7'; +import { GeometryLayer } from '@antv/l7-layers'; +import { GaodeMap } from '@antv/l7-maps'; +import * as React from 'react'; + +export default class Demo extends React.Component { + public async componentDidMount() { + const scene = new Scene({ + id: 'map', + map: new GaodeMap({ + pitch: 90, + style: 'dark', + center: [120, 30], + zoom: 6, + }), + }); + + scene.on('loaded', () => { + const layer = new GeometryLayer() + .shape('sprite') + .size(10) + .style({ + opacity: 0.3, + mapTexture: + 'https://gw.alipayobjects.com/mdn/rms_816329/afts/img/A*w2SFSZJp4nIAAAAAAAAAAAAAARQnAQ', // rain + center: [120, 30], + spriteCount: 120, + spriteRadius: 10, + spriteTop: 2500000, + spriteUpdate: 20000, + spriteScale: 0.6, + }); + scene.addLayer(layer); + }); + } + + public render() { + return ( +
+ ); + } +} diff --git a/stories/layerbuild/components/Wind.tsx b/stories/layerbuild/components/Wind.tsx new file mode 100644 index 0000000000..314a7f58f5 --- /dev/null +++ b/stories/layerbuild/components/Wind.tsx @@ -0,0 +1,68 @@ +// @ts-nocheck +// @ts-ignore +import { Scene, Source } from '@antv/l7'; +import { WindLayer } from '@antv/l7-layers'; +import { GaodeMap } from '@antv/l7-maps'; +import * as React from 'react'; + +export default class Demo extends React.Component { + public async componentDidMount() { + const scene = new Scene({ + id: 'map', + map: new GaodeMap({ + center: [105.732421875, 32.24997445586331], + pitch: 0, + style: 'dark', + zoom: 2, + }), + }); + + scene.on('loaded', () => { + const layer = new WindLayer({}); + layer + .source( + 'https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*wcU8S5xMEDYAAAAAAAAAAAAAARQnAQ', + { + parser: { + type: 'image', + extent: [-180, -85, 180, 85], + }, + }, + ) + .animate(true) + .style({ + uMin: -21.32, + uMax: 26.8, + vMin: -21.57, + vMax: 21.42, + numParticles: 35535, + fadeOpacity: 0.996, + sizeScale: 1.2, + rampColors: { + 0.0: '#c6dbef', + 0.1: '#9ecae1', + 0.2: '#6baed6', + 0.3: '#4292c6', + 0.4: '#2171b5', + 0.5: '#084594', + }, + }); + scene.addLayer(layer); + }); + } + + public render() { + return ( +
+ ); + } +} diff --git a/stories/layerbuild/map.stories.tsx b/stories/layerbuild/map.stories.tsx new file mode 100644 index 0000000000..c1f6713b52 --- /dev/null +++ b/stories/layerbuild/map.stories.tsx @@ -0,0 +1,111 @@ +import { storiesOf } from '@storybook/react'; +import * as React from 'react'; + +import PointFill from './components/Points'; +import PointExtrue from './components/PointsExtrude'; +import PointText from './components/PointsText'; +import PointSimple from './components/PointsSimple'; +import PointsNormal from './components/PointsNormal'; +import PointsFillImage from './components/PointsFillImage'; +import PointImage from './components/PointsImage'; +import PointIconFont from './components/PointsIconFont'; +import PointRader from './components/PointsRadar'; +import PointTile from './components/PointsTile'; +import PointsTextTile from './components/PointsTextTile'; +import PointEarthFill from './components/PointsEarthFill'; +import PointEarthExtrude from './components/PointsEarthExtrude'; + +import Line from './components/Line'; +import LineArc from './components/LineArc'; +import LineArc3d from './components/LineArc3d'; +import LineLinear from './components/LineLinear'; +import LineSimple from './components/LineSimple'; +import LineHalf from './components/LineHalf'; +import LineGreatCircle from './components/LineGreatCircle'; +import LineWall from './components/LineWall'; +import LineEarthArc3D from './components/LineEarthArc3D'; +import LineTile from './components/LineTile'; + +import PolygonFill from './components/Polygon'; +import PolygonExtrude from './components/PolygonExtrude'; +import PolygonOcean from './components/PolygonOcean'; +import PolygonWater from './components/PolygonWater'; +import PolygonTile from './components/PolygonTile'; + +import Heatmap from './components/Heatmap'; +import Heatmap3d from './components/Heatmap3d'; +import HeatmapGrid from './components/HeatmapGrid'; +import HeatmapGrid3d from './components/HeatmapGrid3d'; +import HeatmapHexagon from './components/HeatmapHexagon'; + +import CityBuilding from './components/CityBuilding'; + +import ImageLayer from './components/ImageLayer'; + +import RasterLayer from './components/RasterLayer'; + +import Billboard from './components/Billboard'; +import Sprite from './components/Sprite'; +import Plane from './components/Plane'; + +import Wind from './components/Wind'; + +import RasterImageTile from './components/RasterImageTile'; +import RasterDataTile from './components/RasterDataTile'; + +import SourceTest from './components/SourceTest'; + +storiesOf('图层渲染流程改造', module) + .add('pointFill', () => ) + .add('PointExtrue', () => ) + .add('PointText', () => ) + .add('PointSimple', () => ) + .add('PointsNormal', () => ) + .add('PointsFillImage', () => ) + .add('PointImage', () => ) + .add('PointIconFont', () => ) + .add('PointRader', () => ) + .add('PointEarthFill', () => ) + .add('PointEarthExtrude', () => ) + + .add('Line', () => ) + .add('LineArc', () => ) + .add('LineArc3d', () => ) + .add('LineLinear', () => ) + .add('LineSimple', () => ) + .add('LineHalf', () => ) + .add('LineGreatCircle', () => ) + .add('LineWall', () => ) + .add('LineEarthArc3D', () => ) + + .add('PolygonFill', () => ) + .add('PolygonExtrude', () => ) + .add('PolygonOcean', () => ) + .add('PolygonWater', () => ) + + .add('Heatmap', () => ) + .add('Heatmap3d', () => ) + .add('HeatmapGrid', () => ) + .add('HeatmapGrid3d', () => ) + .add('HeatmapHexagon', () => ) + + .add('CityBuilding', () => ) + + .add('ImageLayer', () => ) + + .add('RasterLayer', () => ) + + .add('Billboard', () => ) + .add('Sprite', () => ) + .add('Plane', () => ) + + .add('Wind', () => ) + + .add('TilePoint', () => ) + .add('TileLine', () => ) + .add('TilePolygon', () => ) + .add('TilePointText', () => ) + .add('TileRasterImage', () => ) + .add('TileRasterData', () => ) + + .add('SourceTest', () => ) diff --git a/tsconfig.json b/tsconfig.json index 334c8ec166..ad538ddb9c 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -31,7 +31,7 @@ "@antv/l7-utils": ["packages/utils/src"], "@antv/l7": ["packages/l7/src"], "*": ["packages", "typings/*"] - }, + } }, "awesomeTypescriptLoaderOptions": { "useBabel": true, @@ -40,5 +40,4 @@ }, "include": ["packages"], "exclude": ["node_modules", "packages/**/dist"] - } diff --git a/tslint.json b/tslint.json index 215422356f..4bb984e1ef 100644 --- a/tslint.json +++ b/tslint.json @@ -19,7 +19,8 @@ "object-literal-sort-keys": false, "no-implicit-dependencies": [true, "dev"], "interface-over-type-literal": false, - "no-this-assignment": false + "no-this-assignment": false, + "no-submodule-imports": false }, "globals": { "AMap": true