mirror of https://gitee.com/antv-l7/antv-l7
Shihui (#1010)
* feat: 修改 CanvasLayer drawingOnCanvas 的 参数 * style: lint style * feat: 新增 geometryLayer plane
This commit is contained in:
parent
74c6ee3ce7
commit
499684ee09
|
@ -126,6 +126,24 @@ export default class IconService extends EventEmitter implements IIconService {
|
|||
this.iconData = [];
|
||||
this.iconMap = {};
|
||||
}
|
||||
|
||||
public loadImage(url: IImage) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (url instanceof HTMLImageElement) {
|
||||
resolve(url);
|
||||
return;
|
||||
}
|
||||
const image = new Image();
|
||||
image.crossOrigin = 'anonymous';
|
||||
image.onload = () => {
|
||||
resolve(image);
|
||||
};
|
||||
image.onerror = () => {
|
||||
reject(new Error('Could not load image at ' + url));
|
||||
};
|
||||
image.src = url instanceof File ? URL.createObjectURL(url) : url;
|
||||
});
|
||||
}
|
||||
private update() {
|
||||
this.updateIconMap();
|
||||
this.updateIconAtlas();
|
||||
|
@ -172,24 +190,6 @@ export default class IconService extends EventEmitter implements IIconService {
|
|||
this.canvasHeight = canvasHeight;
|
||||
}
|
||||
|
||||
private loadImage(url: IImage) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (url instanceof HTMLImageElement) {
|
||||
resolve(url);
|
||||
return;
|
||||
}
|
||||
const image = new Image();
|
||||
image.crossOrigin = 'anonymous';
|
||||
image.onload = () => {
|
||||
resolve(image);
|
||||
};
|
||||
image.onerror = () => {
|
||||
reject(new Error('Could not load image at ' + url));
|
||||
};
|
||||
image.src = url instanceof File ? URL.createObjectURL(url) : url;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 适配小程序
|
||||
* @param url
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
import BaseLayer from '../core/BaseLayer';
|
||||
import { IGeometryLayerStyleOptions } from '../core/interface';
|
||||
import GeometryModels, { GeometryModelType } from './models';
|
||||
|
||||
export default class GeometryLayer extends BaseLayer<
|
||||
IGeometryLayerStyleOptions
|
||||
> {
|
||||
public type: string = 'GeometryLayer';
|
||||
public buildModels() {
|
||||
const modelType = this.getModelType();
|
||||
this.layerModel = new GeometryModels[modelType](this);
|
||||
this.models = this.layerModel.initModels();
|
||||
}
|
||||
public rebuildModels() {
|
||||
this.models = this.layerModel.buildModels();
|
||||
}
|
||||
|
||||
protected getConfigSchema() {
|
||||
return {
|
||||
properties: {
|
||||
opacity: {
|
||||
type: 'number',
|
||||
minimum: 0,
|
||||
maximum: 1,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
protected getDefaultConfig() {
|
||||
const type = this.getModelType();
|
||||
const defaultConfig = {
|
||||
plane: {},
|
||||
};
|
||||
return defaultConfig[type];
|
||||
}
|
||||
|
||||
protected getModelType(): GeometryModelType {
|
||||
return 'plane';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
import PlaneModel from './plane';
|
||||
export type GeometryModelType = 'plane';
|
||||
|
||||
const GeometryModels: { [key in GeometryModelType]: any } = {
|
||||
plane: PlaneModel,
|
||||
};
|
||||
export default GeometryModels;
|
|
@ -0,0 +1,226 @@
|
|||
import {
|
||||
AttributeType,
|
||||
gl,
|
||||
IEncodeFeature,
|
||||
IModelUniform,
|
||||
ITexture2D,
|
||||
} from '@antv/l7-core';
|
||||
import { getMask, isMini } from '@antv/l7-utils';
|
||||
// import { mat4, vec3 } from 'gl-matrix';
|
||||
import BaseModel from '../../core/BaseModel';
|
||||
import { IGeometryLayerStyleOptions } from '../../core/interface';
|
||||
import planeFrag from '../shaders/plane_frag.glsl';
|
||||
import planeVert from '../shaders/plane_vert.glsl';
|
||||
|
||||
function initPlane(
|
||||
width = 1,
|
||||
height = 1,
|
||||
widthSegments = 1,
|
||||
heightSegments = 1,
|
||||
lng = 120,
|
||||
lat = 30,
|
||||
) {
|
||||
// https://github.com/mrdoob/three.js/blob/dev/src/geometries/PlaneGeometry.js
|
||||
const widthHalf = width / 2;
|
||||
const heightHalf = height / 2;
|
||||
|
||||
const gridX = Math.floor(widthSegments);
|
||||
const gridY = Math.floor(heightSegments);
|
||||
|
||||
const gridX1 = gridX + 1;
|
||||
const gridY1 = gridY + 1;
|
||||
|
||||
const segmentWidth = width / gridX;
|
||||
const segmentHeight = height / gridY;
|
||||
|
||||
const indices = [];
|
||||
const positions = [];
|
||||
|
||||
for (let iy = 0; iy < gridY1; iy++) {
|
||||
const y = iy * segmentHeight - heightHalf;
|
||||
|
||||
for (let ix = 0; ix < gridX1; ix++) {
|
||||
const x = ix * segmentWidth - widthHalf;
|
||||
|
||||
positions.push(x + lng, -y + lat, 0);
|
||||
|
||||
positions.push(ix / gridX);
|
||||
positions.push(1 - iy / gridY);
|
||||
}
|
||||
}
|
||||
|
||||
for (let iy = 0; iy < gridY; iy++) {
|
||||
for (let ix = 0; ix < gridX; ix++) {
|
||||
const a = ix + gridX1 * iy;
|
||||
const b = ix + gridX1 * (iy + 1);
|
||||
const c = ix + 1 + gridX1 * (iy + 1);
|
||||
const d = ix + 1 + gridX1 * iy;
|
||||
|
||||
indices.push(a, b, d);
|
||||
indices.push(b, c, d);
|
||||
}
|
||||
}
|
||||
|
||||
return { indices, positions };
|
||||
}
|
||||
|
||||
export default class PlaneModel extends BaseModel {
|
||||
protected texture: ITexture2D;
|
||||
protected mapTexture: string | undefined;
|
||||
public planeGeometryTriangulation = () => {
|
||||
const {
|
||||
width = 1,
|
||||
height = 1,
|
||||
widthSegments = 1,
|
||||
heightSegments = 1,
|
||||
center = [120, 30],
|
||||
} = this.layer.getLayerConfig() as IGeometryLayerStyleOptions;
|
||||
const { indices, positions } = initPlane(
|
||||
width,
|
||||
height,
|
||||
widthSegments,
|
||||
heightSegments,
|
||||
...center,
|
||||
);
|
||||
return {
|
||||
vertices: positions,
|
||||
indices,
|
||||
size: 5,
|
||||
};
|
||||
};
|
||||
|
||||
public getUninforms(): IModelUniform {
|
||||
const {
|
||||
opacity,
|
||||
mapTexture,
|
||||
} = this.layer.getLayerConfig() as IGeometryLayerStyleOptions;
|
||||
if (this.mapTexture !== mapTexture) {
|
||||
this.mapTexture = mapTexture;
|
||||
this.texture.destroy();
|
||||
this.updateTexture(mapTexture);
|
||||
}
|
||||
return {
|
||||
u_opacity: opacity || 1,
|
||||
u_mapFlag: mapTexture ? 1 : 0,
|
||||
|
||||
u_texture: this.texture,
|
||||
// u_ModelMatrix: mat4.translate(mat4.create(), mat4.create(), [1, 0, 0])
|
||||
// u_ModelMatrix: mat4.rotateZ(mat4.create(), mat4.create(), 10)
|
||||
// u_ModelMatrix: mat4.rotateZ(mat4.create(), mat4.create(), 10)
|
||||
// u_ModelMatrix: this.rotateZ()
|
||||
};
|
||||
}
|
||||
|
||||
// public rotateZ(): mat4 {
|
||||
// const res = mat4.create()
|
||||
// const roZero = mat4.translate(mat4.create(), mat4.create(), [-120, 0, -30])
|
||||
// const rotate = mat4.rotateZ(mat4.create(), mat4.create(), 10)
|
||||
// const roOrigin = mat4.translate(mat4.create(), mat4.create(), [120, 0, 30])
|
||||
// mat4.multiply(res, res, roZero)
|
||||
// mat4.multiply(res, res, rotate)
|
||||
// mat4.multiply(res, res, roOrigin)
|
||||
// return res
|
||||
// }
|
||||
|
||||
public clearModels(): void {
|
||||
this.texture.destroy();
|
||||
}
|
||||
|
||||
public initModels() {
|
||||
const {
|
||||
mask = false,
|
||||
maskInside = true,
|
||||
mapTexture,
|
||||
} = this.layer.getLayerConfig() as IGeometryLayerStyleOptions;
|
||||
this.mapTexture = mapTexture;
|
||||
|
||||
const { createTexture2D } = this.rendererService;
|
||||
this.texture = createTexture2D({
|
||||
height: 0,
|
||||
width: 0,
|
||||
});
|
||||
|
||||
this.updateTexture(mapTexture);
|
||||
|
||||
return [
|
||||
this.layer.buildLayerModel({
|
||||
moduleName: 'geometry_plane',
|
||||
vertexShader: planeVert,
|
||||
fragmentShader: planeFrag,
|
||||
triangulation: this.planeGeometryTriangulation,
|
||||
primitive: gl.TRIANGLES,
|
||||
// primitive: gl.POINTS,
|
||||
depth: { enable: false },
|
||||
blend: this.getBlend(),
|
||||
stencil: getMask(mask, maskInside),
|
||||
}),
|
||||
];
|
||||
}
|
||||
public buildModels() {
|
||||
return this.initModels();
|
||||
}
|
||||
|
||||
public updateTexture(mapTexture: string | undefined): void {
|
||||
const { createTexture2D } = this.rendererService;
|
||||
|
||||
if (mapTexture) {
|
||||
const img = new Image();
|
||||
img.crossOrigin = 'anonymous';
|
||||
img.onload = () => {
|
||||
this.texture = createTexture2D({
|
||||
data: img,
|
||||
width: img.width,
|
||||
height: img.height,
|
||||
wrapS: gl.CLAMP_TO_EDGE,
|
||||
wrapT: gl.CLAMP_TO_EDGE,
|
||||
});
|
||||
this.layerService.updateLayerRenderList();
|
||||
this.layerService.renderLayers();
|
||||
};
|
||||
img.src = mapTexture;
|
||||
} else {
|
||||
this.texture = createTexture2D({
|
||||
width: 0,
|
||||
height: 0,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
protected getConfigSchema() {
|
||||
return {
|
||||
properties: {
|
||||
opacity: {
|
||||
type: 'number',
|
||||
minimum: 0,
|
||||
maximum: 1,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected 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]];
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
|
||||
uniform sampler2D u_texture;
|
||||
uniform float u_mapFlag;
|
||||
uniform float u_opacity;
|
||||
|
||||
varying vec3 v_Color;
|
||||
varying vec2 v_uv;
|
||||
|
||||
#pragma include "picking"
|
||||
void main() {
|
||||
// gl_FragColor = vec4(v_Color, u_opacity);
|
||||
if(u_mapFlag > 0.0) {
|
||||
gl_FragColor = texture2D(u_texture, vec2(v_uv.x, 1.0 - v_uv.y));
|
||||
gl_FragColor.a *= u_opacity;
|
||||
|
||||
} else {
|
||||
// gl_FragColor = vec4(v_uv, 0.0, u_opacity);
|
||||
gl_FragColor = vec4(v_Color, u_opacity);
|
||||
}
|
||||
gl_FragColor = filterColor(gl_FragColor);
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
precision highp float;
|
||||
uniform mat4 u_ModelMatrix;
|
||||
|
||||
uniform mat4 u_Mvp;
|
||||
|
||||
attribute vec3 a_Position;
|
||||
attribute vec2 a_Uv;
|
||||
attribute vec3 a_Color;
|
||||
|
||||
varying vec3 v_Color;
|
||||
varying vec2 v_uv;
|
||||
|
||||
#pragma include "projection"
|
||||
#pragma include "picking"
|
||||
void main() {
|
||||
v_Color = a_Color;
|
||||
v_uv = a_Uv;
|
||||
|
||||
vec4 project_pos = project_position(vec4(a_Position, 1.0));
|
||||
// gl_Position = project_common_position_to_clipspace(vec4(project_pos.xy,0., 1.0));
|
||||
|
||||
// float x = 1.0;
|
||||
// float y = 0.0;
|
||||
// float z = 0.0;
|
||||
// mat3 translateMatrix = mat3(
|
||||
// 1.0, 0.0, 0.0
|
||||
// 0.0, 1.0, 0.0
|
||||
// -project_pos.x, -project_pos.y, 1.0
|
||||
// );
|
||||
// mat4 translateMatrix = mat4(
|
||||
// 1.0, 0.0, 0.0, 0.0 ,
|
||||
// 0.0, 1.0, 0.0, 0.0,
|
||||
// 0.0, 0.0, 1.0, 0.0,
|
||||
// 1.0, 0.0, 0.0, 1.0
|
||||
// );
|
||||
|
||||
if(u_CoordinateSystem == COORDINATE_SYSTEM_P20_2) { // gaode2.x
|
||||
gl_Position = u_Mvp * (vec4(project_pos.xy, 0., 1.0));
|
||||
} else {
|
||||
gl_Position = project_common_position_to_clipspace(vec4(project_pos.xy, 0., 1.0));
|
||||
}
|
||||
|
||||
setPickingColor(a_PickingColor);
|
||||
|
||||
gl_PointSize = 10.0;
|
||||
}
|
|
@ -2,6 +2,7 @@ import BaseModel from '../../core/BaseModel';
|
|||
import {
|
||||
CanvasUpdateType,
|
||||
ICanvasLayerStyleOptions,
|
||||
IDrawingOnCanvas,
|
||||
} from '../../core/interface';
|
||||
|
||||
export default class CanvaModel extends BaseModel {
|
||||
|
@ -121,7 +122,12 @@ export default class CanvaModel extends BaseModel {
|
|||
} = this.layer.getLayerConfig() as ICanvasLayerStyleOptions;
|
||||
|
||||
if (this.ctx) {
|
||||
drawingOnCanvas(this.ctx, this.mapService, [viewWidth, viewHeight]);
|
||||
drawingOnCanvas({
|
||||
canvas: this.canvas,
|
||||
ctx: this.ctx,
|
||||
mapService: this.mapService,
|
||||
size: [viewWidth, viewHeight],
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -106,18 +106,37 @@ export interface IImageLayerStyleOptions {
|
|||
maskInside?: boolean;
|
||||
}
|
||||
|
||||
export interface IGeometryLayerStyleOptions {
|
||||
opacity: number;
|
||||
mask?: boolean;
|
||||
maskInside?: boolean;
|
||||
|
||||
mapTexture?: string;
|
||||
|
||||
// planeGeometry
|
||||
center?: [number, number];
|
||||
width?: number;
|
||||
height?: number;
|
||||
|
||||
widthSegments?: number;
|
||||
heightSegments?: number;
|
||||
}
|
||||
|
||||
export enum CanvasUpdateType {
|
||||
'AWAYS' = 'aways',
|
||||
'DRAGEND' = 'dragend',
|
||||
}
|
||||
|
||||
export interface IDrawingOnCanvas {
|
||||
canvas: HTMLCanvasElement;
|
||||
ctx: CanvasRenderingContext2D;
|
||||
mapService: IMapService;
|
||||
size: [number, number];
|
||||
}
|
||||
export interface ICanvasLayerStyleOptions {
|
||||
zIndex: number;
|
||||
update: CanvasUpdateType | string;
|
||||
drawingOnCanvas: (
|
||||
ctx: CanvasRenderingContext2D,
|
||||
mapService: IMapService,
|
||||
size: [number, number],
|
||||
) => void;
|
||||
drawingOnCanvas: (option: IDrawingOnCanvas) => void;
|
||||
}
|
||||
|
||||
export interface IHeatMapLayerStyleOptions {
|
||||
|
|
|
@ -289,6 +289,7 @@ export function RasterImageTriangulation(feature: IEncodeFeature) {
|
|||
size: 5,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算3D弧线顶点
|
||||
* @param feature 映射数据
|
||||
|
|
|
@ -2,6 +2,7 @@ import { container, ILayerPlugin, TYPES } from '@antv/l7-core';
|
|||
import CanvasLayer from './canvas';
|
||||
import CityBuildingLayer from './citybuliding/building';
|
||||
import BaseLayer from './core/BaseLayer';
|
||||
import GeometryLayer from './Geometry';
|
||||
import './glsl.d';
|
||||
import HeatmapLayer from './heatmap';
|
||||
import ImageLayer from './image';
|
||||
|
@ -142,6 +143,7 @@ export {
|
|||
PolygonLayer,
|
||||
LineLayer,
|
||||
CityBuildingLayer,
|
||||
GeometryLayer,
|
||||
CanvasLayer,
|
||||
ImageLayer,
|
||||
ImageTileLayer,
|
||||
|
|
|
@ -33,11 +33,7 @@ export default class Demo extends React.Component {
|
|||
zIndex: 10,
|
||||
update: 'aways',
|
||||
// update: 'dragend',
|
||||
drawingOnCanvas: (
|
||||
ctx: CanvasRenderingContext2D,
|
||||
mapService: IMapService,
|
||||
size: [number, number],
|
||||
) => {
|
||||
drawingOnCanvas: ({ ctx, mapService, size }) => {
|
||||
const [width, height] = size;
|
||||
|
||||
ctx.clearRect(0, 0, width, height);
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
import { GeometryLayer, Scene, IMapService } from '@antv/l7';
|
||||
import { GaodeMap, Mapbox } from '@antv/l7-maps';
|
||||
import * as React from 'react';
|
||||
|
||||
export default class Demo extends React.Component {
|
||||
// @ts-ignore
|
||||
private scene: Scene;
|
||||
|
||||
public componentWillUnmount() {
|
||||
this.scene.destroy();
|
||||
}
|
||||
|
||||
public async componentDidMount() {
|
||||
const scene = new Scene({
|
||||
id: 'map',
|
||||
map: new GaodeMap({
|
||||
// map: new Mapbox({
|
||||
pitch: 0,
|
||||
// style: 'dark',
|
||||
center: [120, 30],
|
||||
zoom: 5,
|
||||
}),
|
||||
});
|
||||
this.scene = scene;
|
||||
|
||||
let layer = new GeometryLayer()
|
||||
.source([{ lng: 120, lat: 30 }], {
|
||||
parser: {
|
||||
type: 'json',
|
||||
x: 'lng',
|
||||
y: 'lat',
|
||||
},
|
||||
})
|
||||
.style({
|
||||
width: 2,
|
||||
height: 2,
|
||||
opacity: 0.8,
|
||||
widthSegments: 3,
|
||||
heightSegments: 3,
|
||||
center: [120, 30],
|
||||
// mapTexture: 'https://gw.alipayobjects.com/mdn/rms_816329/afts/img/A*FG4fT7h5AYMAAAAAAAAAAAAAARQnAQ'
|
||||
})
|
||||
.active({
|
||||
color: '#00f',
|
||||
mix: 0.5,
|
||||
})
|
||||
.color('#ff0');
|
||||
|
||||
scene.on('loaded', () => {
|
||||
scene.addLayer(layer);
|
||||
|
||||
setTimeout(() => {
|
||||
// layer.style({
|
||||
// mapTexture: ""
|
||||
// })
|
||||
layer.style({
|
||||
mapTexture:
|
||||
'https://gw.alipayobjects.com/mdn/rms_816329/afts/img/A*GJhASbfQTK8AAAAAAAAAAAAAARQnAQ',
|
||||
});
|
||||
scene.render();
|
||||
}, 2000);
|
||||
});
|
||||
}
|
||||
|
||||
public render() {
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
id="map"
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -5,10 +5,12 @@ import Ocean from './components/ocean';
|
|||
import Taifong from './components/taifeng'
|
||||
import Radar from './components/radar';
|
||||
import CanvasDemo from './components/canvas';
|
||||
import Plane from './components/plane';
|
||||
|
||||
storiesOf('Object', module)
|
||||
.add('water', () => <Water />)
|
||||
.add('Ocean', () => <Ocean />)
|
||||
.add('Taifong', () => <Taifong />)
|
||||
.add('Radar', () => <Radar/>)
|
||||
.add('CanvasDemo', () => <CanvasDemo/>)
|
||||
.add('CanvasDemo', () => <CanvasDemo/>)
|
||||
.add('Plane', () => <Plane/>)
|
Loading…
Reference in New Issue