From ea0e544ff9116f9c3191e2711f5242c7da9d0f26 Mon Sep 17 00:00:00 2001 From: "mipha.ly" <mipha.ly@alibaba-inc.com> Date: Thu, 14 Mar 2019 14:35:59 +0800 Subject: [PATCH] =?UTF-8?q?fix(heat-map):=20=E6=B8=B2=E6=9F=93=E9=80=BB?= =?UTF-8?q?=E8=BE=91=20&=20bbox?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- demos/heatmap.html | 65 +++++++++++++++++++++++++++-- src/core/layer.js | 10 ++++- src/layer/heatmapLayer.js | 8 +++- src/layer/render/heatmap/heatmap.js | 44 +++++++++++-------- 4 files changed, 104 insertions(+), 23 deletions(-) diff --git a/demos/heatmap.html b/demos/heatmap.html index 23a2d6464a..84bd74387e 100644 --- a/demos/heatmap.html +++ b/demos/heatmap.html @@ -18,10 +18,69 @@ <script src="./assets/dat.gui.min.js"></script> <script src="../build/L7.js"></script> <script> +const data1 = { + type: 'FeatureCollection', + features: [{ + type: 'Feature', + properties: { + value: 550, + address: '浙江省' + }, + geometry: { + type: 'Point', + coordinates: [ 120.5751451280382, 29.98157497829861 ] + } + }, + { + type: 'Feature', + properties: { + value: 2100, + address: '广东省' + }, + geometry: { + type: 'Point', + coordinates: [ 113.818805, 22.664838 ] + } + }, + { + type: 'Feature', + properties: { + value: 420, + address: '北京' + }, + geometry: { + type: 'Point', + coordinates: [ 116.40899441189237, 39.940829535590275 ] + } + }, + { + type: 'Feature', + properties: { + value: 2000, + address: '辽宁省' + }, + geometry: { + type: 'Point', + coordinates: [ 122.689323, 40.80727 ] + } + }, + { + type: 'Feature', + properties: { + value: 7000, + address: '河南省' + }, + geometry: { + type: 'Point', + coordinates: [ 112.903898, 34.075266 ] + } + } + ] +}; const scene = new L7.Scene({ id: 'map', mapStyle: 'dark', // 样式URL - center: [ -155, 60 ], + center: [ 120.5751451280382, 29.98157497829861 ], pitch: 0, zoom: 4.5 }); @@ -31,8 +90,8 @@ scene.on('loaded', () => { scene.HeatmapLayer({ zIndex: 2 }) - .source(data) - .size('mag', [ 0, 1 ]) // weight映射通道 + .source(data1) + .size('value', [ 0, 1 ]) // weight映射通道 .style({ intensity: 3, radius: 20, diff --git a/src/core/layer.js b/src/core/layer.js index 90f49cc2d3..ef474d51a0 100644 --- a/src/core/layer.js +++ b/src/core/layer.js @@ -89,7 +89,10 @@ export default class Layer extends Base { const zoom = this.scene.getZoom(); object.material.setUniformsValue('u_time', this.scene._engine.clock.getElapsedTime()); object.material.setUniformsValue('u_zoom', zoom); + }; + object.onAfterRender = () => { // 每次渲染后改变状态 + this.afterRender(); }; // 更新 if (this._needUpdateFilter) { // 动态更新数据过滤 @@ -120,7 +123,6 @@ export default class Layer extends Base { // }).then(data => { // console.log(data); // }); - return this; } color(field, values) { @@ -624,7 +626,11 @@ export default class Layer extends Base { this.scene.off('zoomchange', this._zoomchangeHander); this.destroyed = true; } - _preRender() { + preRender() { + + } + + afterRender() { } } diff --git a/src/layer/heatmapLayer.js b/src/layer/heatmapLayer.js index e6e1bf5724..203814e5b6 100644 --- a/src/layer/heatmapLayer.js +++ b/src/layer/heatmapLayer.js @@ -2,7 +2,7 @@ import Layer from '../core/layer'; import gridBuffer from '../geom/buffer/heatmap/grid'; import DrawGrid from './render/heatmap/gird'; import DrawHexagon from './render/heatmap/hexagon'; -import drawHeatmap from './render/heatmap/heatmap'; +import { drawHeatmap, updateIntensityPass } from './render/heatmap/heatmap'; import hexagonBuffer from '../geom/buffer/heatmap/hexagon'; export default class HeatMapLayer extends Layer { @@ -56,4 +56,10 @@ export default class HeatMapLayer extends Layer { this.add(girdMesh); } + afterRender() { + if (this.shapeType !== 'grid' || this.shapeType !== 'hexagon') { + updateIntensityPass(this); + } + } + } diff --git a/src/layer/render/heatmap/heatmap.js b/src/layer/render/heatmap/heatmap.js index 07b7bb4cd4..72c90bbdb6 100644 --- a/src/layer/render/heatmap/heatmap.js +++ b/src/layer/render/heatmap/heatmap.js @@ -4,8 +4,9 @@ import { HeatmapIntensityMaterial, HeatmapColorizeMaterial } from '../../../geom import Renderpass from '../../../core/engine/renderpass'; import * as THREE from '../../../core/three'; -export default function drawHeatmap(layer) { +export function drawHeatmap(layer) { const bbox = calBoundingBox(layer.layerData); + layer.dataBbox = bbox; const colors = layer.get('styleOptions').rampColors; layer.colorRamp = createColorRamp(colors); createIntensityPass(layer, bbox); @@ -33,15 +34,15 @@ function createIntensityPass(layer, bbox) { zoom: layer.scene.getZoom() }); const mesh = new THREE.Mesh(geometry, material); - // set camera + // set camera const passOrth = new THREE.OrthographicCamera(bbox.width / -2, bbox.width / 2, bbox.height / 2, bbox.height / -2, 1, 10000); passOrth.position.set(bbox.minX + bbox.width / 2, bbox.minY + bbox.height / 2, 1000); - // renderpass + // renderpass const renderer = layer.scene._engine._renderer; // get extension for bilinear texture interpolation:https://threejs.org/docs/#api/en/textures/DataTexture - const gl = renderer.domElement.getContext('webgl') || + /* const gl = renderer.domElement.getContext('webgl') || renderer.domElement.getContext('experimental-webgl'); - gl.getExtension('OES_texture_float_linear'); + gl.getExtension('OES_texture_float_linear');*/ const renderpass = new Renderpass({ renderer, camera: passOrth, @@ -66,18 +67,21 @@ function createIntensityPass(layer, bbox) { renderpass.add(mesh); renderpass.render(); layer.intensityPass = renderpass; - const scene = layer.scene; - render(); - function render() { - requestAnimationFrame(render); - const zoom = scene.getZoom(); - mesh.material.uniforms.u_zoom.value = zoom; - const passWidth = Math.min(10000, Math.pow(zoom, 2.0) * 300); - const passHeight = passWidth * (bbox.height / bbox.width); - renderpass.pass.setSize(passWidth, passHeight); - renderpass.render(); - } + layer.intensityMesh = mesh; + updateIntensityPass(layer); } + +export function updateIntensityPass(layer) { + const mesh = layer.intensityMesh; + const zoom = layer.scene.getZoom(); + const bbox = layer.dataBbox; + mesh.material.uniforms.u_zoom.value = zoom; + const passWidth = Math.min(5000, Math.pow(zoom, 2.0) * 300); + const passHeight = passWidth * (bbox.height / bbox.width); + layer.intensityPass.pass.setSize(passWidth, passHeight); + layer.intensityPass.render(); +} + function createColorizePass(layer, bbox) { // create plane geometry const geometery = new THREE.PlaneBufferGeometry(bbox.width, bbox.height); @@ -108,9 +112,16 @@ function calBoundingBox(data) { maxY = p[1]; } } + + minX -= ((maxX - minX) * 0.5); + maxX += ((maxX - minX) * 0.5); + minY -= ((maxY - minY) * 0.5); + maxY -= ((maxY - minY) * 0.5); + const width = maxX - minX; const height = maxY - minY; + return { minX, maxX, @@ -120,4 +131,3 @@ function calBoundingBox(data) { height }; } -