1.热力图

开始的时候,是用一个网上找的canvas画渐变热点的demo,原理就是给定顶点坐标,然后画圆,颜色使用渐变色,根据权重决定渐变的层数(红色->橙色->绿色) 。

但是终究觉得这种方法不仅繁琐,而且画出来的效果不够自然。

后来发现有一个开源库heatmap效果很好,它是这样用的(官方demo地址链接):

var heatmapInstance = h337.create({
container: document.querySelector('.heatmap')
});
var data = {
max: max,
data: points
};
heatmapInstance.setData(data);

max值为所有points中权重属性的最大值。

看到这里,那我们要怎么在three.js中去使用heatmap呢,他是用dom去实例化heatmap对象的啊。

不用担心,我们可以creatElement('div'),然后在这个dom对象上实例化heatmap对象,并且

      var canvas = heatmapdiv.getElementsByTagName('canvas')[];

获取绘制后的canvas对象。

        let heatMapGeo = new THREE.PlaneGeometry(,);
let heatMapTexture = new THREE.Texture(canvas);
let heatMapMaterial = new THREE.MeshBasicMaterial({
map: heatMapTexture,
transparent:true
});
heatMapMaterial.map.needsUpdate = true;
var heatMapPlane = new THREE.Mesh(heatMapGeo,heatMapMaterial);
heatMapPlane.position.set(,0.1,);
heatMapPlane.rotation.x = -Math.PI/;
this.scene.add(heatMapPlane);

这样,用heatmap绘制的热力图就添加到了three.js创建的场景中去了。

2.轨迹线

轨迹线不难想,利用three.js提供的曲线来绘制,但是会存在如下两个问题:

q1.three.js的曲线貌似只能一次性整条绘制出来,没有api显示可以按百分比绘制曲线,所以只好自己写shader实现

q2.webgl渲染器不支持线宽属性(three.MeshLine支持线宽,不过没有研究是否支持按百分比绘制);

q3.着色器里面可以针对点设置pointsize来实现点的大小(间接实现曲线的宽度控制),但是点是二维的,默认存在于x-y平面,所以在x-z平面看的时候,如果点的数量不够多那么就会出现断断续续的效果,但是采样的点数量足够多又会影响性能。

上述的问题不能解决的话,后续的曲线样式优化(渐变)就无从谈起。

期间我想过,既然点存在于x-y平面,那么我们就将x-z平面的轨迹放到x-y平面来绘制,最后将这条线绕x轴旋转90度,但是因为对点进行处理的时候,首先正方形的点->圆点->渐变(抗锯齿),最后,结果如下:

看着好像成功了,但是由于深度检测机制(现在想来,是不是可以设置取消这条线的深度检测机制)的存在,某些角度下,这条线的本质(n个大号的点拼接)就变得很明显了,你会明显地看到这条线是由进行抗锯齿处理后的无数个点组成。

哎,好像又遇到困难了啊。

后来一想,既然three.js中一条线很细,那么10条线,100条线在一起呢?只要间距足够小,它们看上去就是一根线,一根麻绳!!!

PS:

回过头来看我当时的这个处理思路,其实在性能上还是有很大的提升空间的,至少增加了内存消耗;

当然后续查看meshline源码,你会发现他是将顶点作偏移绘制三角面来实现有宽度的“线”,并且每个顶点还传入了顶点的索引值属性,可用于进度的控制;

照着这个思路, 写了一个FatLine类:

import * as THREE from 'three'
/**
* Author:桔子桑
* Time:2019.10.12
*/ const vs =`
varying vec3 iPosition; void main(){
iPosition = vec3(position);
gl_Position = projectionMatrix * modelViewMatrix * vec4(position.x,0.2,position.z,1.0);
}
`;
const fs = `
uniform float time;
varying vec3 iPosition;
uniform float alpha; void main( void ) {
if(iPosition.y > time){
discard;
}else{
gl_FragColor = vec4(0.813,0.124,0.334,alpha);
} }
`; function FatLine(vertices,width,scene){
this.width = width;
this.vertices = vertices;
this.start = ;
this.scene = scene;
this.linearr = [];
this.lines = [];
}
function createMaterial(vs, fs, start) {
var attributes = {};
var uniforms = {
time: {type: 'f', value: start},
size:{type:'f',value:25.0},
};
var meshMaterial = new THREE.ShaderMaterial({
uniforms: uniforms,
defaultAttributeValues : attributes,
vertexShader: vs,
fragmentShader: fs,
transparent: true
});
return meshMaterial;
} FatLine.prototype.draw = function() {
var size = this.vertices.length;
var length = Math.floor(this.width/);
var vm = this;
for(var j =;j<length;j++){
var lineadd = [];
var linereduce = [];
for ( var i = ; i <size; i ++ ) {
var Vector3 = this.vertices[i],
x = Vector3.x,
y = Vector3.y,
z = Vector3.z;
var zadd = z+j*0.001;
var zreduce = z-j*0.001;
lineadd.push( new THREE.Vector3(x,y,zadd ));
linereduce.push( new THREE.Vector3(x,y,zreduce ));
}
this.linearr.push(lineadd);
this.linearr.push(linereduce);
};
this.linearr.push(vm.vertices);
var pointsize = this.vertices.length * ;
for(var k = ,size=this.linearr.length;k<size;k++){
var vertices = this.linearr[k];
var alpha = (Math.floor(size/) - Math.floor(k/))/Math.floor(size/);
var curve = new THREE.CatmullRomCurve3(vertices);
var geometry = new THREE.Geometry();
geometry.vertices = curve.getPoints(pointsize);
var material = createMaterial(vs,fs,vm.start);
material.uniforms.alpha = {type:'f',value:alpha};
var line = new THREE.Line(geometry, material);
this.lines.push(line);
this.scene.add( line );
}
} FatLine.prototype.animate = function(speed,callback){
var time = this.lines[].material.uniforms.time.value;
for(var i = ,length=this.lines.length;i<length;i++){
var line = this.lines[i];
line.material.uniforms.time.value +=speed||0.3;
};
if(callback){
callback(time);
}
} export default FatLine;

你可以看到,着色器中还又一个uniform变量time,这个是用来在FatLine开启动画的时候,随着时间的进展来逐步绘制的。

ok,看到这你以为就完了?no!!!

刚开始的时候,按照常规当time++的时候,在x-z平面上轨迹点,我们判断x<time是否来控制曲线的绘制进度,但是一个问题出现了,人员轨迹点可能出现在一个房间兜圈子的情况(实际也是如此),这样就会存在第2个点和第200个点都满足x<2.0,那么总不能根据时间,第2秒的时候,直接把200秒时候的点也绘制出来了吧,这是不符合常理的。

在下班回家的路上,我想到了一个问题,在三维空间,一个点有(x,y,z)三个维度的坐标信息数据传进了着色器里面,但是我们的人员轨迹只会存在于场景的x-z平面,所以这个y坐标值在着色器里面是没有用到的,哈哈,那么这个y值可以充当时间维度值,第一个点y=1,第二个点y=2,第三个点y=3...,如此一来,当time++的时候,我们只要判断y<time就可以实现在时间维度上的控制了。

并且FatLine的animate函数还提供了一个回调函数,参数值是当前的time值,所以你可以用这个time值来绘制具体的点:

     if(this.FatLine){
function addpoint(time){
for(var i = ,length=vm.vertices.length;i<length;i++){
var point = vm.vertices[i];
if(Math.abs(point.y-time)< 0.1){
vm.addpoint(point.x,point.z);
}
}
}
this.FatLine.animate(0.2,addpoint);
}

每一帧都会animate一下,也就是time++,并且判断进度是不是到了指定的某个点上,如果到了,那么就顺便把这个点也画出来,就像上述的动图一样。

最终可控制粗细和运动速度的曲线就完成了。

three.js效果之热力图和轨迹线的更多相关文章

  1. 类js效果

    类似js效果,点击看看  代码 onclick="return confirm('您确定要看看吗?')" 放入a标签里面

  2. m.jd.com首页中的js效果

    m.jd.com中的部分js效果 昨天把m.jd.com的首页布局写好了,今天写一下首页中部分js效果.头部背景色透明度的改变,焦点图轮播,京东快报的小轮播,以及秒杀倒计时.这里html,css样式就 ...

  3. Tab选项卡切换卡JS效果

    <script type="text/javascript"> /* tab切换选项卡js效果 writed by *** 2010.08.13 1.currentid ...

  4. JS效果的步骤

    一.写JS效果的步骤 1.先实现布局 (XHTML+CSS2) 2.实现原理 (1)希望把某个元素移除你的视线: a.  display:none;         显示为无,不占据空间 b.  vi ...

  5. Github上html页面(包括CSS样式和JS效果)如何显示出来

    在看Github上项目时,发现有的html页面效果能很好的展现出来,而有的则不能.对这个问题很好奇,因此研究了一下,最终做到了将页面展示出来的目的.下面以我的Github的开源项目bootstrap- ...

  6. WebView 实现JS效果和a标签的点击事件

    目前很多android app都可以显示web页面的界面,嵌入式开发,这个界面一般都是WebView这个控件加载出来的,学习该控件可以为你的app开发提升扩展性. 先说下WebView的一些优点: 可 ...

  7. 常用JS效果 需要时更新。。。

    1.手风琴效果 JS: $(function() {     var aMenuOneLi = $(".menu-one > li");     var aMenuTwo = ...

  8. js效果-多选只能选两项,如果超出自动取消第一次选的

    这个效果很有意思,个人觉得难点在于点击选中状态的多选的数组操作,以下是代码,感谢落梨 <!DOCTYPE> <html> <head> <title> ...

  9. 用js效果做的简单焦点图

    /*js代码*/ <script src="js/js/myfocus-2.0.1.min.js" type="text/javascript">& ...

随机推荐

  1. Spring入门篇——第3章 Spring Bean装配(上)

    第3章 Spring Bean装配(上) 介绍Bean的作用域.生命周期.Aware接口.自动装配和Resource等内容. 3-1 Spring Bean装配之Bean的配置项及作用域 从上至下依次 ...

  2. linux基础_使用指令

    1.指令运行级别 (0)关机 (1)单用户(找回丢失密码) (2)多用户无网络服务 (3)多用户有网络服务 (4)保留 (5)图形界面 (6)重启 /etc/inittab:系统的运行级别配置之文件 ...

  3. C# 数组(5) 持续更新

    同一类型和不同类型的多个对象 使用同一类型的多个对象,使用集合和数组. 使用不同类型的多个对象,使用Tuple(元组). 初始化数组 ]; myArray 存放在栈中,而 myArray 的内容 放在 ...

  4. django session 加密cookie型

    a. 配置 settings.py           SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'   # 引 ...

  5. mysql查询疯狂41例

    援引自 http://www.cnblogs.com/wupeiqi/articles/5748496.html 一.表关系请创建如下表,并创建相关约束 二.操作表 1.自行创建测试数据 2.查询“生 ...

  6. oracle数据库体系结构

    一.oracle数据库体系结构 基本组成: Oracle server:一般情况下是一个instance和一个database组成 一般:1个instance只能对应一个数据库. 特殊:1个数据库可以 ...

  7. codeforces#1196F. K-th Path(最短路,思维题)

    题目链接: https://codeforces.com/contest/1196/problem/F 题意: 在无向图的所有最短路点对中,求出第$k$大 数据范围: $ 1 \leq k \leq ...

  8. Hdu2037

    Hdu2037 - 今年暑假不AC 题意: 在一个数轴上有n条线段,现要选取其中k条线段使得这k条线段两两没有重合部分,问最大的k为多少. 解法: 这其实就是一个大水题,一个非常简单明了的区间覆盖问题 ...

  9. Linux设备驱动程序 之 主次设备号

    主设备号和次设备号 对字符设备的访问是通过文件系统内的设备名称进行的,这些名称被称为特殊文件.设备文件.或者简单称之为文件系统树的节点,它们通常位于/dev目录.字符设备驱动程序的设备文件可以通过ls ...

  10. SpringMVC支持跨域请求

    一.如果项目中使用的SpringMVC4.3.9以下,就需要对该请求配置Filter,设置请求头可支持跨域.使用方法: --spring cloud zuul支持跨域---:https://blog. ...