threejs_动态heatmap渲染

发布时间 2023-04-21 21:01:49作者: 虎虎生威啊

heatmap > heatmap2d.ts

import {
  Mesh,
  Texture,
  MeshBasicMaterial,
  PlaneGeometry,
  Box3,
  Vector3,
} from 'three';

import Base from '../Base';
import HeatMap, { DataPoint } from 'heatmap-ts';
import { log } from 'console';

export default class HeatMap2D {
  private base: Base;

  constructor() {
    const base = Base.getInstance();
    this.base = base;

    const oCanvas = document.createElement('canvas');
    const heatMap = new HeatMap({
      maxOpacity: 0.6,
      radius: 50,
      blur: 0.9,
      canvas: oCanvas,
      width: this.base.canvasWidth,
      height: this.base.normalHeight,
    });

    // const heatData = [
    //   {
    //     x: window.innerWidth * 0.1,
    //     y: window.innerHeight * 0.1,
    //     value: 80,
    //     radius: 100,
    //   },
    //   {
    //     x: window.innerWidth * 0.2,
    //     y: window.innerHeight * 0.2,
    //     value: 50,
    //     radius: 200,
    //   },
    //   {
    //     x: window.innerWidth * 0.3,
    //     y: window.innerHeight * 0.3,
    //     value: 30,
    //     radius: 50,
    //   },
    //   {
    //     x: window.innerWidth * 0.3,
    //     y: window.innerHeight * 0.4,
    //     value: 30,
    //     radius: 200,
    //   },

    //   {
    //     x: window.innerWidth * 0.5,
    //     y: window.innerHeight * 0.5,
    //     value: 70,
    //     radius: 200,
    //   },
    //   {
    //     x: window.innerWidth * 0.6,
    //     y: window.innerHeight * 0.6,
    //     value: 100,
    //     radius: 20,
    //   },
    //   {
    //     x: window.innerWidth * 0.7,
    //     y: window.innerHeight * 0.7,
    //     value: 80,
    //     radius: 20,
    //   },
    //   {
    //     x: window.innerWidth * 0.8,
    //     y: window.innerHeight * 0.8,
    //     value: 100,
    //     radius: 20,
    //   },
    //   {
    //     x: window.innerWidth * 0.9,
    //     y: window.innerHeight * 0.9,
    //     value: 100,
    //     radius: 20,
    //   },
    //   {
    //     x: window.innerWidth * 1.0,
    //     y: window.innerHeight * 1.0,
    //     value: 100,
    //     radius: 20,
    //   },
    // ];

    const heatData = [
      {
        x: window.innerWidth * 0.1,
        y: window.innerHeight * 0.1,
        value: 80,
        radius: 100,
      },
    ];

    heatMap.setData({
      max: 100,
      min: 1,
      data: heatData,
    });

    let heatMapGeo = new PlaneGeometry(
      this.base.canvasWidth,
      this.base.normalHeight
    );
    let heatMapTexture = new Texture(oCanvas);
    let heatMapMaterial = new MeshBasicMaterial({
      map: heatMapTexture,
      transparent: true,
    });

    heatMapMaterial.map!.needsUpdate = true;

    let heatMapPlane = new Mesh(heatMapGeo, heatMapMaterial);

    // 获取贴图的大小
    const box = new Box3().setFromObject(heatMapPlane);
    const size = box.getSize(new Vector3());

    const xScale = this.base.map.width / size.x;
    const yScale = this.base.map.height / size.y;

    heatMapPlane.scale.set(xScale, yScale, 1);

    heatMapPlane.position.set(
      this.base.map.offsetXY.x,
      this.base.map.offsetXY.y,
      1
    );

    this.base.scene.add(heatMapPlane);
    //
    const newHeatMapData: DataPoint[] = [];
    this.base.time.on('update', () => {
      newHeatMapData.push({
        x:
          this.base.canvasWidth *
          parseFloat((Math.random() * (0.7 - 0.3) + 0.3).toFixed(2)),
        y:
          this.base.normalHeight *
          parseFloat((Math.random() * (0.7 - 0.3) + 0.3).toFixed(2)),

        value: Math.floor(Math.random() * 21) + 10,
        radius: 100,
      });

      if (newHeatMapData.length > 100) {
        newHeatMapData.shift();
      }

      heatMap.setData({
        data: newHeatMapData,
      });

      heatMap.repaint();
      heatMapMaterial.map!.needsUpdate = true;
    });
  }
}