feat: 渲染流程异步改造、部分支持 worker (#1224)

* 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 <yunji.me@outlook.com>
This commit is contained in:
YiQianYao 2022-08-02 19:05:27 +08:00 committed by GitHub
parent 1a78586ee2
commit 6a04210de6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
179 changed files with 6567 additions and 1691 deletions

5
.eslintignore Normal file
View File

@ -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

View File

@ -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() {

View File

@ -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__',
]
: []),
],
};
};

View File

@ -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: '' },
};
},
};
}

View File

@ -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,
}),
],
},
];

View File

@ -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,
// }),
],
},
];

View File

@ -6,7 +6,7 @@
"demos": [
{
"filename": "amap.js",
"title": "高德底图组件",
"title": "高德底图组件"
},
{
"filename": "mapbox.js",

View File

@ -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,

View File

@ -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: {

View File

@ -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 = `
<div class="progress_bg" style="
height: 6px;
border-radius: 3px;
overflow: hidden;
background-color:#f2f2f2;">
</div>
<div class="progress_btn" style="
width: 20px;
height: 20px;
border-radius: 10px;
position: absolute;
background:#ccc;
left: 0px;
margin-left: -10px; top:-9px;
cursor: pointer;
box-sizing:border-box;
">
<div class="text" style="transform:translateY(-30px); color: #fff;user-select:none">00:00</div>
</div>
`;
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);
}

View File

@ -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 => {

View File

@ -20,7 +20,7 @@ scene.on('loaded', () => {
const layer = new PolygonLayer({})
.source(data)
.scale('density', {
type: 'quantize'
type: 'quantile'
})
.color(
'density', color

View File

@ -23,7 +23,8 @@ scene.on('loaded', () => {
type: 'mvt',
tileSize: 256,
zoomOffset: 0,
maxZoom: 9
maxZoom: 9,
extent: [ -180, -85.051129, 179, 85.051129 ]
}
}
)

View File

@ -23,7 +23,8 @@ scene.on('loaded', () => {
type: 'mvt',
tileSize: 256,
zoomOffset: 0,
maxZoom: 9
maxZoom: 9,
extent: [ -180, -85.051129, 179, 85.051129 ]
}
}
)

View File

@ -23,7 +23,8 @@ scene.on('loaded', () => {
type: 'mvt',
tileSize: 256,
zoomOffset: 0,
maxZoom: 9
maxZoom: 9,
extent: [ -180, -85.051129, 179, 85.051129 ]
}
}
)

View File

@ -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": {}
}

View File

@ -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"

View File

@ -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<IModelInitializationOptions>,
): IModel;
): Promise<IModel>;
createAttrubutes(
options: ILayerModelInitializationOptions &
Partial<IModelInitializationOptions>,
@ -555,6 +565,8 @@ export interface ILayerConfig {
* layer point text iconfont
*/
iconfont: boolean;
workerEnabled?: boolean;
onHover(pickedFeature: IPickedFeature): void;
onClick(pickedFeature: IPickedFeature): void;
}

View File

@ -216,6 +216,11 @@ export interface IStyleAttributeService {
};
elements: IElements;
};
createAttributesAndIndicesAscy(
encodedFeatures: IEncodeFeature[],
segmentNumber?: number,
workerOptions?: any,
): Promise<any>;
/**
* feature range
*/

View File

@ -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,
};
});
}
}

View File

@ -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() {

View File

@ -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<string, any>,
): 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];

View File

@ -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",

View File

@ -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 };

View File

@ -6,4 +6,4 @@
"baseUrl": "./"
},
"include": ["./src"]
}
}

View File

@ -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",

View File

@ -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() {

View File

@ -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 {

View File

@ -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) {

View File

@ -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 {

View File

@ -6,10 +6,13 @@ export default class CanvasLayer extends BaseLayer<ICanvasLayerStyleOptions> {
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 {

View File

@ -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({

View File

@ -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() {

View File

@ -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<ChildLayerStyleOptions = {}>
}
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<ChildLayerStyleOptions = {}>
// @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<ChildLayerStyleOptions = {}>
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<ChildLayerStyleOptions = {}>
* 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<ChildLayerStyleOptions = {}>
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<ChildLayerStyleOptions = {}>
}
public clearModels() {
this.models.forEach((model) => model.destroy());
this.layerModel.clearModels();
this.layerModel?.clearModels();
this.models = [];
}
@ -1041,7 +1043,7 @@ export default class BaseLayer<ChildLayerStyleOptions = {}>
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<ChildLayerStyleOptions = {}>
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<ChildLayerStyleOptions = {}>
public buildLayerModel(
options: ILayerModelInitializationOptions &
Partial<IModelInitializationOptions>,
): IModel {
): Promise<IModel> {
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<ChildLayerStyleOptions = {}>
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<ChildLayerStyleOptions = {}>
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');

View File

@ -514,10 +514,10 @@ export default class BaseModel<ChildLayerStyleOptions = {}>
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() {

View File

@ -50,6 +50,8 @@ export interface ILineLayerStyleOptions {
rampColors?: IColorRamp;
featureId?: string;
sourceLayer?: string;
enablePicking?: boolean;
workerEnabled?: boolean;
}
export interface IPointLayerStyleOptions {

View File

@ -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,

View File

@ -24,7 +24,10 @@ export default class EarthLayer extends BaseLayer<IEarthLayerStyleOptions> {
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<IEarthLayerStyleOptions> {
if (this.layerModel && this.layerModel.setEarthTime) {
this.layerModel.setEarthTime(time);
} else {
console.error('请在 scene loaded 之后执行该方法!');
console.warn('请在 scene loaded 之后执行该方法!');
}
}

View File

@ -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() {

View File

@ -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() {

View File

@ -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() {

View File

@ -8,10 +8,13 @@ export default class HeatMapLayer extends BaseLayer<IHeatMapLayerStyleOptions> {
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<IHeatMapLayerStyleOptions> {
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) =>

View File

@ -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({

View File

@ -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;

View File

@ -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,

View File

@ -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({

View File

@ -6,10 +6,13 @@ export default class ImageLayer extends BaseLayer<IImageLayerStyleOptions> {
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 {

View File

@ -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() {

View File

@ -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() {

View File

@ -8,10 +8,13 @@ export default class LineLayer extends BaseLayer<ILineLayerStyleOptions> {
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<ILineLayerStyleOptions> {
wall: {},
arc3d: { blend: 'additive' },
arc: { blend: 'additive' },
arcmini: { blend: 'additive' },
greatcircle: { blend: 'additive' },
vectorline: {},
tileLine: {},

View File

@ -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() {

View File

@ -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;

View File

@ -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]];
},
},
});
}
}

View File

@ -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;

View File

@ -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({

View File

@ -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([]);
});
}
/**

View File

@ -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,

View File

@ -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: '',
};
}
}

View File

@ -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() {

View File

@ -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({

View File

@ -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() {

View File

@ -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({

View File

@ -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;
}
}

View File

@ -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));
}
}

View File

@ -7,10 +7,13 @@ export default class MaskLayer extends BaseLayer<IMaskLayerStyleOptions> {
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 {

View File

@ -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() {

View File

@ -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变化

View File

@ -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<IMapService>(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);
});
// 检测数据是否需要更新

View File

@ -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;
});
}

View File

@ -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,

View File

@ -8,10 +8,14 @@ export default class PointLayer extends BaseLayer<IPointLayerStyleOptions> {
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<IPointLayerStyleOptions> {
fill: { blend: 'normal' },
extrude: {},
image: {},
icon: {},
text: {
blend: 'normal',
},
@ -84,7 +87,6 @@ export default class PointLayer extends BaseLayer<IPointLayerStyleOptions> {
'simplePoint',
'extrude',
'text',
'icon',
'vectorpoint',
'tile',
'earthFill',
@ -93,9 +95,7 @@ export default class PointLayer extends BaseLayer<IPointLayerStyleOptions> {
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<IPointLayerStyleOptions> {
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<IPointLayerStyleOptions> {
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';
}
}

View File

@ -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();

View File

@ -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() {

View File

@ -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();

View File

@ -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];
},

View File

@ -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() {

View File

@ -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,
});
}
}

View File

@ -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;

View File

@ -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,

View File

@ -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() {

View File

@ -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() {

View File

@ -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() {

View File

@ -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 = [];
});
}
}

View File

@ -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() {

View File

@ -8,10 +8,13 @@ export default class PolygonLayer extends BaseLayer<IPolygonLayerStyleOptions> {
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 {

View File

@ -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() {

View File

@ -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,
};
}
}

View File

@ -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() {

View File

@ -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,
};
}
}

View File

@ -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() {

View File

@ -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<IRaterLayerStyleOptions> {
// 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]];
// },
// },
// });
// }
// }

View File

@ -6,10 +6,13 @@ export default class RaterLayer extends BaseLayer<IRasterLayerStyleOptions> {
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 {

View File

@ -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 {

View File

@ -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<IRasterLayerStyleOptions> {
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]];
},
},
});
}
}

View File

@ -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,

View File

@ -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();

View File

@ -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);

View File

@ -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],

View File

@ -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() {

View File

@ -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() {

Some files were not shown because too many files have changed in this diff Show More