Merge pull request #136 from antvis/example

新增文本渲染支持
This commit is contained in:
@thinkinggis 2019-12-30 19:15:07 +08:00 committed by GitHub
commit f22b9ba250
52 changed files with 6667 additions and 6919 deletions

View File

@ -1,8 +1,8 @@
import path from 'path'; import path from 'path';
import alias from '@rollup/plugin-alias'; import alias from '@rollup/plugin-alias';
import json from '@rollup/plugin-json'; import json from '@rollup/plugin-json';
import resolve from 'rollup-plugin-node-resolve'; import resolve from 'sharp';
import commonjs from 'rollup-plugin-commonjs'; import commonjs from '@rollup/plugin-commons';
import { terser } from 'rollup-plugin-terser'; import { terser } from 'rollup-plugin-terser';
import analyze from 'rollup-plugin-analyzer'; import analyze from 'rollup-plugin-analyzer';
import babel from 'rollup-plugin-babel'; import babel from 'rollup-plugin-babel';

View File

@ -6,33 +6,33 @@
"demos": [ "demos": [
{ {
"filename": "column_dark.js", "filename": "column_dark.js",
"title": "", "title": "3D柱图深色",
"screenshot": "https://gw.alipayobjects.com/mdn/antv_site/afts/img/A*7COqR4wCc6QAAAAAAAAAAABkARQnAQ" "screenshot": "https://gw.alipayobjects.com/mdn/antv_site/afts/img/A*7COqR4wCc6QAAAAAAAAAAABkARQnAQ"
}, },
{ {
"filename": "arcCircle.js", "filename": "arcCircle.js",
"title": "", "title": "弧线地图",
"screenshot": "https://gw.alipayobjects.com/mdn/antv_site/afts/img/A*6Qm_QY69sBMAAAAAAAAAAABkARQnAQ" "screenshot": "https://gw.alipayobjects.com/mdn/antv_site/afts/img/A*6Qm_QY69sBMAAAAAAAAAAABkARQnAQ"
}, },
{ {
"filename": "bus_dark.js", "filename": "bus_dark.js",
"title": "", "title": "公交线路深色",
"screenshot": "https://gw.alipayobjects.com/mdn/antv_site/afts/img/A*j-P8RaJMEvAAAAAAAAAAAABkARQnAQ" "screenshot": "https://gw.alipayobjects.com/mdn/antv_site/afts/img/A*j-P8RaJMEvAAAAAAAAAAAABkARQnAQ"
}, },
{ {
"filename": "light.js", "filename": "light.js",
"title": "", "title": "蜂窝图3D",
"screenshot": "https://gw.alipayobjects.com/mdn/antv_site/afts/img/A*SLcGSbvZoEwAAAAAAAAAAABkARQnAQ" "screenshot": "https://gw.alipayobjects.com/mdn/antv_site/afts/img/A*SLcGSbvZoEwAAAAAAAAAAABkARQnAQ"
}, },
{ {
"filename": "point.js", "filename": "point.js",
"title": "", "title": "海量点",
"screenshot": "https://gw.alipayobjects.com/mdn/antv_site/afts/img/A*ypZCT6pqv84AAAAAAAAAAABkARQnAQ" "screenshot": "https://gw.alipayobjects.com/mdn/antv_site/afts/img/A*ypZCT6pqv84AAAAAAAAAAABkARQnAQ"
} }
, ,
{ {
"filename": "normal.js", "filename": "normal.js",
"title": "", "title": "亮度图",
"screenshot": "https://gw.alipayobjects.com/mdn/antv_site/afts/img/A*xr8BQouXGvoAAAAAAAAAAABkARQnAQ" "screenshot": "https://gw.alipayobjects.com/mdn/antv_site/afts/img/A*xr8BQouXGvoAAAAAAAAAAABkARQnAQ"
} }
] ]

View File

@ -1,6 +1,4 @@
--- ---
title: Gallery title: Featured
order: 0 order: 0
redirect_from:
- /en/examples
--- ---

View File

@ -1,6 +1,4 @@
--- ---
title: Gallery title: 官方精品库
order: 0 order: 0
redirect_from:
- /zh/examples
--- ---

View File

@ -0,0 +1,7 @@
---
title: Gallery
order: -1
icon: other
redirect_from:
- /en/examples
---

View File

@ -0,0 +1,7 @@
---
title: 所有图表
order: -1
icon: other
redirect_from:
- /zh/examples
---

View File

@ -1,42 +0,0 @@
import { Scene, LineLayer } from '@antv/l7';
import { GaodeMap } from '@antv/l7-maps';
const scene = new Scene({
id: 'map',
map: new GaodeMap({
pitch: 0,
style: 'light',
center: [ 104.117492, 36.492696 ],
zoom: 3.89
})
});
fetch(
'https://gw.alipayobjects.com/os/basement_prod/9f6afbcd-3aec-4a26-bd4a-2276d3439e0d.json'
)
.then(res => res.json())
.then(data => {
const layer = new LineLayer({})
.source(data)
.scale('value', {
type: 'quantile'
})
.size('value', [ 0.5, 1, 1.5, 2 ])
.shape('line')
.color(
'value',
[
'#0A3663',
'#1558AC',
'#3771D9',
'#4D89E5',
'#64A5D3',
'#72BED6',
'#83CED6',
'#A6E1E0',
'#B8EFE2',
'#D7F9F0'
].reverse()
);
scene.addLayer(layer);
});

View File

@ -22,8 +22,8 @@
}, { }, {
"filename": "scatter.js", "filename": "scatter.js",
"title": "定点图", "title": "气泡图动画",
"screenshot":"https://gw.alipayobjects.com/mdn/antv_site/afts/img/A*LnlmQ7sFWigAAAAAAAAAAABkARQnAQ" "screenshot":"https://gw.alipayobjects.com/mdn/antv_site/afts/img/A*L-wETZt7WHwAAAAAAAAAAABkARQnAQ"
} }

View File

@ -4,15 +4,15 @@ import { GaodeMap } from '@antv/l7-maps';
const scene = new Scene({ const scene = new Scene({
id: 'map', id: 'map',
map: new GaodeMap({ map: new GaodeMap({
style: 'light',
center: [ -121.24357, 37.58264 ],
pitch: 0, pitch: 0,
zoom: 6.45 style: 'dark',
center: [ 112, 23.69 ],
zoom: 2.5
}) })
}); });
fetch( fetch(
'https://gw.alipayobjects.com/os/basement_prod/6c4bb5f2-850b-419d-afc4-e46032fc9f94.csv' 'https://gw.alipayobjects.com/os/basement_prod/9078fd36-ce8d-4ee2-91bc-605db8315fdf.csv'
) )
.then(res => res.text()) .then(res => res.text())
.then(data => { .then(data => {
@ -25,22 +25,12 @@ fetch(
} }
}) })
.shape('circle') .shape('circle')
.size(4) .active(true)
.color('Magnitude', [ .animate(true)
'#0A3663', .size(40)
'#1558AC', .color('#ffa842')
'#3771D9',
'#4D89E5',
'#64A5D3',
'#72BED6',
'#83CED6',
'#A6E1E0',
'#B8EFE2',
'#D7F9F0'
])
.style({ .style({
opacity: 0.5, opacity: 1
strokeWidth: 0
}); });
scene.addLayer(pointLayer); scene.addLayer(pointLayer);

View File

@ -11,7 +11,7 @@
}, },
{ {
"filename": "locate.js", "filename": "locate.js",
"title": "顶点符号", "title": "精确符号",
"screenshot": "https://gw.alipayobjects.com/mdn/antv_site/afts/img/A*DgoWS7-XKdUAAAAAAAAAAABkARQnAQ" "screenshot": "https://gw.alipayobjects.com/mdn/antv_site/afts/img/A*DgoWS7-XKdUAAAAAAAAAAABkARQnAQ"
}, },
{ {

View File

@ -25,6 +25,10 @@ function pointOnCircle(angle) {
}] }]
}; };
} }
scene.on('loaded', () => {
// animateMarker(0);
});
const layer = new PointLayer() const layer = new PointLayer()
.source(pointOnCircle(0)) .source(pointOnCircle(0))
.shape('circle') .shape('circle')
@ -36,11 +40,7 @@ const layer = new PointLayer()
opacity: 1 opacity: 1
}); });
scene.addLayer(layer); scene.addLayer(layer);
function animateMarker(timestamp) { // function animateMarker(timestamp) {
layer.setData(pointOnCircle(timestamp / 1000)); // layer.setData(pointOnCircle(timestamp / 1000));
requestAnimationFrame(animateMarker); // requestAnimationFrame(animateMarker);
} // }
layer.on('inited', () => {
animateMarker(0);
});

View File

@ -1,14 +1,56 @@
import { Scene } from '@antv/l7'; import { Scene, PointLayer } from '@antv/l7';
import { GaodeMap } from '@antv/l7-maps'; import { GaodeMap } from '@antv/l7-maps';
const map = new AMap.Map('container', { window.onLoad = function() {
resizeEnable: true, // 是否监控地图容器尺寸变化 const map = new AMap.Map('map', {
zoom: 11, // 初始化地图层级 viewMode: '3D',
center: [ 116.397428, 39.90923 ] // 初始化地图中心点 pitch: 0,
}); mapStyle: 'amap://styles/darkblue',
new Scene({ center: [ 121.435159, 31.256971 ],
zoom: 14.89,
minZoom: 10
});
const scene = new Scene({
id: 'map', id: 'map',
map: new GaodeMap({ map: new GaodeMap({
mapInstance: map mapInstance: map
}) })
}); });
fetch(
'https://gw.alipayobjects.com/os/basement_prod/893d1d5f-11d9-45f3-8322-ee9140d288ae.json'
)
.then(res => res.json())
.then(data => {
const pointLayer = new PointLayer()
.source(data, {
parser: {
type: 'json',
x: 'longitude',
y: 'latitude'
}
})
.shape('name', [
'circle',
'triangle',
'square',
'pentagon',
'hexagon',
'octogon',
'hexagram',
'rhombus',
'vesica'
])
.size('unit_price', [ 10, 25 ])
.color('name', [ '#5B8FF9', '#5CCEA1', '#5D7092', '#F6BD16', '#E86452' ])
.style({
opacity: 0.3,
strokeWidth: 2
});
scene.addLayer(pointLayer);
});
};
const url = 'https://webapi.amap.com/maps?v=1.4.15&key=15cd8a57710d40c9b7c0e3cc120f1200&callback=onLoad';
const jsapi = document.createElement('script');
jsapi.charset = 'utf-8';
jsapi.src = url;
document.head.appendChild(jsapi);

View File

@ -13,6 +13,11 @@
"filename": "mapbox.js", "filename": "mapbox.js",
"title": "MapBox底图", "title": "MapBox底图",
"screenshot": "https://gw.alipayobjects.com/mdn/antv_site/afts/img/A*_SIYR50bbcoAAAAAAAAAAABkARQnAQ" "screenshot": "https://gw.alipayobjects.com/mdn/antv_site/afts/img/A*_SIYR50bbcoAAAAAAAAAAABkARQnAQ"
},
{
"filename": "amapInstance.js",
"title": "通过高德地图实例化",
"screenshot": "https://gw.alipayobjects.com/mdn/antv_site/afts/img/A*_SIYR50bbcoAAAAAAAAAAABkARQnAQ"
} }
] ]
} }

View File

@ -33,10 +33,8 @@ module.exports = {
title: { title: {
zh: '图表演示', zh: '图表演示',
en: 'Examples' en: 'Examples'
},
redirect: 'gallery/basic'
} }
// target: '_blank', }
], ],
docs: [ docs: [
{ {
@ -141,8 +139,8 @@ module.exports = {
slug: 'gallery', slug: 'gallery',
icon: 'gallery', icon: 'gallery',
title: { title: {
zh: 'Gallery', zh: '官方精品库',
en: 'Gallery' en: 'Featured'
} }
}, },
{ {

View File

@ -23,12 +23,6 @@
"@commitlint/config-conventional": "^8.1.0", "@commitlint/config-conventional": "^8.1.0",
"@rollup/plugin-alias": "^2.2.0", "@rollup/plugin-alias": "^2.2.0",
"@rollup/plugin-json": "^4.0.0", "@rollup/plugin-json": "^4.0.0",
"@storybook/addon-actions": "^5.1.9",
"@storybook/addon-console": "^1.2.1",
"@storybook/addon-info": "^5.1.9",
"@storybook/addon-knobs": "^5.1.9",
"@storybook/addon-notes": "^5.1.9",
"@storybook/addon-storysource": "^5.1.11",
"@storybook/react": "^5.1.9", "@storybook/react": "^5.1.9",
"@types/dat.gui": "^0.7.1", "@types/dat.gui": "^0.7.1",
"@types/enzyme": "^3.1.14", "@types/enzyme": "^3.1.14",
@ -94,8 +88,6 @@
"rollup": "^1.27.14", "rollup": "^1.27.14",
"rollup-plugin-analyzer": "^3.2.2", "rollup-plugin-analyzer": "^3.2.2",
"rollup-plugin-babel": "^4.3.3", "rollup-plugin-babel": "^4.3.3",
"rollup-plugin-commonjs": "^10.1.0",
"rollup-plugin-node-resolve": "^5.2.0",
"rollup-plugin-postcss": "^2.0.3", "rollup-plugin-postcss": "^2.0.3",
"rollup-plugin-terser": "^5.1.2", "rollup-plugin-terser": "^5.1.2",
"rollup-pluginutils": "^2.8.2", "rollup-pluginutils": "^2.8.2",
@ -173,6 +165,9 @@
"path": "cz-conventional-changelog" "path": "cz-conventional-changelog"
} }
}, },
"resolutions": {
"../core-js": "3"
},
"tnpm": { "tnpm": {
"mode": "yarn" "mode": "yarn"
}, },

View File

@ -26,15 +26,10 @@
"dependencies": { "dependencies": {
"@antv/l7-core": "^2.0.0-beta.25", "@antv/l7-core": "^2.0.0-beta.25",
"@antv/l7-utils": "^2.0.0-beta.25", "@antv/l7-utils": "^2.0.0-beta.25",
"@babel/runtime": "^7.7.7",
"@turf/distance": "^6.0.1",
"core-js": "3", "core-js": "3",
"eventemitter3": "^4.0.0", "eventemitter3": "^4.0.0",
"inversify": "^5.0.1", "inversify": "^5.0.1",
"inversify-inject-decorators": "^3.1.0", "load-styles": "^2.0.0"
"inversify-logging": "^0.2.1",
"load-styles": "^2.0.0",
"regenerator-runtime": "^0.13.3"
}, },
"gitHead": "00d23ef70d9ec76eec26833fc50ac18fe584cf26", "gitHead": "00d23ef70d9ec76eec26833fc50ac18fe584cf26",
"publishConfig": { "publishConfig": {

View File

@ -23,7 +23,6 @@
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"@antv/l7-utils": "^2.0.0-beta.25", "@antv/l7-utils": "^2.0.0-beta.25",
"@babel/runtime": "^7.7.7",
"@mapbox/tiny-sdf": "^1.1.1", "@mapbox/tiny-sdf": "^1.1.1",
"ajv": "^6.10.2", "ajv": "^6.10.2",
"core-js": "3", "core-js": "3",

View File

@ -12,7 +12,7 @@ import {
} from './IFontService'; } from './IFontService';
export const DEFAULT_CHAR_SET = getDefaultCharacterSet(); export const DEFAULT_CHAR_SET = getDefaultCharacterSet();
export const DEFAULT_FONT_FAMILY = 'sans-serif'; export const DEFAULT_FONT_FAMILY = 'sans-serif';
export const DEFAULT_FONT_WEIGHT = 'normal'; export const DEFAULT_FONT_WEIGHT = '800';
export const DEFAULT_FONT_SIZE = 24; export const DEFAULT_FONT_SIZE = 24;
export const DEFAULT_BUFFER = 3; export const DEFAULT_BUFFER = 3;
export const DEFAULT_CUTOFF = 0.25; export const DEFAULT_CUTOFF = 0.25;

View File

@ -47,7 +47,7 @@ const defaultLayerConfig: Partial<ILayerConfig> = {
], ],
shape3d: ['cylinder', 'triangleColumn', 'hexagonColumn', 'squareColumn'], shape3d: ['cylinder', 'triangleColumn', 'hexagonColumn', 'squareColumn'],
minZoom: 0, minZoom: 0,
maxZoom: 20, maxZoom: 24,
visible: true, visible: true,
autoFit: false, autoFit: false,
zIndex: 0, zIndex: 0,

View File

@ -55,6 +55,7 @@ export interface ILayerModel {
getDefaultStyle(): unknown; getDefaultStyle(): unknown;
getAnimateUniforms(): IModelUniform; getAnimateUniforms(): IModelUniform;
buildModels(): IModel[]; buildModels(): IModel[];
needUpdate(): boolean;
} }
export interface IModelUniform { export interface IModelUniform {
[key: string]: IUniform; [key: string]: IUniform;

View File

@ -161,7 +161,9 @@ export default class Scene extends EventEmitter implements ISceneService {
this.$container as HTMLDivElement, this.$container as HTMLDivElement,
this.handleWindowResized, this.handleWindowResized,
); );
// window.addEventListener('resize', this.handleWindowResized, false); window
.matchMedia('screen and (-webkit-min-device-pixel-ratio: 1.5)')
.addListener(this.handleWindowResized);
} else { } else {
this.logger.error('容器 id 不存在'); this.logger.error('容器 id 不存在');
} }
@ -227,7 +229,9 @@ export default class Scene extends EventEmitter implements ISceneService {
this.rendererService.destroy(); this.rendererService.destroy();
this.map.destroy(); this.map.destroy();
unbind(this.$container as HTMLDivElement, this.handleWindowResized); unbind(this.$container as HTMLDivElement, this.handleWindowResized);
// window.removeEventListener('resize', this.handleWindowResized, false); window
.matchMedia('screen and (min-resolution: 2dppx)')
.removeListener(this.handleWindowResized);
} }
private handleWindowResized = () => { private handleWindowResized = () => {

View File

@ -28,9 +28,7 @@
"@antv/l7-core": "^2.0.0-beta.25", "@antv/l7-core": "^2.0.0-beta.25",
"@antv/l7-layers": "^2.0.0-beta.25", "@antv/l7-layers": "^2.0.0-beta.25",
"@antv/l7-maps": "^2.0.0-beta.25", "@antv/l7-maps": "^2.0.0-beta.25",
"@antv/l7-scene": "^2.0.0-beta.25", "@antv/l7-scene": "^2.0.0-beta.25"
"core-js": "3",
"regenerator-runtime": "^0.13.3"
}, },
"gitHead": "00d23ef70d9ec76eec26833fc50ac18fe584cf26", "gitHead": "00d23ef70d9ec76eec26833fc50ac18fe584cf26",
"publishConfig": { "publishConfig": {

View File

@ -25,7 +25,6 @@
"@antv/l7-core": "^2.0.0-beta.25", "@antv/l7-core": "^2.0.0-beta.25",
"@antv/l7-source": "^2.0.0-beta.25", "@antv/l7-source": "^2.0.0-beta.25",
"@antv/l7-utils": "^2.0.0-beta.25", "@antv/l7-utils": "^2.0.0-beta.25",
"@babel/runtime": "^7.7.7",
"@mapbox/martini": "^0.1.0", "@mapbox/martini": "^0.1.0",
"@turf/meta": "^6.0.2", "@turf/meta": "^6.0.2",
"@types/d3-color": "^1.2.2", "@types/d3-color": "^1.2.2",
@ -40,7 +39,6 @@
"inversify": "^5.0.1", "inversify": "^5.0.1",
"lodash": "^4.17.15", "lodash": "^4.17.15",
"merge-json-schemas": "1.0.0", "merge-json-schemas": "1.0.0",
"polyline-miter-util": "^1.0.1",
"reflect-metadata": "^0.1.13", "reflect-metadata": "^0.1.13",
"regenerator-runtime": "^0.13.3", "regenerator-runtime": "^0.13.3",
"tapable": "^2.0.0-beta.8" "tapable": "^2.0.0-beta.8"

View File

@ -16,16 +16,6 @@ export default class CityBuildingLayer extends BaseLayer {
}, },
}; };
} }
protected renderModels() {
this.models.forEach((model) =>
model.draw({
uniforms: this.layerModel.getUninforms(),
}),
);
return this;
}
protected buildModels() { protected buildModels() {
this.layerModel = new CityBuildModel(this); this.layerModel = new CityBuildModel(this);
this.models = this.layerModel.buildModels(); this.models = this.layerModel.buildModels();

View File

@ -165,7 +165,9 @@ export default class BaseLayer<ChildLayerStyleOptions = {}> extends EventEmitter
private scaleOptions: IScaleOptions = {}; private scaleOptions: IScaleOptions = {};
private AnimateStartTime: number; private animateStartTime: number;
private aniamateStatus: boolean = false;
constructor(config: Partial<ILayerConfig & ChildLayerStyleOptions> = {}) { constructor(config: Partial<ILayerConfig & ChildLayerStyleOptions> = {}) {
super(); super();
@ -309,6 +311,7 @@ export default class BaseLayer<ChildLayerStyleOptions = {}> extends EventEmitter
const { animateOption } = this.getLayerConfig(); const { animateOption } = this.getLayerConfig();
if (animateOption?.enable) { if (animateOption?.enable) {
this.layerService.startAnimate(); this.layerService.startAnimate();
this.aniamateStatus = true;
} }
this.buildModels(); this.buildModels();
// 触发初始化完成事件; // 触发初始化完成事件;
@ -730,10 +733,21 @@ export default class BaseLayer<ChildLayerStyleOptions = {}> extends EventEmitter
return this.layerService.clock.getDelta(); return this.layerService.clock.getDelta();
} }
public setAnimateStartTime() { public setAnimateStartTime() {
this.AnimateStartTime = this.layerService.clock.getElapsedTime(); this.animateStartTime = this.layerService.clock.getElapsedTime();
}
public stopAnimate() {
if (this.aniamateStatus) {
this.layerService.stopAnimate();
this.aniamateStatus = false;
this.updateLayerConfig({
animateOption: {
enable: false,
},
});
}
} }
public getLayerAnimateTime(): number { public getLayerAnimateTime(): number {
return this.layerService.clock.getElapsedTime() - this.AnimateStartTime; return this.layerService.clock.getElapsedTime() - this.animateStartTime;
} }
protected getConfigSchema() { protected getConfigSchema() {
@ -745,7 +759,16 @@ export default class BaseLayer<ChildLayerStyleOptions = {}> extends EventEmitter
} }
protected renderModels() { protected renderModels() {
throw new Error('Method not implemented.'); if (this.layerModelNeedUpdate) {
this.models = this.layerModel.buildModels();
this.layerModelNeedUpdate = false;
}
this.models.forEach((model) => {
model.draw({
uniforms: this.layerModel.getUninforms(),
});
});
return this;
} }
protected getModelType(): unknown { protected getModelType(): unknown {

View File

@ -77,6 +77,9 @@ export default class BaseModel<ChildLayerStyleOptions = {}>
return {}; return {};
} }
public needUpdate(): boolean {
return false;
}
public buildModels(): IModel[] { public buildModels(): IModel[] {
throw new Error('Method not implemented.'); throw new Error('Method not implemented.');
} }

View File

@ -2,6 +2,7 @@ import { IEncodeFeature } from '@antv/l7-core';
import { aProjectFlat, lngLatToMeters } from '@antv/l7-utils'; import { aProjectFlat, lngLatToMeters } from '@antv/l7-utils';
import earcut from 'earcut'; import earcut from 'earcut';
import { vec3 } from 'gl-matrix'; import { vec3 } from 'gl-matrix';
import { calculteCentroid } from '../utils/geo';
import getNormals from '../utils/polylineNormal'; import getNormals from '../utils/polylineNormal';
import extrudePolygon, { import extrudePolygon, {
extrude_PolygonNormal, extrude_PolygonNormal,
@ -24,7 +25,7 @@ const GeometryCache: IGeometryCache = {};
* @param feature feature * @param feature feature
*/ */
export function PointFillTriangulation(feature: IEncodeFeature) { export function PointFillTriangulation(feature: IEncodeFeature) {
const coordinates = feature.coordinates as number[]; const coordinates = calculteCentroid(feature.coordinates);
return { return {
vertices: [...coordinates, ...coordinates, ...coordinates, ...coordinates], vertices: [...coordinates, ...coordinates, ...coordinates, ...coordinates],
indices: [0, 1, 2, 2, 3, 0], indices: [0, 1, 2, 2, 3, 0],
@ -46,7 +47,6 @@ export function PointExtrudeTriangulation(feature: IEncodeFeature) {
vertices: positions, vertices: positions,
indices: index, indices: index,
normals, normals,
// normals: Array.from(computeVertexNormals(positions, index, 3, false)),
size: 5, size: 5,
}; };
} }
@ -56,7 +56,7 @@ export function PointExtrudeTriangulation(feature: IEncodeFeature) {
* @param feature feature * @param feature feature
*/ */
export function PointImageTriangulation(feature: IEncodeFeature) { export function PointImageTriangulation(feature: IEncodeFeature) {
const coordinates = feature.coordinates as number[]; const coordinates = calculteCentroid(feature.coordinates);
return { return {
vertices: [...coordinates], vertices: [...coordinates],
indices: [0], indices: [0],

View File

@ -21,8 +21,12 @@ export default class HeatMapLayer extends BaseLayer<IHeatMapLayerStyleOptions> {
protected renderModels() { protected renderModels() {
const shape = this.getModelType(); const shape = this.getModelType();
if (shape === 'heatmap') { if (shape === 'heatmap') {
this.layerModel.render(); this.layerModel.render(); // 独立的渲染流程
return; return this;
}
if (this.layerModelNeedUpdate) {
this.models = this.layerModel.buildModels();
this.layerModelNeedUpdate = false;
} }
this.models.forEach((model) => this.models.forEach((model) =>
model.draw({ model.draw({

View File

@ -20,8 +20,8 @@ import MultiPassRendererPlugin from './plugins/MultiPassRendererPlugin';
import PixelPickingPlugin from './plugins/PixelPickingPlugin'; import PixelPickingPlugin from './plugins/PixelPickingPlugin';
import RegisterStyleAttributePlugin from './plugins/RegisterStyleAttributePlugin'; import RegisterStyleAttributePlugin from './plugins/RegisterStyleAttributePlugin';
import ShaderUniformPlugin from './plugins/ShaderUniformPlugin'; import ShaderUniformPlugin from './plugins/ShaderUniformPlugin';
import UpdateModelPlugin from './plugins/UpdateModelPlugin';
import UpdateStyleAttributePlugin from './plugins/UpdateStyleAttributePlugin'; import UpdateStyleAttributePlugin from './plugins/UpdateStyleAttributePlugin';
/** /**
* *
* @see /dev-docs/ConfigSchemaValidation.md * @see /dev-docs/ConfigSchemaValidation.md
@ -74,6 +74,15 @@ container
.bind<ILayerPlugin>(TYPES.ILayerPlugin) .bind<ILayerPlugin>(TYPES.ILayerPlugin)
.to(UpdateStyleAttributePlugin) .to(UpdateStyleAttributePlugin)
.inRequestScope(); .inRequestScope();
/**
* Model更新
*/
container
.bind<ILayerPlugin>(TYPES.ILayerPlugin)
.to(UpdateModelPlugin)
.inRequestScope();
/** /**
* Multi Pass 线 * Multi Pass 线
*/ */

View File

@ -5,8 +5,6 @@ import LineModels, { LineModelType } from './models';
export default class LineLayer extends BaseLayer<ILineLayerStyleOptions> { export default class LineLayer extends BaseLayer<ILineLayerStyleOptions> {
public type: string = 'LineLayer'; public type: string = 'LineLayer';
private animateStartTime: number = 0;
protected getConfigSchema() { protected getConfigSchema() {
return { return {
properties: { properties: {
@ -28,14 +26,6 @@ export default class LineLayer extends BaseLayer<ILineLayerStyleOptions> {
}; };
return defaultConfig[type]; return defaultConfig[type];
} }
protected renderModels() {
this.models.forEach((model) =>
model.draw({
uniforms: this.layerModel.getUninforms(),
}),
);
return this;
}
protected buildModels() { protected buildModels() {
const shape = this.getModelType(); const shape = this.getModelType();
@ -49,12 +39,4 @@ export default class LineLayer extends BaseLayer<ILineLayerStyleOptions> {
const shape = shapeAttribute?.scale?.field as LineModelType; const shape = shapeAttribute?.scale?.field as LineModelType;
return shape || 'line'; return shape || 'line';
} }
// 拆分的动画插件
private initAnimate() {
const { enable } = this.animateOptions;
if (enable) {
this.layerService.startAnimate();
this.animateStartTime = this.layerService.clock.getElapsedTime();
}
}
} }

View File

@ -20,6 +20,9 @@ export default class LayerAnimateStylePlugin implements ILayerPlugin {
private readonly rendererService: IRendererService; private readonly rendererService: IRendererService;
public apply(layer: ILayer) { public apply(layer: ILayer) {
// layer.hooks.beforeRender.tap('LayerAnimateStylePlugin', () => {
// })
layer.hooks.beforeRender.tap('LayerAnimateStylePlugin', () => { layer.hooks.beforeRender.tap('LayerAnimateStylePlugin', () => {
// 重新计算坐标系参数 // 重新计算坐标系参数
layer.models.forEach((model: IModel) => { layer.models.forEach((model: IModel) => {

View File

@ -2,6 +2,9 @@ import { ILayer, ILayerPlugin, IMapService, TYPES } from '@antv/l7-core';
import Source from '@antv/l7-source'; import Source from '@antv/l7-source';
import { encodePickingColor, rgb2arr } from '@antv/l7-utils'; import { encodePickingColor, rgb2arr } from '@antv/l7-utils';
import { injectable } from 'inversify'; import { injectable } from 'inversify';
/**
*
*/
@injectable() @injectable()
export default class LayerStylePlugin implements ILayerPlugin { export default class LayerStylePlugin implements ILayerPlugin {
public apply(layer: ILayer) { public apply(layer: ILayer) {

View File

@ -0,0 +1,16 @@
import { ILayer, ILayerPlugin, IMapService, TYPES } from '@antv/l7-core';
import { injectable } from 'inversify';
/**
* Model
*/
@injectable()
export default class UpdateModelPlugin implements ILayerPlugin {
public apply(layer: ILayer) {
layer.hooks.beforeRender.tap('UpdateModelPlugin', () => {
// 处理文本更新
if (layer.layerModel) {
layer.layerModel.needUpdate();
}
});
}
}

View File

@ -28,23 +28,12 @@ export default class PointLayer extends BaseLayer<IPointLayerStyleOptions> {
fill: {}, fill: {},
extrude: {}, extrude: {},
image: {}, image: {},
text: {}, text: {
blend: 'normal',
},
}; };
return defaultConfig[type]; return defaultConfig[type];
} }
protected renderModels() {
if (this.layerModelNeedUpdate) {
this.models = this.layerModel.buildModels();
this.layerModelNeedUpdate = false;
}
this.models.forEach((model) => {
model.draw({
uniforms: this.layerModel.getUninforms(),
});
});
return this;
}
protected buildModels() { protected buildModels() {
const modelType = this.getModelType(); const modelType = this.getModelType();
this.layerModel = new PointModels[modelType](this); this.layerModel = new PointModels[modelType](this);
@ -79,9 +68,4 @@ export default class PointLayer extends BaseLayer<IPointLayerStyleOptions> {
return 'text'; return 'text';
} }
} }
private updateData() {
// const bounds = this.mapService.getBounds();
// console.log(bounds);
}
} }

View File

@ -1,6 +1,7 @@
import { AttributeType, gl, IEncodeFeature, IModel } from '@antv/l7-core'; import { AttributeType, gl, IEncodeFeature, IModel } from '@antv/l7-core';
import BaseModel from '../../core/BaseModel'; import BaseModel from '../../core/BaseModel';
import { PointExtrudeTriangulation } from '../../core/triangulation'; import { PointExtrudeTriangulation } from '../../core/triangulation';
import { calculteCentroid } from '../../utils/geo';
import pointExtrudeFrag from '../shaders/extrude_frag.glsl'; import pointExtrudeFrag from '../shaders/extrude_frag.glsl';
import pointExtrudeVert from '../shaders/extrude_vert.glsl'; import pointExtrudeVert from '../shaders/extrude_vert.glsl';
interface IPointLayerStyleOptions { interface IPointLayerStyleOptions {
@ -21,15 +22,7 @@ export default class ExtrudeModel extends BaseModel {
vertexShader: pointExtrudeVert, vertexShader: pointExtrudeVert,
fragmentShader: pointExtrudeFrag, fragmentShader: pointExtrudeFrag,
triangulation: PointExtrudeTriangulation, triangulation: PointExtrudeTriangulation,
blend: { blend: this.getBlend(),
enable: true,
func: {
srcRGB: gl.SRC_ALPHA,
srcAlpha: 1,
dstRGB: gl.ONE_MINUS_SRC_ALPHA,
dstAlpha: 1,
},
},
}), }),
]; ];
} }
@ -108,7 +101,7 @@ export default class ExtrudeModel extends BaseModel {
}, },
size: 3, size: 3,
update: (feature: IEncodeFeature, featureIdx: number) => { update: (feature: IEncodeFeature, featureIdx: number) => {
const coordinates = feature.coordinates as number[]; const coordinates = calculteCentroid(feature.coordinates);
return [coordinates[0], coordinates[1], 0]; return [coordinates[0], coordinates[1], 0];
}, },
}, },

View File

@ -42,15 +42,7 @@ export default class ImageModel extends BaseModel {
triangulation: PointImageTriangulation, triangulation: PointImageTriangulation,
primitive: gl.POINTS, primitive: gl.POINTS,
depth: { enable: false }, depth: { enable: false },
blend: { blend: this.getBlend(),
enable: true,
func: {
srcRGB: gl.SRC_ALPHA,
srcAlpha: 1,
dstRGB: gl.ONE_MINUS_SRC_ALPHA,
dstAlpha: 1,
},
},
}), }),
]; ];
} }

View File

@ -3,6 +3,7 @@ import {
BlendType, BlendType,
gl, gl,
IEncodeFeature, IEncodeFeature,
ILayer,
ILayerConfig, ILayerConfig,
IModel, IModel,
IModelUniform, IModelUniform,
@ -10,7 +11,8 @@ import {
} from '@antv/l7-core'; } from '@antv/l7-core';
import { rgb2arr } from '@antv/l7-utils'; import { rgb2arr } from '@antv/l7-utils';
import BaseModel from '../../core/BaseModel'; import BaseModel from '../../core/BaseModel';
import { PointFillTriangulation } from '../../core/triangulation'; import CollisionIndex from '../../utils/collision-index';
import { calculteCentroid } from '../../utils/geo';
import { import {
getGlyphQuads, getGlyphQuads,
IGlyphQuad, IGlyphQuad,
@ -32,14 +34,12 @@ interface IPointTextLayerStyleOptions {
textAllowOverlap: boolean; textAllowOverlap: boolean;
} }
export function TextTriangulation(feature: IEncodeFeature) { export function TextTriangulation(feature: IEncodeFeature) {
const coordinates = feature.coordinates as number[]; const centroid = feature.centroid as number[]; // 计算中心点
const { glyphQuads } = feature; const { glyphQuads } = feature;
const vertices: number[] = []; const vertices: number[] = [];
const indices: number[] = []; const indices: number[] = [];
const coord = const coord =
coordinates.length === 2 centroid.length === 2 ? [centroid[0], centroid[1], 0] : centroid;
? [coordinates[0], coordinates[1], 0]
: coordinates;
glyphQuads.forEach((quad: IGlyphQuad, index: number) => { glyphQuads.forEach((quad: IGlyphQuad, index: number) => {
vertices.push( vertices.push(
...coord, ...coord,
@ -81,14 +81,18 @@ export function TextTriangulation(feature: IEncodeFeature) {
export default class TextModel extends BaseModel { export default class TextModel extends BaseModel {
private texture: ITexture2D; private texture: ITexture2D;
private glyphInfo: IEncodeFeature[];
private currentZoom: number = -1;
private extent: [[number, number], [number, number]];
public getUninforms(): IModelUniform { public getUninforms(): IModelUniform {
const { const {
fontWeight = 'normal', fontWeight = 800,
fontFamily, fontFamily,
stroke, stroke = '#fff',
strokeWidth, strokeWidth = 0,
} = this.layer.getLayerConfig() as IPointTextLayerStyleOptions; } = this.layer.getLayerConfig() as IPointTextLayerStyleOptions;
const { canvas, fontAtlas, mapping } = this.fontService; const { canvas } = this.fontService;
return { return {
u_opacity: 1.0, u_opacity: 1.0,
u_sdf_map: this.texture, u_sdf_map: this.texture,
@ -100,10 +104,9 @@ export default class TextModel extends BaseModel {
} }
public buildModels(): IModel[] { public buildModels(): IModel[] {
this.initTextFont(); this.initGlyph();
this.generateGlyphLayout();
this.registerBuiltinAttributes();
this.updateTexture(); this.updateTexture();
this.filterGlyphs();
return [ return [
this.layer.buildLayerModel({ this.layer.buildLayerModel({
moduleName: 'pointText', moduleName: 'pointText',
@ -115,9 +118,36 @@ export default class TextModel extends BaseModel {
}), }),
]; ];
} }
public needUpdate() {
const {
textAllowOverlap = false,
} = this.layer.getLayerConfig() as IPointTextLayerStyleOptions;
const zoom = this.mapService.getZoom();
const extent = this.mapService.getBounds();
const flag =
extent[0][0] < this.extent[0][0] ||
extent[0][1] < this.extent[0][1] ||
extent[1][0] > this.extent[1][0] ||
extent[1][1] < this.extent[1][1];
if (!textAllowOverlap && (Math.abs(this.currentZoom - zoom) > 1 || flag)) {
this.filterGlyphs();
this.layer.models = [
this.layer.buildLayerModel({
moduleName: 'pointText',
vertexShader: textVert,
fragmentShader: textFrag,
triangulation: TextTriangulation,
depth: { enable: false },
blend: this.getBlend(),
}),
];
return true;
}
return false;
}
protected registerBuiltinAttributes() { protected registerBuiltinAttributes() {
const viewProjection = this.cameraService.getViewProjectionMatrix();
this.styleAttributeService.registerStyleAttribute({ this.styleAttributeService.registerStyleAttribute({
name: 'textOffsets', name: 'textOffsets',
type: AttributeType.Attribute, type: AttributeType.Attribute,
@ -190,9 +220,21 @@ export default class TextModel extends BaseModel {
}, },
}); });
} }
private textExtent(): [[number, number], [number, number]] {
const bounds = this.mapService.getBounds();
const step =
Math.min(bounds[1][0] - bounds[0][0], bounds[1][1] - bounds[1][0]) / 2;
return [
[bounds[0][0] - step, bounds[0][1] - step],
[bounds[1][0] + step, bounds[1][1] + step],
];
}
/**
*
*/
private initTextFont() { private initTextFont() {
const { const {
fontWeight = 'normal', fontWeight = '800',
fontFamily, fontFamily,
} = this.layer.getLayerConfig() as IPointTextLayerStyleOptions; } = this.layer.getLayerConfig() as IPointTextLayerStyleOptions;
const data = this.layer.getEncodedData(); const data = this.layer.getEncodedData();
@ -213,20 +255,19 @@ export default class TextModel extends BaseModel {
fontFamily, fontFamily,
}); });
} }
/**
*
*/
private generateGlyphLayout() { private generateGlyphLayout() {
const { canvas, fontAtlas, mapping } = this.fontService; const { mapping } = this.fontService;
const { const {
spacing = 2, spacing = 2,
textAnchor = 'center', textAnchor = 'center',
textOffset, textOffset,
padding = [4, 4],
textAllowOverlap,
} = this.layer.getLayerConfig() as IPointTextLayerStyleOptions; } = this.layer.getLayerConfig() as IPointTextLayerStyleOptions;
const data = this.layer.getEncodedData(); const data = this.layer.getEncodedData();
data.forEach((feature: IEncodeFeature) => { this.glyphInfo = data.map((feature: IEncodeFeature) => {
const { coordinates, shape = '' } = feature; const { shape = '', coordinates } = feature;
const size = feature.size as number;
const fontScale = size / 24;
const shaping = shapeText( const shaping = shapeText(
shape.toString(), shape.toString(),
mapping, mapping,
@ -239,19 +280,61 @@ export default class TextModel extends BaseModel {
const glyphQuads = getGlyphQuads(shaping, textOffset, false); const glyphQuads = getGlyphQuads(shaping, textOffset, false);
feature.shaping = shaping; feature.shaping = shaping;
feature.glyphQuads = glyphQuads; feature.glyphQuads = glyphQuads;
feature.centroid = calculteCentroid(coordinates);
return feature;
}); });
} }
/**
private drawGlyph() { *
*/
private filterGlyphs() {
const { const {
spacing = 2,
textAnchor = 'center',
textOffset = [0, 0],
padding = [4, 4], padding = [4, 4],
textAllowOverlap, textAllowOverlap = false,
} = this.layer.getLayerConfig() as IPointTextLayerStyleOptions; } = this.layer.getLayerConfig() as IPointTextLayerStyleOptions;
const viewProjection = this.cameraService.getViewProjectionMatrix(); if (textAllowOverlap) {
return;
} }
this.currentZoom = this.mapService.getZoom();
this.extent = this.textExtent();
const { width, height } = this.rendererService.getViewportSize();
const collisionIndex = new CollisionIndex(width, height);
const filterData = this.glyphInfo.filter((feature: IEncodeFeature) => {
const { shaping, id = 0 } = feature;
const centroid = feature.centroid as [number, number];
const size = feature.size as number;
const fontScale: number = size / 24;
const pixels = this.mapService.lngLatToContainer(centroid);
const { box } = collisionIndex.placeCollisionBox({
x1: shaping.left * fontScale - padding[0],
x2: shaping.right * fontScale + padding[0],
y1: shaping.top * fontScale - padding[1],
y2: shaping.bottom * fontScale + padding[1],
anchorPointX: pixels.x,
anchorPointY: pixels.y,
});
if (box && box.length) {
// TODOfeatureIndex
collisionIndex.insertCollisionBox(box, id);
return true;
} else {
return false;
}
});
this.layer.setEncodedData(filterData);
}
/**
*
*/
private initGlyph() {
// 1.生成文字纹理
this.initTextFont();
// 2.生成文字布局
this.generateGlyphLayout();
}
/**
*
*/
private updateTexture() { private updateTexture() {
const { createTexture2D } = this.rendererService; const { createTexture2D } = this.rendererService;
const { canvas } = this.fontService; const { canvas } = this.fontService;

View File

@ -27,7 +27,7 @@ void main() {
vec4 projected_position = project_common_position_to_clipspace(vec4(project_pos.xyz, 1.0)); vec4 projected_position = project_common_position_to_clipspace(vec4(project_pos.xyz, 1.0));
gl_Position = vec4(projected_position.xy / projected_position.w gl_Position = vec4(projected_position.xy / projected_position.w
+ a_textOffsets * fontScale / u_ViewportSize * 2., 0.0, 1.0); + a_textOffsets * fontScale / u_ViewportSize * 2. * u_DevicePixelRatio, 0.0, 1.0);
v_gamma_scale = gl_Position.w; v_gamma_scale = gl_Position.w;

View File

@ -1,5 +1,6 @@
import { IEncodeFeature } from '@antv/l7-core'; import { IEncodeFeature } from '@antv/l7-core';
import BaseLayer from '../core/BaseLayer'; import BaseLayer from '../core/BaseLayer';
import { PointType } from '../point/models/';
import PolygonModels, { PolygonModelType } from './models/'; import PolygonModels, { PolygonModelType } from './models/';
interface IPolygonLayerStyleOptions { interface IPolygonLayerStyleOptions {
@ -20,16 +21,6 @@ export default class PolygonLayer extends BaseLayer<IPolygonLayerStyleOptions> {
}, },
}; };
} }
protected renderModels() {
this.models.forEach((model) =>
model.draw({
uniforms: this.layerModel.getUninforms(),
}),
);
return this;
}
protected buildModels() { protected buildModels() {
const shape = this.getModelType(); const shape = this.getModelType();
this.layerModel = new PolygonModels[shape](this); this.layerModel = new PolygonModels[shape](this);
@ -41,6 +32,42 @@ export default class PolygonLayer extends BaseLayer<IPolygonLayerStyleOptions> {
'shape', 'shape',
); );
const shape = shapeAttribute?.scale?.field as PolygonModelType; const shape = shapeAttribute?.scale?.field as PolygonModelType;
return shape || 'fill'; if (shape === 'fill') {
return 'fill';
} else if (shape === 'extrude') {
return 'extrude';
} else if (shape === 'line') {
return 'line';
} else {
return this.getPointModelType();
}
}
protected getPointModelType(): PolygonModelType {
// pointlayer
// 2D、 3d、 shape、image、text、normal、
const layerData = this.getEncodedData();
const { shape2d, shape3d } = this.getLayerConfig();
const iconMap = this.iconService.getIconMap();
const item = layerData.find((fe: IEncodeFeature) => {
return fe.hasOwnProperty('shape');
});
if (!item) {
return 'fill';
} else {
const shape = item.shape;
if (shape === 'dot') {
return 'point_normal';
}
if (shape2d?.indexOf(shape as string) !== -1) {
return 'point_fill';
}
if (shape3d?.indexOf(shape as string) !== -1) {
return 'point_extrude';
}
if (iconMap.hasOwnProperty(shape as string)) {
return 'point_image';
}
return 'text';
}
} }
} }

View File

@ -1,13 +1,32 @@
import LineModel from '../../line/models/line'; import LineModel from '../../line/models/line';
import PointExtrudeModel from '../../point/models/extrude';
import PointFillModel from '../../point/models/fill';
import IMageModel from '../../point/models/image';
import NormalModel from '../../point/models/normal';
import TextModel from '../../point/models/text';
import ExtrudeModel from './extrude'; import ExtrudeModel from './extrude';
import FillModel from './fill'; import FillModel from './fill';
export type PolygonModelType = 'fill' | 'extrude' | 'line'; export type PolygonModelType =
| 'fill'
| 'extrude'
| 'line'
| 'point_fill'
| 'point_image'
| 'point_normal'
| 'point_extrude'
| 'text';
const PolygonModels: { [key in PolygonModelType]: any } = { const PolygonModels: { [key in PolygonModelType]: any } = {
fill: FillModel, fill: FillModel,
line: LineModel, line: LineModel,
extrude: ExtrudeModel, extrude: ExtrudeModel,
}; text: TextModel,
point_fill: PointFillModel,
point_image: IMageModel,
point_normal: NormalModel,
point_extrude: PointExtrudeModel,
// point_fill: PointModels.fill,
};
export default PolygonModels; export default PolygonModels;

View File

@ -9,10 +9,6 @@ export interface ICollisionBox {
// @mapbox/grid-index 并没有类似 hitTest 的单纯获取碰撞检测结果的方法query 将导致计算大量多余的包围盒结果,因此使用改良版 // @mapbox/grid-index 并没有类似 hitTest 的单纯获取碰撞检测结果的方法query 将导致计算大量多余的包围盒结果,因此使用改良版
import { mat4, vec4 } from 'gl-matrix'; import { mat4, vec4 } from 'gl-matrix';
import GridIndex from './grid-index'; import GridIndex from './grid-index';
// 为 viewport 加上 buffer避免边缘处的文本无法显示
const viewportPadding = 100;
/** /**
* *
* @see https://zhuanlan.zhihu.com/p/74373214 * @see https://zhuanlan.zhihu.com/p/74373214
@ -21,6 +17,7 @@ export default class CollisionIndex {
private width: number; private width: number;
private height: number; private height: number;
private grid: GridIndex; private grid: GridIndex;
private viewportPadding: number = 100;
private screenRightBoundary: number; private screenRightBoundary: number;
private screenBottomBoundary: number; private screenBottomBoundary: number;
private gridRightBoundary: number; private gridRightBoundary: number;
@ -28,30 +25,35 @@ export default class CollisionIndex {
constructor(width: number, height: number) { constructor(width: number, height: number) {
this.width = width; this.width = width;
this.height = height; this.height = height;
this.viewportPadding = Math.max(width, height);
// 创建网格索引 // 创建网格索引
this.grid = new GridIndex( this.grid = new GridIndex(
width + 2 * viewportPadding, width + this.viewportPadding,
height + 2 * viewportPadding, height + this.viewportPadding,
25, 25,
); );
this.screenRightBoundary = width + viewportPadding; this.screenRightBoundary = width + this.viewportPadding;
this.screenBottomBoundary = height + viewportPadding; this.screenBottomBoundary = height + this.viewportPadding;
this.gridRightBoundary = width + 2 * viewportPadding; this.gridRightBoundary = width + 2 * this.viewportPadding;
this.gridBottomBoundary = height + 2 * viewportPadding; this.gridBottomBoundary = height + 2 * this.viewportPadding;
} }
public placeCollisionBox(collisionBox: ICollisionBox, mvpMatrix: mat4) { public placeCollisionBox(collisionBox: ICollisionBox) {
const projectedPoint = this.project( // const projectedPoint = this.project(
mvpMatrix, // mvpMatrix,
collisionBox.anchorPointX, // collisionBox.anchorPointX,
collisionBox.anchorPointY, // collisionBox.anchorPointY,
); // );
const tlX = collisionBox.x1 + projectedPoint.x; const tlX =
const tlY = collisionBox.y1 + projectedPoint.y; collisionBox.x1 + collisionBox.anchorPointX + this.viewportPadding;
const brX = collisionBox.x2 + projectedPoint.x; const tlY =
const brY = collisionBox.y2 + projectedPoint.y; collisionBox.y1 + collisionBox.anchorPointY + this.viewportPadding;
const brX =
collisionBox.x2 + collisionBox.anchorPointX + this.viewportPadding;
const brY =
collisionBox.y2 + collisionBox.anchorPointY + this.viewportPadding;
if ( if (
!this.isInsideGrid(tlX, tlY, brX, brY) || !this.isInsideGrid(tlX, tlY, brX, brY) ||
@ -79,14 +81,16 @@ export default class CollisionIndex {
* @param {number} y P20 Y * @param {number} y P20 Y
* @return {Point} projectedPoint * @return {Point} projectedPoint
*/ */
public project(mvpMatrix: mat4, x: number, y: number) { public project(mvpMatrix: number[], x: number, y: number) {
const point = vec4.fromValues(x, y, 0, 1); const point = vec4.fromValues(x, y, 0, 1);
const out = vec4.create(); const out = vec4.create();
vec4.transformMat4(out, point, mvpMatrix); // @ts-ignore
const mat = mat4.fromValues(...mvpMatrix);
vec4.transformMat4(out, point, mat);
// GL 坐标系[-1, 1] -> viewport 坐标系[width, height] // GL 坐标系[-1, 1] -> viewport 坐标系[width, height]
return { return {
x: ((out[0] / out[3] + 1) / 2) * this.width + viewportPadding, x: ((out[0] / out[3] + 1) / 2) * this.width + this.viewportPadding,
y: ((-out[1] / out[3] + 1) / 2) * this.height + viewportPadding, y: ((-out[1] / out[3] + 1) / 2) * this.height + this.viewportPadding,
}; };
} }

View File

@ -0,0 +1,27 @@
type Position = number[];
import { isNumber } from 'lodash';
export function calculteCentroid(
coord: Position | Position[] | Position[][],
): Position {
// let pos = coord as Position;
if (isNumber(coord[0])) {
return coord as Position;
} else if (isNumber(coord[0][0])) {
throw new Error('当前数据不支持标注');
} else if (isNumber(coord[0][0][0])) {
const coords = coord as Position[][];
let xSum = 0;
let ySum = 0;
let len = 0;
coords.forEach((coor: Position[]) => {
coor.forEach((pos) => {
xSum += pos[0];
ySum += pos[1];
len++;
});
});
return [xSum / len, ySum / len, 0];
} else {
throw new Error('当前数据不支持标注');
}
}

View File

@ -8,7 +8,7 @@ type CallBack = (...args: any[]) => any;
* @see https://zhuanlan.zhihu.com/p/74373214 * @see https://zhuanlan.zhihu.com/p/74373214
*/ */
class GridIndex { class GridIndex {
private boxCells: number[][]; private boxCells: number[][] = [];
private xCellCount: number; private xCellCount: number;
private yCellCount: number; private yCellCount: number;
private boxKeys: string[]; private boxKeys: string[];

View File

@ -237,7 +237,7 @@ export function getGlyphQuads(
textOffset: [number, number] = [0, 0], textOffset: [number, number] = [0, 0],
alongLine: boolean, alongLine: boolean,
): IGlyphQuad[] { ): IGlyphQuad[] {
const { positionedGlyphs } = shaping; const { positionedGlyphs = [] } = shaping;
const quads: IGlyphQuad[] = []; const quads: IGlyphQuad[] = [];
for (const positionedGlyph of positionedGlyphs) { for (const positionedGlyph of positionedGlyphs) {

View File

@ -25,7 +25,6 @@
"dependencies": { "dependencies": {
"@antv/l7-core": "^2.0.0-beta.25", "@antv/l7-core": "^2.0.0-beta.25",
"@antv/l7-utils": "^2.0.0-beta.25", "@antv/l7-utils": "^2.0.0-beta.25",
"@babel/runtime": "^7.7.7",
"core-js": "3", "core-js": "3",
"gl-matrix": "^3.1.0", "gl-matrix": "^3.1.0",
"inversify": "^5.0.1", "inversify": "^5.0.1",

View File

@ -26,10 +26,8 @@
}, },
"dependencies": { "dependencies": {
"@antv/l7-core": "^2.0.0-beta.25", "@antv/l7-core": "^2.0.0-beta.25",
"@babel/runtime": "^7.7.7",
"core-js": "3", "core-js": "3",
"inversify": "^5.0.1", "inversify": "^5.0.1",
"inversify-logging": "^0.2.1",
"lodash": "^4.17.15", "lodash": "^4.17.15",
"reflect-metadata": "^0.1.13", "reflect-metadata": "^0.1.13",
"regenerator-runtime": "^0.13.3", "regenerator-runtime": "^0.13.3",

View File

@ -27,13 +27,10 @@
"@antv/l7-maps": "^2.0.0-beta.25", "@antv/l7-maps": "^2.0.0-beta.25",
"@antv/l7-renderer": "^2.0.0-beta.25", "@antv/l7-renderer": "^2.0.0-beta.25",
"@antv/l7-utils": "^2.0.0-beta.25", "@antv/l7-utils": "^2.0.0-beta.25",
"@babel/runtime": "^7.7.7",
"core-js": "3", "core-js": "3",
"inversify": "^5.0.1", "inversify": "^5.0.1",
"inversify-inject-decorators": "^3.1.0",
"mapbox-gl": "^1.2.1", "mapbox-gl": "^1.2.1",
"reflect-metadata": "^0.1.13", "reflect-metadata": "^0.1.13"
"regenerator-runtime": "^0.13.3"
}, },
"gitHead": "00d23ef70d9ec76eec26833fc50ac18fe584cf26", "gitHead": "00d23ef70d9ec76eec26833fc50ac18fe584cf26",
"publishConfig": { "publishConfig": {

View File

@ -26,7 +26,6 @@
"dependencies": { "dependencies": {
"@antv/l7-core": "^2.0.0-beta.25", "@antv/l7-core": "^2.0.0-beta.25",
"@antv/l7-utils": "^2.0.0-beta.25", "@antv/l7-utils": "^2.0.0-beta.25",
"@babel/runtime": "^7.7.7",
"@mapbox/geojson-rewind": "^0.4.0", "@mapbox/geojson-rewind": "^0.4.0",
"@turf/helpers": "^6.1.4", "@turf/helpers": "^6.1.4",
"@turf/invariant": "^6.1.2", "@turf/invariant": "^6.1.2",
@ -35,22 +34,15 @@
"d3-dsv": "^1.1.1", "d3-dsv": "^1.1.1",
"d3-hexbin": "^0.2.2", "d3-hexbin": "^0.2.2",
"eventemitter3": "^4.0.0", "eventemitter3": "^4.0.0",
"gl-matrix": "^3.1.0",
"inversify": "^5.0.1", "inversify": "^5.0.1",
"inversify-inject-decorators": "^3.1.0",
"inversify-logging": "^0.2.1",
"lodash": "^4.17.15", "lodash": "^4.17.15",
"reflect-metadata": "^0.1.13",
"regenerator-runtime": "^0.13.3",
"supercluster": "^6.0.2", "supercluster": "^6.0.2",
"tapable": "^2.0.0-beta.8" "tapable": "^2.0.0-beta.8"
}, },
"devDependencies": { "devDependencies": {
"@types/d3-dsv": "^1.0.36", "@types/d3-dsv": "^1.0.36",
"@types/d3-hexbin": "^0.2.3", "@types/d3-hexbin": "^0.2.3",
"@types/gl-matrix": "^2.4.5", "@types/lodash": "^4.14.138"
"@types/lodash": "^4.14.138",
"@types/viewport-mercator-project": "^6.1.0"
}, },
"gitHead": "00d23ef70d9ec76eec26833fc50ac18fe584cf26", "gitHead": "00d23ef70d9ec76eec26833fc50ac18fe584cf26",
"publishConfig": { "publishConfig": {

View File

@ -22,22 +22,8 @@
"author": "lzxue", "author": "lzxue",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"@babel/runtime": "^7.7.7",
"@turf/helpers": "^6.1.4", "@turf/helpers": "^6.1.4",
"core-js": "3", "core-js": "3"
"eventemitter3": "^4.0.0",
"gl-matrix": "^3.1.0",
"inversify": "^5.0.1",
"inversify-inject-decorators": "^3.1.0",
"inversify-logging": "^0.2.1",
"lodash": "^4.17.15",
"reflect-metadata": "^0.1.13",
"regenerator-runtime": "^0.13.3",
"tapable": "^2.0.0-beta.8"
},
"devDependencies": {
"@types/gl-matrix": "^2.4.5",
"@types/lodash": "^4.14.138"
}, },
"gitHead": "00d23ef70d9ec76eec26833fc50ac18fe584cf26", "gitHead": "00d23ef70d9ec76eec26833fc50ac18fe584cf26",
"publishConfig": { "publishConfig": {

View File

@ -19,7 +19,7 @@ export default class ZoomComponent extends React.Component {
const scene = new Scene({ const scene = new Scene({
id: 'map', id: 'map',
map: new Mapbox({ map: new Mapbox({
style: 'mapbox://styles/mapbox/streets-v9', style: 'dark',
center: [110.19382669582967, 30.258134], center: [110.19382669582967, 30.258134],
pitch: 0, pitch: 0,
zoom: 3, zoom: 3,
@ -39,9 +39,10 @@ export default class ZoomComponent extends React.Component {
'#FF7A45', '#FF7A45',
'#CF1D49', '#CF1D49',
]) ])
.shape('fill') .shape('name', 'text')
.size(10)
.style({ .style({
opacity: 0.3, opacity: 1.0,
}); });
scene.addLayer(layer); scene.addLayer(layer);
const zoomControl = new Zoom({ const zoomControl = new Zoom({

View File

@ -44,7 +44,7 @@ export default class TextLayerDemo extends React.Component {
const scene = new Scene({ const scene = new Scene({
id: 'map', id: 'map',
map: new GaodeMap({ map: new Mapbox({
center: [120.19382669582967, 30.258134], center: [120.19382669582967, 30.258134],
pitch: 0, pitch: 0,
style: 'dark', style: 'dark',
@ -61,17 +61,17 @@ export default class TextLayerDemo extends React.Component {
}, },
}) })
.shape('m', 'text') .shape('m', 'text')
.size(24) .size(12)
.color('#fff') .color('#fff')
.style({ .style({
fontWeight: 800, // fontWeight: 200,
textAnchor: 'center', // 文本相对锚点的位置 center|left|right|top|bottom|top-left // textAnchor: 'center', // 文本相对锚点的位置 center|left|right|top|bottom|top-left
textOffset: [0, 0], // 文本相对锚点的偏移量 [水平, 垂直] // textOffset: [0, 0], // 文本相对锚点的偏移量 [水平, 垂直]
spacing: 2, // 字符间距 // spacing: 2, // 字符间距
padding: [4, 4], // 文本包围盒 padding [水平,垂直],影响碰撞检测结果,避免相邻文本靠的太近 // padding: [1, 1], // 文本包围盒 padding [水平,垂直],影响碰撞检测结果,避免相邻文本靠的太近
strokeColor: 'white', // 描边颜色 // stroke: 'red', // 描边颜色
strokeWidth: 4, // 描边宽度 // strokeWidth: 2, // 描边宽度
strokeOpacity: 1.0, // strokeOpacity: 1.0,
}); });
scene.addLayer(pointLayer); scene.addLayer(pointLayer);

12828
yarn.lock

File diff suppressed because it is too large Load Diff