mirror of https://gitee.com/antv-l7/antv-l7
feat: 栅格表达式添加 min/max/log10/log2/计算逻辑&文本更新避让能力完善 (#1594)
* feat: 栅格表示添加 min/max/log10/log2/计算逻辑 * fix: lint format * fix: 文本避让 * fix: utils some error * fix: 文本支持 fontFamily,fontweight,padding 更新 * chore: 图片标注图层空数据改为空图标 * chore: fillImange 默认shape 为透明
This commit is contained in:
parent
faf6c7719f
commit
ffee682445
|
@ -33,14 +33,14 @@ export default () => {
|
||||||
'https://gw.alipayobjects.com/zos/bmw-prod/904d047a-16a5-461b-a921-98fa537fc04a.svg',
|
'https://gw.alipayobjects.com/zos/bmw-prod/904d047a-16a5-461b-a921-98fa537fc04a.svg',
|
||||||
);
|
);
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
const newData = data.map((item: any) => {
|
const newData = data.map((item: any,index: number) => {
|
||||||
item.type = ['00', '01', '02'][Math.floor(Math.random() * 3)];
|
item.type = ['00', '01', '02',''][index % 4];
|
||||||
return item;
|
return item;
|
||||||
});
|
});
|
||||||
const imageLayer = new PointLayer({
|
const imageLayer = new PointLayer({
|
||||||
autoFit:false
|
autoFit:false
|
||||||
})
|
})
|
||||||
.source(newData, {
|
.source(newData.slice(0,4), {
|
||||||
parser: {
|
parser: {
|
||||||
type: 'json',
|
type: 'json',
|
||||||
x: 'longitude',
|
x: 'longitude',
|
||||||
|
@ -52,25 +52,9 @@ export default () => {
|
||||||
})
|
})
|
||||||
.active(false)
|
.active(false)
|
||||||
.size(20);
|
.size(20);
|
||||||
|
|
||||||
scene.addLayer(imageLayer);
|
scene.addLayer(imageLayer);
|
||||||
setInterval(()=>{
|
|
||||||
scene.addImage(
|
|
||||||
'00',
|
|
||||||
'https://gw.alipayobjects.com/mdn/rms_fcd5b3/afts/img/A*g8cUQ7pPT9YAAAAAAAAAAAAAARQnAQ',
|
|
||||||
);
|
|
||||||
scene.addImage(
|
|
||||||
'01',
|
|
||||||
'https://gw.alipayobjects.com/mdn/rms_fcd5b3/afts/img/A*LTcXTLBM7kYAAAAAAAAAAAAAARQnAQ',
|
|
||||||
);
|
|
||||||
scene.addImage(
|
|
||||||
'02',
|
|
||||||
'https://gw.alipayobjects.com/zos/bmw-prod/904d047a-16a5-461b-a921-98fa537fc04a.svg',
|
|
||||||
);
|
|
||||||
const data = newData.slice(0,5+ Math.round(Math.random()*10));
|
|
||||||
imageLayer.setData(data)
|
|
||||||
console.log(imageLayer)
|
|
||||||
console.log('更新')
|
|
||||||
},3000)
|
|
||||||
|
|
||||||
|
|
||||||
}, []);
|
}, []);
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -298,20 +298,8 @@ export default class FontService extends EventEmitter implements IFontService {
|
||||||
}
|
}
|
||||||
|
|
||||||
private getKey() {
|
private getKey() {
|
||||||
return 'key';
|
const { fontFamily, fontWeight } = this.fontOptions;
|
||||||
const {
|
return `${fontFamily}_${fontWeight}`;
|
||||||
fontFamily,
|
|
||||||
fontWeight,
|
|
||||||
fontSize,
|
|
||||||
buffer,
|
|
||||||
sdf,
|
|
||||||
radius,
|
|
||||||
cutoff,
|
|
||||||
} = this.fontOptions;
|
|
||||||
if (sdf) {
|
|
||||||
return `${fontFamily} ${fontWeight} ${fontSize} ${buffer} ${radius} ${cutoff} `;
|
|
||||||
}
|
|
||||||
return `${fontFamily} ${fontWeight} ${fontSize} ${buffer}`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -5,12 +5,7 @@ import 'reflect-metadata';
|
||||||
import { buildIconMaping } from '../../utils/font_util';
|
import { buildIconMaping } from '../../utils/font_util';
|
||||||
import { ITexture2D } from '../renderer/ITexture2D';
|
import { ITexture2D } from '../renderer/ITexture2D';
|
||||||
import { ISceneService } from '../scene/ISceneService';
|
import { ISceneService } from '../scene/ISceneService';
|
||||||
import {
|
import { IIcon, IICONMap, IIconService, IImage } from './IIconService';
|
||||||
IIcon,
|
|
||||||
IICONMap,
|
|
||||||
IIconService,
|
|
||||||
IImage,
|
|
||||||
} from './IIconService';
|
|
||||||
const BUFFER = 3;
|
const BUFFER = 3;
|
||||||
const MAX_CANVAS_WIDTH = 1024;
|
const MAX_CANVAS_WIDTH = 1024;
|
||||||
const imageSize = 64;
|
const imageSize = 64;
|
||||||
|
@ -48,7 +43,7 @@ export default class IconService extends EventEmitter implements IIconService {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
this.updateIconMap(); // 先存储 ID,
|
this.updateIconMap(); // 先存储 ID,
|
||||||
imagedata = await this.loadImage(image) as HTMLImageElement;
|
imagedata = (await this.loadImage(image)) as HTMLImageElement;
|
||||||
const iconImage = this.iconData.find((icon: IIcon) => {
|
const iconImage = this.iconData.find((icon: IIcon) => {
|
||||||
return icon.id === id;
|
return icon.id === id;
|
||||||
});
|
});
|
||||||
|
@ -58,7 +53,6 @@ export default class IconService extends EventEmitter implements IIconService {
|
||||||
iconImage.height = imagedata.height;
|
iconImage.height = imagedata.height;
|
||||||
}
|
}
|
||||||
this.update();
|
this.update();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -12,17 +12,14 @@ import {
|
||||||
import { getMask, PointFillTriangulation } from '@antv/l7-utils';
|
import { getMask, PointFillTriangulation } from '@antv/l7-utils';
|
||||||
import { isNumber } from 'lodash';
|
import { isNumber } from 'lodash';
|
||||||
import BaseModel from '../../core/BaseModel';
|
import BaseModel from '../../core/BaseModel';
|
||||||
import { IPointLayerStyleOptions } from '../../core/interface';
|
import { IPointLayerStyleOptions, SizeUnitType } from '../../core/interface';
|
||||||
// animate pointLayer shader - support animate
|
// animate pointLayer shader - support animate
|
||||||
import waveFillFrag from '../shaders/animate/wave_frag.glsl';
|
import waveFillFrag from '../shaders/animate/wave_frag.glsl';
|
||||||
// static pointLayer shader - not support animate
|
// static pointLayer shader - not support animate
|
||||||
import pointFillFrag from '../shaders/fill_frag.glsl';
|
import pointFillFrag from '../shaders/fill_frag.glsl';
|
||||||
import pointFillVert from '../shaders/fill_vert.glsl';
|
import pointFillVert from '../shaders/fill_vert.glsl';
|
||||||
import { SizeUnitType } from '../../core/interface'
|
|
||||||
|
|
||||||
|
|
||||||
export default class FillModel extends BaseModel {
|
export default class FillModel extends BaseModel {
|
||||||
|
|
||||||
public getUninforms(): IModelUniform {
|
public getUninforms(): IModelUniform {
|
||||||
const {
|
const {
|
||||||
opacity = 1,
|
opacity = 1,
|
||||||
|
@ -100,9 +97,8 @@ export default class FillModel extends BaseModel {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
public getAnimateUniforms(): IModelUniform {
|
public getAnimateUniforms(): IModelUniform {
|
||||||
const {
|
const { animateOption = { enable: false } } =
|
||||||
animateOption = { enable: false },
|
this.layer.getLayerConfig() as ILayerConfig;
|
||||||
} = this.layer.getLayerConfig() as ILayerConfig;
|
|
||||||
return {
|
return {
|
||||||
u_animate: this.animateOption2Array(animateOption),
|
u_animate: this.animateOption2Array(animateOption),
|
||||||
u_time: this.layer.getLayerAnimateTime(),
|
u_time: this.layer.getLayerAnimateTime(),
|
||||||
|
@ -122,7 +118,7 @@ export default class FillModel extends BaseModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
public async initModels(): Promise<IModel[]> {
|
public async initModels(): Promise<IModel[]> {
|
||||||
return await this.buildModels();
|
return this.buildModels();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async buildModels(): Promise<IModel[]> {
|
public async buildModels(): Promise<IModel[]> {
|
||||||
|
@ -139,8 +135,7 @@ export default class FillModel extends BaseModel {
|
||||||
const { frag, vert, type } = this.getShaders(animateOption);
|
const { frag, vert, type } = this.getShaders(animateOption);
|
||||||
|
|
||||||
this.layer.triangulation = PointFillTriangulation;
|
this.layer.triangulation = PointFillTriangulation;
|
||||||
const model = await this.layer
|
const model = await this.layer.buildLayerModel({
|
||||||
.buildLayerModel({
|
|
||||||
moduleName: type,
|
moduleName: type,
|
||||||
vertexShader: vert,
|
vertexShader: vert,
|
||||||
fragmentShader: frag,
|
fragmentShader: frag,
|
||||||
|
@ -162,9 +157,11 @@ export default class FillModel extends BaseModel {
|
||||||
* 根据 animateOption 的值返回对应的 shader 代码
|
* 根据 animateOption 的值返回对应的 shader 代码
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
public getShaders(
|
public getShaders(animateOption: Partial<IAnimateOption>): {
|
||||||
animateOption: Partial<IAnimateOption>,
|
frag: string;
|
||||||
): { frag: string; vert: string; type: string } {
|
vert: string;
|
||||||
|
type: string;
|
||||||
|
} {
|
||||||
if (animateOption.enable) {
|
if (animateOption.enable) {
|
||||||
switch (animateOption.type) {
|
switch (animateOption.type) {
|
||||||
case 'wave':
|
case 'wave':
|
||||||
|
@ -242,9 +239,7 @@ export default class FillModel extends BaseModel {
|
||||||
type: gl.FLOAT,
|
type: gl.FLOAT,
|
||||||
},
|
},
|
||||||
size: 1,
|
size: 1,
|
||||||
update: (
|
update: (feature: IEncodeFeature) => {
|
||||||
feature: IEncodeFeature,
|
|
||||||
) => {
|
|
||||||
const { size = 5 } = feature;
|
const { size = 5 } = feature;
|
||||||
return Array.isArray(size) ? [size[0]] : [size];
|
return Array.isArray(size) ? [size[0]] : [size];
|
||||||
},
|
},
|
||||||
|
@ -264,9 +259,7 @@ export default class FillModel extends BaseModel {
|
||||||
type: gl.FLOAT,
|
type: gl.FLOAT,
|
||||||
},
|
},
|
||||||
size: 1,
|
size: 1,
|
||||||
update: (
|
update: (feature: IEncodeFeature) => {
|
||||||
feature: IEncodeFeature,
|
|
||||||
) => {
|
|
||||||
const { shape = 2 } = feature;
|
const { shape = 2 } = feature;
|
||||||
const shapeIndex = shape2d.indexOf(shape as string);
|
const shapeIndex = shape2d.indexOf(shape as string);
|
||||||
return [shapeIndex];
|
return [shapeIndex];
|
||||||
|
@ -274,6 +267,4 @@ export default class FillModel extends BaseModel {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,12 +11,11 @@ import {
|
||||||
import { getCullFace, getMask } from '@antv/l7-utils';
|
import { getCullFace, getMask } from '@antv/l7-utils';
|
||||||
import { isNumber } from 'lodash';
|
import { isNumber } from 'lodash';
|
||||||
import BaseModel from '../../core/BaseModel';
|
import BaseModel from '../../core/BaseModel';
|
||||||
import { IPointLayerStyleOptions } from '../../core/interface';
|
import { IPointLayerStyleOptions, SizeUnitType } from '../../core/interface';
|
||||||
import { PointFillTriangulation } from '../../core/triangulation';
|
import { PointFillTriangulation } from '../../core/triangulation';
|
||||||
// static pointLayer shader - not support animate
|
// static pointLayer shader - not support animate
|
||||||
import pointFillFrag from '../shaders/image/fillImage_frag.glsl';
|
import pointFillFrag from '../shaders/image/fillImage_frag.glsl';
|
||||||
import pointFillVert from '../shaders/image/fillImage_vert.glsl';
|
import pointFillVert from '../shaders/image/fillImage_vert.glsl';
|
||||||
import { SizeUnitType } from '../../core/interface'
|
|
||||||
|
|
||||||
export default class FillImageModel extends BaseModel {
|
export default class FillImageModel extends BaseModel {
|
||||||
private meter2coord: number = 1;
|
private meter2coord: number = 1;
|
||||||
|
@ -135,18 +134,13 @@ export default class FillImageModel extends BaseModel {
|
||||||
public async initModels(): Promise<IModel[]> {
|
public async initModels(): Promise<IModel[]> {
|
||||||
this.iconService.on('imageUpdate', this.updateTexture);
|
this.iconService.on('imageUpdate', this.updateTexture);
|
||||||
this.updateTexture();
|
this.updateTexture();
|
||||||
return await this.buildModels();
|
return this.buildModels();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public async buildModels(): Promise<IModel[]> {
|
public async buildModels(): Promise<IModel[]> {
|
||||||
const {
|
const { mask = false, maskInside = true } =
|
||||||
mask = false,
|
this.layer.getLayerConfig() as IPointLayerStyleOptions;
|
||||||
maskInside = true,
|
const model = await this.layer.buildLayerModel({
|
||||||
} = this.layer.getLayerConfig() as IPointLayerStyleOptions;
|
|
||||||
const model = await this.layer
|
|
||||||
.buildLayerModel({
|
|
||||||
moduleName: 'pointFillImage',
|
moduleName: 'pointFillImage',
|
||||||
vertexShader: pointFillVert,
|
vertexShader: pointFillVert,
|
||||||
fragmentShader: pointFillFrag,
|
fragmentShader: pointFillFrag,
|
||||||
|
@ -159,8 +153,7 @@ export default class FillImageModel extends BaseModel {
|
||||||
face: getCullFace(this.mapService.version),
|
face: getCullFace(this.mapService.version),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
return [model]
|
return [model];
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public clearModels() {
|
public clearModels() {
|
||||||
|
@ -182,9 +175,7 @@ export default class FillImageModel extends BaseModel {
|
||||||
type: gl.FLOAT,
|
type: gl.FLOAT,
|
||||||
},
|
},
|
||||||
size: 1,
|
size: 1,
|
||||||
update: (
|
update: (feature: IEncodeFeature) => {
|
||||||
feature: IEncodeFeature,
|
|
||||||
) => {
|
|
||||||
const { rotate = 0 } = feature;
|
const { rotate = 0 } = feature;
|
||||||
return Array.isArray(rotate) ? [rotate[0]] : [rotate as number];
|
return Array.isArray(rotate) ? [rotate[0]] : [rotate as number];
|
||||||
},
|
},
|
||||||
|
@ -202,12 +193,10 @@ export default class FillImageModel extends BaseModel {
|
||||||
type: gl.FLOAT,
|
type: gl.FLOAT,
|
||||||
},
|
},
|
||||||
size: 2,
|
size: 2,
|
||||||
update: (
|
update: (feature: IEncodeFeature) => {
|
||||||
feature: IEncodeFeature,
|
|
||||||
) => {
|
|
||||||
const iconMap = this.iconService.getIconMap();
|
const iconMap = this.iconService.getIconMap();
|
||||||
const { shape } = feature;
|
const { shape } = feature;
|
||||||
const { x, y } = iconMap[shape as string] || { x: 0, y: 0 };
|
const { x, y } = iconMap[shape as string] || { x: -64, y: -64 };
|
||||||
return [x, y];
|
return [x, y];
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -256,13 +245,9 @@ export default class FillImageModel extends BaseModel {
|
||||||
type: gl.FLOAT,
|
type: gl.FLOAT,
|
||||||
},
|
},
|
||||||
size: 1,
|
size: 1,
|
||||||
update: (
|
update: (feature: IEncodeFeature) => {
|
||||||
feature: IEncodeFeature,
|
|
||||||
) => {
|
|
||||||
const { size = 5 } = feature;
|
const { size = 5 } = feature;
|
||||||
return Array.isArray(size)
|
return Array.isArray(size) ? [size[0]] : [size as number];
|
||||||
? [size[0]]
|
|
||||||
: [(size as number)];
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -83,7 +83,7 @@ export default class ImageModel extends BaseModel {
|
||||||
public async initModels(): Promise<IModel[]> {
|
public async initModels(): Promise<IModel[]> {
|
||||||
this.iconService.on('imageUpdate', this.updateTexture);
|
this.iconService.on('imageUpdate', this.updateTexture);
|
||||||
this.updateTexture();
|
this.updateTexture();
|
||||||
return await this.buildModels();
|
return this.buildModels();
|
||||||
}
|
}
|
||||||
|
|
||||||
public clearModels() {
|
public clearModels() {
|
||||||
|
@ -93,13 +93,10 @@ export default class ImageModel extends BaseModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
public async buildModels(): Promise<IModel[]> {
|
public async buildModels(): Promise<IModel[]> {
|
||||||
const {
|
const { mask = false, maskInside = true } =
|
||||||
mask = false,
|
this.layer.getLayerConfig() as IPointLayerStyleOptions;
|
||||||
maskInside = true,
|
|
||||||
} = this.layer.getLayerConfig() as IPointLayerStyleOptions;
|
|
||||||
|
|
||||||
const model = await this.layer
|
const model = await this.layer.buildLayerModel({
|
||||||
.buildLayerModel({
|
|
||||||
moduleName: 'pointImage',
|
moduleName: 'pointImage',
|
||||||
vertexShader: pointImageVert,
|
vertexShader: pointImageVert,
|
||||||
fragmentShader: pointImageFrag,
|
fragmentShader: pointImageFrag,
|
||||||
|
@ -110,8 +107,7 @@ export default class ImageModel extends BaseModel {
|
||||||
stencil: getMask(mask, maskInside),
|
stencil: getMask(mask, maskInside),
|
||||||
});
|
});
|
||||||
|
|
||||||
return [model]
|
return [model];
|
||||||
|
|
||||||
}
|
}
|
||||||
protected registerBuiltinAttributes() {
|
protected registerBuiltinAttributes() {
|
||||||
// point layer size;
|
// point layer size;
|
||||||
|
@ -127,9 +123,7 @@ export default class ImageModel extends BaseModel {
|
||||||
type: gl.FLOAT,
|
type: gl.FLOAT,
|
||||||
},
|
},
|
||||||
size: 1,
|
size: 1,
|
||||||
update: (
|
update: (feature: IEncodeFeature) => {
|
||||||
feature: IEncodeFeature,
|
|
||||||
) => {
|
|
||||||
const { size = 5 } = feature;
|
const { size = 5 } = feature;
|
||||||
return Array.isArray(size) ? [size[0]] : [size as number];
|
return Array.isArray(size) ? [size[0]] : [size as number];
|
||||||
},
|
},
|
||||||
|
@ -149,12 +143,10 @@ export default class ImageModel extends BaseModel {
|
||||||
type: gl.FLOAT,
|
type: gl.FLOAT,
|
||||||
},
|
},
|
||||||
size: 2,
|
size: 2,
|
||||||
update: (
|
update: (feature: IEncodeFeature) => {
|
||||||
feature: IEncodeFeature,
|
|
||||||
) => {
|
|
||||||
const iconMap = this.iconService.getIconMap();
|
const iconMap = this.iconService.getIconMap();
|
||||||
const { shape } = feature;
|
const { shape } = feature;
|
||||||
const { x, y } = iconMap[shape as string] || { x: 0, y: 0 };
|
const { x, y } = iconMap[shape as string] || { x: -64, y: -64 }; // 非画布区域,默认的图标改为透明
|
||||||
return [x, y];
|
return [x, y];
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -172,9 +164,10 @@ export default class ImageModel extends BaseModel {
|
||||||
});
|
});
|
||||||
// 更新完纹理后在更新的图层的时候需要更新所有的图层
|
// 更新完纹理后在更新的图层的时候需要更新所有的图层
|
||||||
// this.layer.layerModelNeedUpdate = true;
|
// this.layer.layerModelNeedUpdate = true;
|
||||||
setTimeout(() => { // 延迟渲染
|
setTimeout(() => {
|
||||||
|
// 延迟渲染
|
||||||
this.layerService.throttleRenderLayers();
|
this.layerService.throttleRenderLayers();
|
||||||
})
|
});
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ import {
|
||||||
getMask,
|
getMask,
|
||||||
padBounds,
|
padBounds,
|
||||||
} from '@antv/l7-utils';
|
} from '@antv/l7-utils';
|
||||||
import { isNumber } from 'lodash';
|
import { isEqual, isNumber } from 'lodash';
|
||||||
import BaseModel from '../../core/BaseModel';
|
import BaseModel from '../../core/BaseModel';
|
||||||
import { IPointLayerStyleOptions } from '../../core/interface';
|
import { IPointLayerStyleOptions } from '../../core/interface';
|
||||||
import CollisionIndex from '../../utils/collision-index';
|
import CollisionIndex from '../../utils/collision-index';
|
||||||
|
@ -102,9 +102,6 @@ export default class TextModel extends BaseModel {
|
||||||
opacity = 1.0,
|
opacity = 1.0,
|
||||||
stroke = '#fff',
|
stroke = '#fff',
|
||||||
strokeWidth = 0,
|
strokeWidth = 0,
|
||||||
textAnchor = 'center',
|
|
||||||
textOffset,
|
|
||||||
textAllowOverlap = false,
|
|
||||||
halo = 0.5,
|
halo = 0.5,
|
||||||
gamma = 2.0,
|
gamma = 2.0,
|
||||||
raisingHeight = 0,
|
raisingHeight = 0,
|
||||||
|
@ -116,11 +113,7 @@ export default class TextModel extends BaseModel {
|
||||||
this.textCount = Object.keys(mapping).length;
|
this.textCount = Object.keys(mapping).length;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.preTextStyle = {
|
this.preTextStyle = this.getTextStyle();
|
||||||
textAnchor,
|
|
||||||
textAllowOverlap,
|
|
||||||
textOffset,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
this.dataTextureTest &&
|
this.dataTextureTest &&
|
||||||
|
@ -181,39 +174,27 @@ export default class TextModel extends BaseModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
public async initModels(): Promise<IModel[]> {
|
public async initModels(): Promise<IModel[]> {
|
||||||
|
|
||||||
// 绑定事件
|
// 绑定事件
|
||||||
this.bindEvent();
|
this.bindEvent();
|
||||||
this.extent = this.textExtent();
|
this.extent = this.textExtent();
|
||||||
const {
|
this.preTextStyle = this.getTextStyle();
|
||||||
textAnchor = 'center',
|
return this.buildModels();
|
||||||
textAllowOverlap = true,
|
|
||||||
textOffset,
|
|
||||||
} = this.layer.getLayerConfig() as IPointLayerStyleOptions;
|
|
||||||
this.preTextStyle = {
|
|
||||||
textAnchor,
|
|
||||||
textAllowOverlap,
|
|
||||||
textOffset
|
|
||||||
};
|
|
||||||
return await this.buildModels();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async buildModels(): Promise<IModel[]> {
|
public async buildModels(): Promise<IModel[]> {
|
||||||
const {
|
const {
|
||||||
mask = false,
|
mask = false,
|
||||||
maskInside = true,
|
maskInside = true,
|
||||||
textAllowOverlap = false
|
textAllowOverlap = false,
|
||||||
} = this.layer.getLayerConfig() as IPointLayerStyleOptions;
|
} = this.layer.getLayerConfig() as IPointLayerStyleOptions;
|
||||||
|
|
||||||
|
|
||||||
// this.mapping(); 重复调用
|
// this.mapping(); 重复调用
|
||||||
this.initGlyph(); //
|
this.initGlyph(); //
|
||||||
this.updateTexture();
|
this.updateTexture();
|
||||||
if (!textAllowOverlap) {
|
if (!textAllowOverlap) {
|
||||||
this.filterGlyphs();
|
this.filterGlyphs();
|
||||||
}
|
}
|
||||||
const model = await this.layer
|
const model = await this.layer.buildLayerModel({
|
||||||
.buildLayerModel({
|
|
||||||
moduleName: 'pointText',
|
moduleName: 'pointText',
|
||||||
vertexShader: textVert,
|
vertexShader: textVert,
|
||||||
fragmentShader: textFrag,
|
fragmentShader: textFrag,
|
||||||
|
@ -222,22 +203,44 @@ export default class TextModel extends BaseModel {
|
||||||
blend: this.getBlend(),
|
blend: this.getBlend(),
|
||||||
stencil: getMask(mask, maskInside),
|
stencil: getMask(mask, maskInside),
|
||||||
});
|
});
|
||||||
return [model]
|
return [model];
|
||||||
|
|
||||||
}
|
}
|
||||||
|
// 需要更新的场景
|
||||||
|
// 1. 文本偏移量发生改变
|
||||||
|
// 2. 文本锚点发生改变
|
||||||
|
// 3. 文本允许重叠发生改变
|
||||||
|
// 4. 文本字体发生改变
|
||||||
|
// 5. 文本字体粗细发生改变
|
||||||
public async needUpdate(): Promise<boolean> {
|
public async needUpdate(): Promise<boolean> {
|
||||||
const {
|
const {
|
||||||
textAllowOverlap = false,
|
textAllowOverlap = false,
|
||||||
textAnchor = 'center',
|
textAnchor = 'center',
|
||||||
textOffset
|
textOffset,
|
||||||
} = this.layer.getLayerConfig() as IPointLayerStyleOptions;
|
padding,
|
||||||
const data = this.layer.getEncodedData();
|
fontFamily,
|
||||||
if(JSON.stringify(textOffset) !==JSON.stringify(this.preTextStyle.textOffset) ||textAnchor!==this.preTextStyle.textAnchor ) {
|
fontWeight,
|
||||||
|
} = this.getTextStyle() as IPointLayerStyleOptions;
|
||||||
|
if (
|
||||||
|
!isEqual(padding, this.preTextStyle.padding) ||
|
||||||
|
!isEqual(textOffset, this.preTextStyle.textOffset) ||
|
||||||
|
!isEqual(textAnchor, this.preTextStyle.textAnchor) ||
|
||||||
|
!isEqual(fontFamily, this.preTextStyle.fontFamily) ||
|
||||||
|
!isEqual(fontWeight, this.preTextStyle.fontWeight)
|
||||||
|
) {
|
||||||
await this.mapping();
|
await this.mapping();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if(data.length < 5 || textAllowOverlap) { // 小于不做避让
|
|
||||||
|
// if (
|
||||||
|
// JSON.stringify(textOffset) !==
|
||||||
|
// JSON.stringify(this.preTextStyle.textOffset) ||
|
||||||
|
// textAnchor !== this.preTextStyle.textAnchor
|
||||||
|
// ) {
|
||||||
|
// await this.mapping();
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
if (textAllowOverlap) {
|
||||||
|
// 小于不做避让
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -247,7 +250,8 @@ export default class TextModel extends BaseModel {
|
||||||
const flag = boundsContains(this.extent, extent);
|
const flag = boundsContains(this.extent, extent);
|
||||||
// 文本不能压盖则进行过滤
|
// 文本不能压盖则进行过滤
|
||||||
if (
|
if (
|
||||||
((Math.abs(this.currentZoom - zoom) > 1 || !flag)) ||
|
Math.abs(this.currentZoom - zoom) > 0.5 ||
|
||||||
|
!flag ||
|
||||||
textAllowOverlap !== this.preTextStyle.textAllowOverlap
|
textAllowOverlap !== this.preTextStyle.textAllowOverlap
|
||||||
) {
|
) {
|
||||||
// TODO this.mapping 数据未变化,避让
|
// TODO this.mapping 数据未变化,避让
|
||||||
|
@ -277,9 +281,7 @@ export default class TextModel extends BaseModel {
|
||||||
type: gl.FLOAT,
|
type: gl.FLOAT,
|
||||||
},
|
},
|
||||||
size: 1,
|
size: 1,
|
||||||
update: (
|
update: (feature: IEncodeFeature) => {
|
||||||
feature: IEncodeFeature,
|
|
||||||
) => {
|
|
||||||
const { rotate = 0 } = feature;
|
const { rotate = 0 } = feature;
|
||||||
return Array.isArray(rotate) ? [rotate[0]] : [rotate as number];
|
return Array.isArray(rotate) ? [rotate[0]] : [rotate as number];
|
||||||
},
|
},
|
||||||
|
@ -320,9 +322,7 @@ export default class TextModel extends BaseModel {
|
||||||
type: gl.FLOAT,
|
type: gl.FLOAT,
|
||||||
},
|
},
|
||||||
size: 1,
|
size: 1,
|
||||||
update: (
|
update: (feature: IEncodeFeature) => {
|
||||||
feature: IEncodeFeature,
|
|
||||||
) => {
|
|
||||||
const { size = 12 } = feature;
|
const { size = 12 } = feature;
|
||||||
return Array.isArray(size) ? [size[0]] : [size as number];
|
return Array.isArray(size) ? [size[0]] : [size as number];
|
||||||
},
|
},
|
||||||
|
@ -362,7 +362,7 @@ export default class TextModel extends BaseModel {
|
||||||
this.initGlyph(); //
|
this.initGlyph(); //
|
||||||
this.updateTexture();
|
this.updateTexture();
|
||||||
await this.reBuildModel();
|
await this.reBuildModel();
|
||||||
}
|
};
|
||||||
|
|
||||||
private textExtent(): [[number, number], [number, number]] {
|
private textExtent(): [[number, number], [number, number]] {
|
||||||
const bounds = this.mapService.getBounds();
|
const bounds = this.mapService.getBounds();
|
||||||
|
@ -372,10 +372,7 @@ export default class TextModel extends BaseModel {
|
||||||
* 生成文字纹理(生成文字纹理字典)
|
* 生成文字纹理(生成文字纹理字典)
|
||||||
*/
|
*/
|
||||||
private initTextFont() {
|
private initTextFont() {
|
||||||
const {
|
const { fontWeight, fontFamily } = this.getTextStyle();
|
||||||
fontWeight = '400',
|
|
||||||
fontFamily = 'sans-serif',
|
|
||||||
} = this.layer.getLayerConfig() as IPointLayerStyleOptions;
|
|
||||||
const data = this.layer.getEncodedData();
|
const data = this.layer.getEncodedData();
|
||||||
const characterSet: string[] = [];
|
const characterSet: string[] = [];
|
||||||
data.forEach((item: IEncodeFeature) => {
|
data.forEach((item: IEncodeFeature) => {
|
||||||
|
@ -400,10 +397,7 @@ export default class TextModel extends BaseModel {
|
||||||
* 生成 iconfont 纹理字典
|
* 生成 iconfont 纹理字典
|
||||||
*/
|
*/
|
||||||
private initIconFontTex() {
|
private initIconFontTex() {
|
||||||
const {
|
const { fontWeight, fontFamily } = this.getTextStyle();
|
||||||
fontWeight = '400',
|
|
||||||
fontFamily = 'sans-serif',
|
|
||||||
} = this.layer.getLayerConfig() as IPointLayerStyleOptions;
|
|
||||||
const data = this.layer.getEncodedData();
|
const data = this.layer.getEncodedData();
|
||||||
const characterSet: string[] = [];
|
const characterSet: string[] = [];
|
||||||
data.forEach((item: IEncodeFeature) => {
|
data.forEach((item: IEncodeFeature) => {
|
||||||
|
@ -421,6 +415,33 @@ export default class TextModel extends BaseModel {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private getTextStyle() {
|
||||||
|
const {
|
||||||
|
fontWeight = '400',
|
||||||
|
fontFamily = 'sans-serif',
|
||||||
|
textAllowOverlap = false,
|
||||||
|
padding = [0, 0],
|
||||||
|
textAnchor = 'center',
|
||||||
|
textOffset = [0, 0],
|
||||||
|
opacity = 1,
|
||||||
|
strokeOpacity = 1,
|
||||||
|
strokeWidth = 0,
|
||||||
|
stroke = '#000',
|
||||||
|
} = this.layer.getLayerConfig() as IPointLayerStyleOptions;
|
||||||
|
return {
|
||||||
|
fontWeight,
|
||||||
|
fontFamily,
|
||||||
|
textAllowOverlap,
|
||||||
|
padding,
|
||||||
|
textAnchor,
|
||||||
|
textOffset,
|
||||||
|
opacity,
|
||||||
|
strokeOpacity,
|
||||||
|
strokeWidth,
|
||||||
|
stroke,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 生成文字布局(对照文字纹理字典提取对应文字的位置很好信息)
|
* 生成文字布局(对照文字纹理字典提取对应文字的位置很好信息)
|
||||||
*/
|
*/
|
||||||
|
@ -435,7 +456,7 @@ export default class TextModel extends BaseModel {
|
||||||
const data = this.layer.getEncodedData();
|
const data = this.layer.getEncodedData();
|
||||||
|
|
||||||
this.glyphInfo = data.map((feature: IEncodeFeature) => {
|
this.glyphInfo = data.map((feature: IEncodeFeature) => {
|
||||||
const { shape = '', id, size = 1, } = feature;
|
const { shape = '', id, size = 1 } = feature;
|
||||||
|
|
||||||
const shaping = shapeText(
|
const shaping = shapeText(
|
||||||
shape.toString(),
|
shape.toString(),
|
||||||
|
@ -473,13 +494,10 @@ export default class TextModel extends BaseModel {
|
||||||
* 文字避让 depend on originCentorid
|
* 文字避让 depend on originCentorid
|
||||||
*/
|
*/
|
||||||
private filterGlyphs() {
|
private filterGlyphs() {
|
||||||
const {
|
const { padding = [0, 0], textAllowOverlap = false } =
|
||||||
padding = [0, 0],
|
this.layer.getLayerConfig() as IPointLayerStyleOptions;
|
||||||
textAllowOverlap = false,
|
|
||||||
} = this.layer.getLayerConfig() as IPointLayerStyleOptions;
|
|
||||||
if (textAllowOverlap) {
|
if (textAllowOverlap) {
|
||||||
// 如果允许文本覆盖
|
// 如果允许文本覆盖
|
||||||
// this.layer.setEncodedData(this.glyphInfo);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.glyphInfoMap = {};
|
this.glyphInfoMap = {};
|
||||||
|
@ -491,9 +509,11 @@ export default class TextModel extends BaseModel {
|
||||||
const { shaping, id = 0 } = feature;
|
const { shaping, id = 0 } = feature;
|
||||||
// const centroid = feature.centroid as [number, number];
|
// const centroid = feature.centroid as [number, number];
|
||||||
// const centroid = feature.originCentroid as [number, number];
|
// const centroid = feature.originCentroid as [number, number];
|
||||||
const centroid = (feature.version === 'GAODE2.x'
|
const centroid = (
|
||||||
|
feature.version === 'GAODE2.x'
|
||||||
? feature.originCentroid
|
? feature.originCentroid
|
||||||
: feature.centroid) as [number, number];
|
: feature.centroid
|
||||||
|
) as [number, number];
|
||||||
const size = feature.size as number;
|
const size = feature.size as number;
|
||||||
const fontScale: number = size / 16;
|
const fontScale: number = size / 16;
|
||||||
const pixels = this.mapService.lngLatToContainer(centroid);
|
const pixels = this.mapService.lngLatToContainer(centroid);
|
||||||
|
@ -525,8 +545,6 @@ export default class TextModel extends BaseModel {
|
||||||
const { iconfont = false } = this.layer.getLayerConfig();
|
const { iconfont = false } = this.layer.getLayerConfig();
|
||||||
// 1.生成文字纹理(或是生成 iconfont)
|
// 1.生成文字纹理(或是生成 iconfont)
|
||||||
iconfont ? this.initIconFontTex() : this.initTextFont();
|
iconfont ? this.initIconFontTex() : this.initTextFont();
|
||||||
// this.initTextFont();
|
|
||||||
|
|
||||||
// 2.生成文字布局
|
// 2.生成文字布局
|
||||||
this.generateGlyphLayout(iconfont);
|
this.generateGlyphLayout(iconfont);
|
||||||
}
|
}
|
||||||
|
@ -550,13 +568,10 @@ export default class TextModel extends BaseModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
private async reBuildModel() {
|
private async reBuildModel() {
|
||||||
const {
|
const { mask = false, maskInside = true } =
|
||||||
mask = false,
|
this.layer.getLayerConfig() as IPointLayerStyleOptions;
|
||||||
maskInside = true,
|
|
||||||
} = this.layer.getLayerConfig() as IPointLayerStyleOptions;
|
|
||||||
this.filterGlyphs();
|
this.filterGlyphs();
|
||||||
const model = await this.layer
|
const model = await this.layer.buildLayerModel({
|
||||||
.buildLayerModel({
|
|
||||||
moduleName: 'pointText',
|
moduleName: 'pointText',
|
||||||
vertexShader: textVert,
|
vertexShader: textVert,
|
||||||
fragmentShader: textFrag,
|
fragmentShader: textFrag,
|
||||||
|
|
|
@ -212,7 +212,7 @@ layer.scale('value'); // L7 能够自动推断为 identify
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
|
|
||||||
pointLayer.size('type', (type) => {
|
pointLayer.filter('type', (type) => {
|
||||||
// 回调函数
|
// 回调函数
|
||||||
if (type === 'a') {
|
if (type === 'a') {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
import { IRasterData } from '../../interface';
|
import { IRasterData } from '../../interface';
|
||||||
|
|
||||||
/** 数学运算 根据计算表达式进行数学运算
|
/** 数学运算 根据计算表达式进行数学运算
|
||||||
|
@ -19,21 +18,41 @@ import { IRasterData } from '../../interface';
|
||||||
*/
|
*/
|
||||||
export function mathematical(symbol: string, n1: number, n2: number) {
|
export function mathematical(symbol: string, n1: number, n2: number) {
|
||||||
switch (symbol) {
|
switch (symbol) {
|
||||||
case '+': return n1 + n2;
|
case '+':
|
||||||
case '-': return n1 - n2;
|
return n1 + n2;
|
||||||
case '*': return n1 * n2;
|
case '-':
|
||||||
case '/': return n1 / n2;
|
return n1 - n2;
|
||||||
case '%': return n1 % n2;
|
case '*':
|
||||||
|
return n1 * n2;
|
||||||
case '^': return Math.pow(n1, n2);
|
case '/':
|
||||||
case 'abs': return Math.abs(n1);
|
return n1 / n2;
|
||||||
case 'floor': return Math.floor(n1);
|
case '%':
|
||||||
case 'round': return Math.round(n1);
|
return n1 % n2;
|
||||||
case 'ceil': return Math.ceil(n1);
|
|
||||||
case 'sin': return Math.sin(n1);
|
|
||||||
case 'cos': return Math.cos(n1);
|
|
||||||
case 'atan': return (n2 === -1) ? Math.atan(n1): Math.atan2(n1, n2);
|
|
||||||
|
|
||||||
|
case '^':
|
||||||
|
return Math.pow(n1, n2);
|
||||||
|
case 'abs':
|
||||||
|
return Math.abs(n1);
|
||||||
|
case 'floor':
|
||||||
|
return Math.floor(n1);
|
||||||
|
case 'round':
|
||||||
|
return Math.round(n1);
|
||||||
|
case 'ceil':
|
||||||
|
return Math.ceil(n1);
|
||||||
|
case 'sin':
|
||||||
|
return Math.sin(n1);
|
||||||
|
case 'cos':
|
||||||
|
return Math.cos(n1);
|
||||||
|
case 'atan':
|
||||||
|
return n2 === -1 ? Math.atan(n1) : Math.atan2(n1, n2);
|
||||||
|
case 'min':
|
||||||
|
return Math.min(n1, n2);
|
||||||
|
case 'max':
|
||||||
|
return Math.max(n1, n2);
|
||||||
|
case 'log10':
|
||||||
|
return Math.log(n1);
|
||||||
|
case 'log2':
|
||||||
|
return Math.log2(n1);
|
||||||
default:
|
default:
|
||||||
console.warn('Calculate symbol err! Return default 0');
|
console.warn('Calculate symbol err! Return default 0');
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -47,7 +66,7 @@ export function mathematical(symbol: string, n1: number, n2: number) {
|
||||||
*/
|
*/
|
||||||
export function calculate(express: any[], bandsData: IRasterData[]) {
|
export function calculate(express: any[], bandsData: IRasterData[]) {
|
||||||
const { width, height } = bandsData[0];
|
const { width, height } = bandsData[0];
|
||||||
const dataArray = bandsData.map(band => band.rasterData) as Uint8Array[];
|
const dataArray = bandsData.map((band) => band.rasterData) as Uint8Array[];
|
||||||
const length = width * height;
|
const length = width * height;
|
||||||
const rasterData = [];
|
const rasterData = [];
|
||||||
const originExp = JSON.stringify(express);
|
const originExp = JSON.stringify(express);
|
||||||
|
@ -63,7 +82,6 @@ export function calculate(express: any[], bandsData: IRasterData[]) {
|
||||||
const result = calculateExpress(exp);
|
const result = calculateExpress(exp);
|
||||||
rasterData.push(result);
|
rasterData.push(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return rasterData as unknown as Uint8Array;
|
return rasterData as unknown as Uint8Array;
|
||||||
}
|
}
|
||||||
|
@ -76,11 +94,19 @@ type IExpress = any[];
|
||||||
* @param dataArray
|
* @param dataArray
|
||||||
* @param index
|
* @param index
|
||||||
*/
|
*/
|
||||||
export function spellExpress(express: IExpress, dataArray: Uint8Array[], index: number) {
|
export function spellExpress(
|
||||||
|
express: IExpress,
|
||||||
|
dataArray: Uint8Array[],
|
||||||
|
index: number,
|
||||||
|
) {
|
||||||
/**
|
/**
|
||||||
* 用户直接指定波段数值,无需计算
|
* 用户直接指定波段数值,无需计算
|
||||||
*/
|
*/
|
||||||
if(express.length === 2 && express[0] === 'band' && typeof express[1] === 'number') {
|
if (
|
||||||
|
express.length === 2 &&
|
||||||
|
express[0] === 'band' &&
|
||||||
|
typeof express[1] === 'number'
|
||||||
|
) {
|
||||||
try {
|
try {
|
||||||
return dataArray[express[1]][index];
|
return dataArray[express[1]][index];
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
@ -103,13 +129,13 @@ export function spellExpress(express: IExpress, dataArray: Uint8Array[], index:
|
||||||
spellExpress(e, dataArray, index);
|
spellExpress(e, dataArray, index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function formatExpress(express: IExpress) {
|
export function formatExpress(express: IExpress) {
|
||||||
const [symbol1, symbol2 = -1, symbol3 = -1] = express;
|
const [symbol1, symbol2 = -1, symbol3 = -1] = express;
|
||||||
if (symbol1 === undefined) {
|
if (symbol1 === undefined) {
|
||||||
console.warn('Express err!')
|
console.warn('Express err!');
|
||||||
return ['+', 0, 0];
|
return ['+', 0, 0];
|
||||||
}
|
}
|
||||||
const symbol = symbol1.replace(/\s+/g, '');
|
const symbol = symbol1.replace(/\s+/g, '');
|
||||||
|
|
|
@ -2,7 +2,7 @@ import * as d3 from 'd3-color';
|
||||||
import { Context } from 'vm';
|
import { Context } from 'vm';
|
||||||
import { $window, isMini } from './mini-adapter';
|
import { $window, isMini } from './mini-adapter';
|
||||||
export interface IColorRamp {
|
export interface IColorRamp {
|
||||||
type?: 'cat' | 'linear' | 'quantize' | 'custom'
|
type?: 'cat' | 'linear' | 'quantize' | 'custom';
|
||||||
positions: number[];
|
positions: number[];
|
||||||
colors: string[];
|
colors: string[];
|
||||||
}
|
}
|
||||||
|
@ -74,7 +74,6 @@ export function generateColorRamp(
|
||||||
ctx.fillStyle = gradient;
|
ctx.fillStyle = gradient;
|
||||||
ctx.fillRect(0, 0, 256, 1);
|
ctx.fillRect(0, 0, 256, 1);
|
||||||
|
|
||||||
|
|
||||||
if (!isMini) {
|
if (!isMini) {
|
||||||
data = ctx.getImageData(0, 0, 256, 1).data;
|
data = ctx.getImageData(0, 0, 256, 1).data;
|
||||||
// 使用 createImageData 替代 new ImageData、兼容 IE11
|
// 使用 createImageData 替代 new ImageData、兼容 IE11
|
||||||
|
@ -115,7 +114,6 @@ export function generateLinearRamp(
|
||||||
|
|
||||||
for (let i = 0; i < colorRamp.colors.length; ++i) {
|
for (let i = 0; i < colorRamp.colors.length; ++i) {
|
||||||
const value = Math.max((colorRamp.positions[i] - domain[0]) / step, 0);
|
const value = Math.max((colorRamp.positions[i] - domain[0]) / step, 0);
|
||||||
console.log(value)
|
|
||||||
gradient.addColorStop(value, colorRamp.colors[i]);
|
gradient.addColorStop(value, colorRamp.colors[i]);
|
||||||
}
|
}
|
||||||
ctx.fillStyle = gradient;
|
ctx.fillStyle = gradient;
|
||||||
|
@ -127,16 +125,11 @@ export function generateLinearRamp(
|
||||||
canvas = null;
|
canvas = null;
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
ctx = null;
|
ctx = null;
|
||||||
return imageData
|
return imageData;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// 枚举类型
|
// 枚举类型
|
||||||
export function generateCatRamp(
|
export function generateCatRamp(colorRamp: IColorRamp): ImageData | IImagedata {
|
||||||
colorRamp: IColorRamp,
|
|
||||||
): ImageData | IImagedata {
|
|
||||||
|
|
||||||
let canvas = $window.document.createElement('canvas');
|
let canvas = $window.document.createElement('canvas');
|
||||||
let ctx = canvas.getContext('2d') as CanvasRenderingContext2D;
|
let ctx = canvas.getContext('2d') as CanvasRenderingContext2D;
|
||||||
canvas.width = 256;
|
canvas.width = 256;
|
||||||
|
@ -144,12 +137,12 @@ export function generateCatRamp(
|
||||||
const imageData = ctx.createImageData(256, 1);
|
const imageData = ctx.createImageData(256, 1);
|
||||||
imageData.data.fill(0);
|
imageData.data.fill(0);
|
||||||
colorRamp.positions.forEach((p: number, index: number) => {
|
colorRamp.positions.forEach((p: number, index: number) => {
|
||||||
const colorArray = rgb2arr(colorRamp.colors[index])
|
const colorArray = rgb2arr(colorRamp.colors[index]);
|
||||||
imageData.data[p * 4 + 0] = colorArray[0] * 255;
|
imageData.data[p * 4 + 0] = colorArray[0] * 255;
|
||||||
imageData.data[p * 4 + 1] = colorArray[1] * 255;
|
imageData.data[p * 4 + 1] = colorArray[1] * 255;
|
||||||
imageData.data[p * 4 + 2] = colorArray[2] * 255;
|
imageData.data[p * 4 + 2] = colorArray[2] * 255;
|
||||||
imageData.data[p * 4 + 3] = colorArray[3] * 255;
|
imageData.data[p * 4 + 3] = colorArray[3] * 255;
|
||||||
})
|
});
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
canvas = null;
|
canvas = null;
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
|
@ -163,7 +156,7 @@ export function generateQuantizeRamp(
|
||||||
): ImageData | IImagedata {
|
): ImageData | IImagedata {
|
||||||
let canvas = $window.document.createElement('canvas');
|
let canvas = $window.document.createElement('canvas');
|
||||||
let ctx = canvas.getContext('2d') as CanvasRenderingContext2D;
|
let ctx = canvas.getContext('2d') as CanvasRenderingContext2D;
|
||||||
ctx.globalAlpha = 1.0
|
ctx.globalAlpha = 1.0;
|
||||||
canvas.width = 256;
|
canvas.width = 256;
|
||||||
canvas.height = 1;
|
canvas.height = 1;
|
||||||
const step = 256 / colorRamp.colors.length; // TODO 精度问题
|
const step = 256 / colorRamp.colors.length; // TODO 精度问题
|
||||||
|
@ -176,14 +169,12 @@ export function generateQuantizeRamp(
|
||||||
ctx.moveTo(i * step, 0); // positioned at 50,25
|
ctx.moveTo(i * step, 0); // positioned at 50,25
|
||||||
ctx.lineTo((i + 1) * step, 0);
|
ctx.lineTo((i + 1) * step, 0);
|
||||||
ctx.stroke();
|
ctx.stroke();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = ctx.getImageData(0, 0, 256, 1).data;
|
const data = ctx.getImageData(0, 0, 256, 1).data;
|
||||||
// 使用 createImageData 替代 new ImageData、兼容 IE11
|
// 使用 createImageData 替代 new ImageData、兼容 IE11
|
||||||
const imageData = toIEIMageData(ctx, data);
|
const imageData = toIEIMageData(ctx, data);
|
||||||
|
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
canvas = null;
|
canvas = null;
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
|
@ -197,25 +188,25 @@ export function generateCustomRamp(
|
||||||
colorRamp: IColorRamp,
|
colorRamp: IColorRamp,
|
||||||
domain: [number, number],
|
domain: [number, number],
|
||||||
): ImageData | IImagedata {
|
): ImageData | IImagedata {
|
||||||
|
|
||||||
let canvas = $window.document.createElement('canvas');
|
let canvas = $window.document.createElement('canvas');
|
||||||
let ctx = canvas.getContext('2d') as CanvasRenderingContext2D;
|
let ctx = canvas.getContext('2d') as CanvasRenderingContext2D;
|
||||||
ctx.globalAlpha = 1.0
|
ctx.globalAlpha = 1.0;
|
||||||
canvas.width = 256;
|
canvas.width = 256;
|
||||||
canvas.height = 1;
|
canvas.height = 1;
|
||||||
const step = domain[1] - domain[0];
|
const step = domain[1] - domain[0];
|
||||||
if (colorRamp.positions.length - colorRamp.colors.length !== 1) {
|
if (colorRamp.positions.length - colorRamp.colors.length !== 1) {
|
||||||
console.warn('positions 的数字个数应当比 colors 的样式多一个,poisitions 的首尾值一般为数据的最大最新值')
|
console.warn(
|
||||||
|
'positions 的数字个数应当比 colors 的样式多一个,poisitions 的首尾值一般为数据的最大最新值',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let i = 0; i < colorRamp.colors.length; i++) {
|
for (let i = 0; i < colorRamp.colors.length; i++) {
|
||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
ctx.lineWidth = 2;
|
ctx.lineWidth = 2;
|
||||||
ctx.strokeStyle = colorRamp.colors[i];
|
ctx.strokeStyle = colorRamp.colors[i];
|
||||||
ctx.moveTo((colorRamp.positions[i] - domain[0]) / step * 255, 0); // positioned at 50,25
|
ctx.moveTo(((colorRamp.positions[i] - domain[0]) / step) * 255, 0); // positioned at 50,25
|
||||||
ctx.lineTo((colorRamp.positions[i + 1]- domain[0]) / step * 255, 0);
|
ctx.lineTo(((colorRamp.positions[i + 1] - domain[0]) / step) * 255, 0);
|
||||||
ctx.stroke();
|
ctx.stroke();
|
||||||
|
|
||||||
}
|
}
|
||||||
const data = ctx.getImageData(0, 0, 256, 1).data;
|
const data = ctx.getImageData(0, 0, 256, 1).data;
|
||||||
const imageData = toIEIMageData(ctx, data);
|
const imageData = toIEIMageData(ctx, data);
|
||||||
|
@ -233,15 +224,15 @@ function toIEIMageData(ctx: Context, data: Uint8ClampedArray) {
|
||||||
imageData.data[i + 2] = data[i + 2];
|
imageData.data[i + 2] = data[i + 2];
|
||||||
imageData.data[i + 3] = data[i + 3];
|
imageData.data[i + 3] = data[i + 3];
|
||||||
}
|
}
|
||||||
return imageData
|
return imageData;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getDefaultDomain(rampColors: IColorRamp) {
|
export function getDefaultDomain(rampColors: IColorRamp) {
|
||||||
switch (rampColors.type) {
|
switch (rampColors.type) {
|
||||||
case 'cat':
|
case 'cat':
|
||||||
return [0,255]
|
return [0, 255];
|
||||||
default:
|
default:
|
||||||
[0,1]
|
[0, 1];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
|
@ -1,22 +1,19 @@
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
export { djb2hash, BKDRHash } from './hash';
|
|
||||||
|
|
||||||
import * as DOM from './dom';
|
|
||||||
import * as Satistics from './statistics';
|
|
||||||
|
|
||||||
export { DOM, Satistics };
|
|
||||||
|
|
||||||
export * from './mini-adapter/index';
|
|
||||||
export * from './ajax';
|
export * from './ajax';
|
||||||
export * from './geo';
|
|
||||||
export * from './lru_cache';
|
|
||||||
export * from './event';
|
|
||||||
export * from './color';
|
|
||||||
export * from './anchor';
|
export * from './anchor';
|
||||||
export * from './stencli';
|
export * from './color';
|
||||||
export * from './worker-helper';
|
|
||||||
export * from './cull';
|
export * from './cull';
|
||||||
|
export * as DOM from './dom';
|
||||||
export * from './env';
|
export * from './env';
|
||||||
export * from './tileset-manager';
|
export * from './event';
|
||||||
export * from './workers/triangulation';
|
export * from './geo';
|
||||||
|
export { BKDRHash, djb2hash } from './hash';
|
||||||
export * from './lineAtOffset';
|
export * from './lineAtOffset';
|
||||||
|
export * from './lru_cache';
|
||||||
|
export * from './mini-adapter/index';
|
||||||
|
export * as Satistics from './statistics';
|
||||||
|
export * from './stencli';
|
||||||
|
export * from './tileset-manager';
|
||||||
|
export * from './worker-helper';
|
||||||
|
export * from './workers/triangulation';
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue