feat: polygon 支持text

This commit is contained in:
thinkinggis 2019-12-30 18:10:21 +08:00
parent 0a9558d8eb
commit 3114ab55a5
12 changed files with 118 additions and 44 deletions

View File

@ -12,7 +12,7 @@ import {
} from './IFontService';
export const DEFAULT_CHAR_SET = getDefaultCharacterSet();
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_BUFFER = 3;
export const DEFAULT_CUTOFF = 0.25;

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() {
this.layerModel = new CityBuildModel(this);
this.models = this.layerModel.buildModels();

View File

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

View File

@ -8,10 +8,9 @@ export default class UpdateModelPlugin implements ILayerPlugin {
public apply(layer: ILayer) {
layer.hooks.beforeRender.tap('UpdateModelPlugin', () => {
// 处理文本更新
layer.layerModel.needUpdate();
// if (layer.layerModel.needUpdate()) {
// layer.layerModelNeedUpdate = true;
// }
if (layer.layerModel) {
layer.layerModel.needUpdate();
}
});
}
}

View File

@ -1,6 +1,7 @@
import { AttributeType, gl, IEncodeFeature, IModel } from '@antv/l7-core';
import BaseModel from '../../core/BaseModel';
import { PointExtrudeTriangulation } from '../../core/triangulation';
import { calculteCentroid } from '../../utils/geo';
import pointExtrudeFrag from '../shaders/extrude_frag.glsl';
import pointExtrudeVert from '../shaders/extrude_vert.glsl';
interface IPointLayerStyleOptions {
@ -100,7 +101,7 @@ export default class ExtrudeModel extends BaseModel {
},
size: 3,
update: (feature: IEncodeFeature, featureIdx: number) => {
const coordinates = feature.coordinates as number[];
const coordinates = calculteCentroid(feature.coordinates);
return [coordinates[0], coordinates[1], 0];
},
},

View File

@ -12,6 +12,7 @@ import {
import { rgb2arr } from '@antv/l7-utils';
import BaseModel from '../../core/BaseModel';
import CollisionIndex from '../../utils/collision-index';
import { calculteCentroid } from '../../utils/geo';
import {
getGlyphQuads,
IGlyphQuad,
@ -33,14 +34,12 @@ interface IPointTextLayerStyleOptions {
textAllowOverlap: boolean;
}
export function TextTriangulation(feature: IEncodeFeature) {
const coordinates = feature.coordinates as number[];
const centroid = feature.centroid as number[]; // 计算中心点
const { glyphQuads } = feature;
const vertices: number[] = [];
const indices: number[] = [];
const coord =
coordinates.length === 2
? [coordinates[0], coordinates[1], 0]
: coordinates;
centroid.length === 2 ? [centroid[0], centroid[1], 0] : centroid;
glyphQuads.forEach((quad: IGlyphQuad, index: number) => {
vertices.push(
...coord,
@ -90,8 +89,8 @@ export default class TextModel extends BaseModel {
const {
fontWeight = 800,
fontFamily,
stroke,
strokeWidth,
stroke = '#fff',
strokeWidth = 0,
} = this.layer.getLayerConfig() as IPointTextLayerStyleOptions;
const { canvas } = this.fontService;
return {
@ -235,7 +234,7 @@ export default class TextModel extends BaseModel {
*/
private initTextFont() {
const {
fontWeight = 'normal',
fontWeight = '800',
fontFamily,
} = this.layer.getLayerConfig() as IPointTextLayerStyleOptions;
const data = this.layer.getEncodedData();
@ -268,7 +267,7 @@ export default class TextModel extends BaseModel {
} = this.layer.getLayerConfig() as IPointTextLayerStyleOptions;
const data = this.layer.getEncodedData();
this.glyphInfo = data.map((feature: IEncodeFeature) => {
const { shape = '' } = feature;
const { shape = '', coordinates } = feature;
const shaping = shapeText(
shape.toString(),
mapping,
@ -281,6 +280,7 @@ export default class TextModel extends BaseModel {
const glyphQuads = getGlyphQuads(shaping, textOffset, false);
feature.shaping = shaping;
feature.glyphQuads = glyphQuads;
feature.centroid = calculteCentroid(coordinates);
return feature;
});
}
@ -301,10 +301,10 @@ export default class TextModel extends BaseModel {
const collisionIndex = new CollisionIndex(width, height);
const filterData = this.glyphInfo.filter((feature: IEncodeFeature) => {
const { shaping, id = 0 } = feature;
const coordinates = feature.coordinates as [number, number];
const centroid = feature.centroid as [number, number];
const size = feature.size as number;
const fontScale: number = size / 24;
const pixels = this.mapService.lngLatToContainer(coordinates);
const pixels = this.mapService.lngLatToContainer(centroid);
const { box } = collisionIndex.placeCollisionBox({
x1: shaping.left * fontScale - padding[0],
x2: shaping.right * fontScale + padding[0],

View File

@ -1,5 +1,6 @@
import { IEncodeFeature } from '@antv/l7-core';
import BaseLayer from '../core/BaseLayer';
import { PointType } from '../point/models/';
import PolygonModels, { PolygonModelType } from './models/';
interface IPolygonLayerStyleOptions {
@ -31,6 +32,42 @@ export default class PolygonLayer extends BaseLayer<IPolygonLayerStyleOptions> {
'shape',
);
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 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 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 } = {
fill: FillModel,
line: LineModel,
extrude: ExtrudeModel,
};
text: TextModel,
point_fill: PointFillModel,
point_image: IMageModel,
point_normal: NormalModel,
point_extrude: PointExtrudeModel,
// point_fill: PointModels.fill,
};
export default PolygonModels;

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

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

View File

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

View File

@ -64,14 +64,14 @@ export default class TextLayerDemo extends React.Component {
.size(12)
.color('#fff')
.style({
fontWeight: 200,
textAnchor: 'center', // 文本相对锚点的位置 center|left|right|top|bottom|top-left
textOffset: [0, 0], // 文本相对锚点的偏移量 [水平, 垂直]
spacing: 2, // 字符间距
padding: [1, 1], // 文本包围盒 padding [水平,垂直],影响碰撞检测结果,避免相邻文本靠的太近
stroke: 'red', // 描边颜色
strokeWidth: 2, // 描边宽度
strokeOpacity: 1.0,
// fontWeight: 200,
// textAnchor: 'center', // 文本相对锚点的位置 center|left|right|top|bottom|top-left
// textOffset: [0, 0], // 文本相对锚点的偏移量 [水平, 垂直]
// spacing: 2, // 字符间距
// padding: [1, 1], // 文本包围盒 padding [水平,垂直],影响碰撞检测结果,避免相邻文本靠的太近
// stroke: 'red', // 描边颜色
// strokeWidth: 2, // 描边宽度
// strokeOpacity: 1.0,
});
scene.addLayer(pointLayer);