【Three.js热力点图】

实现效果

在这里插入图片描述
在这里插入图片描述

1、基本配置

首先需要配置基本场景、相机、渲染器

import * as THREE from 'three'
// 场景
this.scene = new THREE.Scene();
// 正交相机
this.camera = new THREE.OrthographicCamera(-1, 1, 1, -1, 1, 10000000);
this.camera.position.set(0, 0, 5.5);
// 渲染器
this.renderer = new THREE.WebGLRenderer();
this.renderer.setSize(width, height);
this.renderer.setClearColor('#383838', 1);
dom.appendChild(this.renderer.domElement);
//配置环境光
this.ambientLight(this.scene)
 // 开始渲染
const animate = () => {
   requestAnimationFrame(animate);
   this.controls.update();
   // 渲染主场景
   this.renderer.clear();
   this.renderer.render(this.scene, this.camera);
   // 渲染坐标轴场景
   this.renderer.autoClear = false; // 不清除颜色缓存
   this.renderer.clearDepth(); // 清除深度缓存
   // 设置坐标轴的渲染区域
   this.renderer.setViewport(0, 0, width / 4, height / 4);
   this.renderer.render(this.Helper.axesScene, this.Helper.axesCamera);
   // 复原视口
   this.renderer.setViewport(0, 0, width, height);
   this.renderer.autoClear = true; // 恢复 autoClear
 }
 animate()

2、数据结构解析

points- 点的x、y、z轴坐标
properties- 点的热力值

{
	"points": [
		[5.6,0,0],
		[0,5.6,0],
		[0,0,5.6],
		[0,0,0]
	]"properties": [
		"3.83E+07",
		"4.99E+07",
		"3.79E+07",
		"4.92E+07"
	]
}

3、代码部分

引入准备好的json文件

	import data from 'data.json'
核心部分

热力的核心部分是min_color和max_color需要定义两个颜色对应热力的最大值和最小值,然后根据每个点下标对应的properties对应的数字进行计算得出。
rgb_convert 用于提取数字
rgb_diff 计算两个RGB颜色之间的差异
点图需要很大的数据支撑。我最上面方的图点的数量大概是8w多个

drawScatter(data){
    let geometry = new THREE.BufferGeometry();
    let vertices = [];
    let colors = [];
    let aps = data.properties.map(at => parseFloat(at))
    let min_color = this.rgb_convert('rgb(0,0,0)')
    let max_color = this.rgb_convert('rgb(255,255,255)')
    let seg_colors = []
    let diff = this.rgb_diff(min_color, max_color)
    let aps_max = aps[0]
    let aps_min = aps[0]
    for (let i = 0; i < aps.length; i++) {
      if (aps[i] < aps_min) {
        aps_min = aps[i]
      }
      if (aps[i] > aps_max) {
        aps_max = aps[i]
      }
    }
    let aps_diff = aps_max - aps_min
    for (let i = 0; i < aps.length; i++) {
      if (i === 1) {
        console.log('aps[i]:' + aps[i])
        console.log('(aps[i] - aps_min) / aps_diff * diff[0] + min_color[0]:' + ((aps[i] - aps_min) / aps_diff * diff[0] + min_color[0]))
      }
      seg_colors.push([
        parseInt((aps[i] - aps_min) / aps_diff *  diff[0] + min_color[0]),
        parseInt((aps[i] - aps_min) / aps_diff *  diff[1] + min_color[1]),
        parseInt((aps[i] - aps_min) / aps_diff * diff[2] + min_color[2]),
      ])
    }
    data.points.forEach((in_it, in_index) => {
      let x = in_it[0];
      let y = in_it[1] * 5;
      let z = in_it[2];
      vertices.push(x, y, z);
      // 随机颜色
      let color = new THREE.Color("rgb("+seg_colors[in_index][0]+","+
        seg_colors[in_index][1]+","+ seg_colors[in_index][2]+")");
      colors.push(color.r, color.g, color.b);
    })
    geometry.setAttribute('position', new THREE.Float32BufferAttribute(vertices, 3));
    geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3)); // 设置颜色属性
    // 定义点的材质
    let material = new THREE.PointsMaterial({vertexColors: true, size: 10});
    // 创建粒子系统对象
    let particleSystem = new THREE.Points(geometry, material);
    return particleSystem
  }

  rgb_convert(rgb_str) {
    let rgb = rgb_str.substring(5, rgb_str.length - 1).replace(/ /g, '').split(',').map(Number);
    return rgb
  }

  rgb_diff(min, max) {
    return [max[0] - min[0], max[1] - min[1], max[2] - min[2]]
  }
绘制部分

调用上述代码,将所有的内容放到atomGroup 中,将atomGroup 添加到场景即可实现完整逻辑

	const particleSystem = this.drawScatter(data)
    // 将粒子系统对象添加到场景中
    this.scatterGroup.add(particleSystem);
    // 放入场景
    scene.add(this.scatterGroup)
  • 7
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值