UNPKG

@orca-fe/x-map

Version:
124 lines (123 loc) 5.21 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = require("tslib"); /* eslint-disable no-param-reassign */ const three_1 = require("three"); const supercluster_1 = tslib_1.__importDefault(require("supercluster")); const ThreeObject_1 = tslib_1.__importDefault(require("./ThreeObject")); const heatmap_1 = tslib_1.__importDefault(require("./heatmap")); const coord_1 = require("../../utils/coord"); const private_1 = require("../../utils/private"); const ThreeLayer_1 = tslib_1.__importDefault(require("../ThreeLayer")); function rangeDiff(min, max, value) { if (value < min) return value - min; if (value > max) return value - max; return 0; } function toGeoJSONPoint(data) { return data.map(({ value, lng, lat }) => ({ type: 'Feature', geometry: { type: 'Point', coordinates: [lng, lat], }, properties: { value, lng, lat, }, })); } class HeatmapObject extends ThreeObject_1.default { constructor(options) { super(); this.material = new three_1.MeshBasicMaterial({ side: three_1.FrontSide, opacity: 0.5, transparent: true }); this.canvas = document.createElement('canvas'); this.sc = new supercluster_1.default({ maxZoom: 1, }); this.dom = document.createElement('div'); this.redraw = () => { var _a; if ((_a = this.layer) === null || _a === void 0 ? void 0 : _a.map) { const { map } = this.layer; const { threeCenter } = map; // 取得屏幕尺寸 const { zoom } = map.getViewport(); const bounds = map.getBounds(); const [minMercator, maxMercator] = bounds.map(coord_1.lonLat2Mercator); const mercatorSize = [maxMercator[0] - minMercator[0], maxMercator[1] - minMercator[1]]; const size = map.getSize(); // 根据屏幕尺寸,计算出热力图 canvas 的尺寸 const scale = ((Math.pow(2, zoom) / coord_1.MercatorMax) * Math.min(size[0], size[1])) / 20; const canvasSize = [mercatorSize[0] * scale, mercatorSize[1] * scale]; const [width, height] = canvasSize; [this.canvas.width, this.canvas.height] = canvasSize; this.canvas.style.width = `${this.canvas.width}px`; this.canvas.style.height = `${this.canvas.height}px`; let radius = Math.round(20 * Math.pow(2, rangeDiff(12, 15, zoom))); radius = Math.max(2, radius); const points = this.data.map((p) => { const [x, y] = (0, coord_1.lonLat2Mercator)([p.x, p.y]); return { x: Math.round((x - minMercator[0]) * scale), y: -Math.round((y - maxMercator[1]) * scale), value: p.value, }; }); this.heatmap = heatmap_1.default.create({ container: this.dom, canvas: this.canvas, radius, width, height, }); this.heatmap.setData({ min: 0, max: 100, data: points, }); this.heatmap.repaint(); // 重新调整 平面的尺寸 const center = [ 0.5 * (minMercator[0] + maxMercator[0]) - threeCenter[0], 0.5 * (minMercator[1] + maxMercator[1]) - threeCenter[1], ]; if (this.material.map) this.material.map.needsUpdate = true; this.object3D.position.set(center[0], center[1], 1); this.object3D.scale.set(Math.abs(maxMercator[0] - minMercator[0]), Math.abs(maxMercator[1] - minMercator[1]), 1); if (this.layer instanceof ThreeLayer_1.default) { this.layer.three.render(); } } }; this.redrawDebounce = (0, private_1.debounce)(this.redraw, 300, { maxWait: 1000 }); const { data = [] } = options; this.data = data.map(({ lng, lat, value }) => ({ x: lng, y: lat, value, })); this.sc.load(toGeoJSONPoint(data)); this.object3D = new three_1.Mesh(new three_1.PlaneGeometry(1, 1, 2), this.material); this.material.map = new three_1.CanvasTexture(this.canvas); document.body.append(this.dom); this.dom.style.display = 'none'; this.dom.append(this.canvas); this.heatmap = heatmap_1.default.create({ container: this.dom, canvas: this.canvas, radius: 10, }); } updatePosition() { this.redrawDebounce(); } createObject() { this.redraw(); } } exports.default = HeatmapObject;