feat: 优化风场图层的显示效果 (#1263)

* feat: 优化风场图层效果

* style: lint style
This commit is contained in:
YiQianYao 2022-07-29 17:16:46 +08:00 committed by GitHub
parent 9c9fa85cd3
commit 1a78586ee2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 92 additions and 65 deletions

View File

@ -36,9 +36,10 @@ export default class WindModel extends BaseModel {
// source: 'http://nomads.ncep.noaa.gov', // source: 'http://nomads.ncep.noaa.gov',
private frequency = new FrequencyController(7.2); private frequency = new FrequencyController(7.2);
private cacheZoom: number;
public render() { public render() {
// TODO: 控制风场的平均更新频率 // Tip: 控制风场的平均更新频率
this.frequency.run(() => { this.frequency.run(() => {
this.drawWind(); this.drawWind();
}); });
@ -71,12 +72,13 @@ export default class WindModel extends BaseModel {
height: 0, height: 0,
width: 0, width: 0,
}); });
this.cacheZoom = Math.floor(this.mapService.getZoom());
const glContext = this.rendererService.getGLContext(); const glContext = this.rendererService.getGLContext();
this.imageCoords = source.data.dataArray[0].coordinates as [Point, Point]; this.imageCoords = source.data?.dataArray[0].coordinates as [Point, Point];
source.data.images.then((imageData: HTMLImageElement[]) => { source.data?.images?.then((imageData: HTMLImageElement[]) => {
this.sizeScale = sizeScale; this.sizeScale = sizeScale * this.getZoomScale();
const { imageWidth, imageHeight } = this.getWindSize(); const { imageWidth, imageHeight } = this.getWindSize();
@ -101,11 +103,11 @@ export default class WindModel extends BaseModel {
vMax, vMax,
image: imageData[0], image: imageData[0],
}); });
this.texture?.destroy();
this.texture = createTexture2D({ this.texture = createTexture2D({
data: imageData[0], width: imageWidth,
width: imageData[0].width, height: imageHeight,
height: imageData[0].height,
}); });
this.layerService.updateLayerRenderList(); this.layerService.updateLayerRenderList();
@ -120,7 +122,7 @@ export default class WindModel extends BaseModel {
primitive: gl.TRIANGLES, primitive: gl.TRIANGLES,
depth: { enable: false }, depth: { enable: false },
blend: this.getBlend(), blend: this.getBlend(),
// stencil: getMask(mask, maskInside), stencil: getMask(mask, maskInside),
}); });
return [this.colorModel]; return [this.colorModel];
@ -130,8 +132,14 @@ export default class WindModel extends BaseModel {
const p1 = this.mapService.lngLatToPixel(this.imageCoords[0]); const p1 = this.mapService.lngLatToPixel(this.imageCoords[0]);
const p2 = this.mapService.lngLatToPixel(this.imageCoords[1]); const p2 = this.mapService.lngLatToPixel(this.imageCoords[1]);
const imageWidth = Math.floor((p2.x - p1.x) * this.sizeScale); const imageWidth = Math.min(
const imageHeight = Math.floor((p1.y - p2.y) * this.sizeScale); Math.floor((p2.x - p1.x) * this.sizeScale),
2048,
);
const imageHeight = Math.min(
Math.floor((p1.y - p2.y) * this.sizeScale),
2048,
);
return { imageWidth, imageHeight }; return { imageWidth, imageHeight };
} }
@ -182,6 +190,10 @@ export default class WindModel extends BaseModel {
}); });
} }
private getZoomScale() {
return Math.min(((this.cacheZoom + 4) / 30) * 2, 2);
}
private drawWind() { private drawWind() {
if (this.wind) { if (this.wind) {
const { const {
@ -197,15 +209,23 @@ export default class WindModel extends BaseModel {
rampColors = defaultRampColors, rampColors = defaultRampColors,
sizeScale = 0.5, sizeScale = 0.5,
} = this.layer.getLayerConfig() as IWindLayerStyleOptions; } = this.layer.getLayerConfig() as IWindLayerStyleOptions;
if (typeof sizeScale === 'number' && sizeScale !== this.sizeScale) { let newNumParticles = numParticles;
const currentZoom = Math.floor(this.mapService.getZoom());
if (
(typeof sizeScale === 'number' && sizeScale !== this.sizeScale) ||
currentZoom !== this.cacheZoom
) {
const zoomScale = this.getZoomScale();
this.sizeScale = sizeScale; this.sizeScale = sizeScale;
newNumParticles *= zoomScale;
const { imageWidth, imageHeight } = this.getWindSize(); const { imageWidth, imageHeight } = this.getWindSize();
this.wind.reSize(imageWidth, imageHeight); this.wind.reSize(imageWidth, imageHeight);
this.cacheZoom = currentZoom;
} }
this.wind.updateWindDir(uMin, uMax, vMin, vMax); this.wind.updateWindDir(uMin, uMax, vMin, vMax);
this.wind.updateParticelNum(numParticles); this.wind.updateParticelNum(newNumParticles);
this.wind.updateColorRampTexture(rampColors); this.wind.updateColorRampTexture(rampColors);
@ -227,6 +247,13 @@ export default class WindModel extends BaseModel {
private drawColorMode() { private drawColorMode() {
const { opacity } = this.layer.getLayerConfig() as IWindLayerStyleOptions; const { opacity } = this.layer.getLayerConfig() as IWindLayerStyleOptions;
this.layer.masks.map((m) => {
m.hooks.beforeRenderData.call();
m.hooks.beforeRender.call();
m.render();
m.hooks.afterRender.call();
});
this.colorModel.draw({ this.colorModel.draw({
uniforms: { uniforms: {
u_opacity: opacity || 1.0, u_opacity: opacity || 1.0,

View File

@ -368,7 +368,6 @@ export class Wind {
); );
} }
} }
public draw() { public draw() {
if (this.windData?.image) { if (this.windData?.image) {
const gl = this.gl; const gl = this.gl;
@ -393,11 +392,10 @@ export class Wind {
gl.viewport(0, 0, this.width, this.height); gl.viewport(0, 0, this.width, this.height);
gl.disable(gl.BLEND);
this.drawFullTexture(this.backgroundTexture, this.fadeOpacity); this.drawFullTexture(this.backgroundTexture, this.fadeOpacity);
this.drawParticles(); this.drawParticles();
gl.disable(gl.BLEND);
this.pixels = new Uint8Array(4 * this.width * this.height); this.pixels = new Uint8Array(4 * this.width * this.height);
gl.readPixels( gl.readPixels(
0, 0,

View File

@ -19,64 +19,63 @@ export default class WindMap extends React.Component {
public async componentDidMount() { public async componentDidMount() {
const scene = new Scene({ const scene = new Scene({
id: 'map', id: 'map',
stencil: true,
map: new GaodeMap({ map: new GaodeMap({
center: [40, 30.3628], center: [105, 35],
pitch: 0, pitch: 0,
style: 'normal', style: 'normal',
zoom: 2, zoom: 4,
viewMode: '3D',
}), }),
}); });
this.scene = scene; this.scene = scene;
const pointLayer = new PointLayer({ zIndex: 1 }) const styleOptions = {
.source( uMin: -21.32,
[ uMax: 26.8,
{ vMin: -21.57,
lng: 121.107846, vMax: 21.42,
lat: 30.267069, numParticles: 65535 / 2,
}, fadeOpacity: 0.996,
], rampColors: {
{ 0.0: '#3288bd',
parser: { 0.1: '#66c2a5',
type: 'json', 0.2: '#abdda4',
x: 'lng', 0.3: '#e6f598',
y: 'lat', 0.4: '#fee08b',
}, 0.5: '#fdae61',
}, 0.6: '#f46d43', // f46d43
) 1.0: '#d53e4f',
.shape('circle') },
.color('#f00') sizeScale: 1,
.active(true) };
.size(40)
.style({ // const pointLayer = new PointLayer({ zIndex: 1 })
stroke: '#fff', // .source(
storkeWidth: 2, // [
}); // {
// lng: 121.107846,
// lat: 30.267069,
// },
// ],
// {
// parser: {
// type: 'json',
// x: 'lng',
// y: 'lat',
// },
// },
// )
// .shape('circle')
// .color('#f00')
// .active(true)
// .size(40)
// .style({
// stroke: '#fff',
// storkeWidth: 2,
// });
scene.on('loaded', () => { scene.on('loaded', () => {
scene.addLayer(pointLayer); // scene.addLayer(pointLayer);
const styleOptions = {
uMin: -21.32,
uMax: 26.8,
vMin: -21.57,
vMax: 21.42,
numParticles: 65535,
fadeOpacity: 0.996,
rampColors: {
0.0: '#3288bd',
0.1: '#66c2a5',
0.2: '#abdda4',
0.3: '#e6f598',
0.4: '#fee08b',
0.5: '#fdae61',
0.6: '#f46d43', // f46d43
1.0: '#d53e4f',
},
sizeScale: 0.5,
};
fetch( fetch(
'https://gw.alipayobjects.com/os/basement_prod/d2e0e930-fd44-4fca-8872-c1037b0fee7b.json', 'https://gw.alipayobjects.com/os/basement_prod/d2e0e930-fd44-4fca-8872-c1037b0fee7b.json',
) )
@ -85,6 +84,8 @@ export default class WindMap extends React.Component {
const layer = new WindLayer({ const layer = new WindLayer({
mask: true, mask: true,
maskfence: maskData, maskfence: maskData,
// maskColor: '#fff',
// maskOpacity: 0.5,
}); });
layer layer
.source( .source(
@ -92,7 +93,8 @@ export default class WindMap extends React.Component {
{ {
parser: { parser: {
type: 'image', type: 'image',
extent: [-180, -85, 180, 85], // extent: [-180, -85, 180, 85],
extent: [70, 16, 136, 54],
}, },
}, },
) )