文章系本人原创,转载请保持完整性并注明出自《四火的唠叨》

在说3D图表以前,首先要明确两个概念,一个是数据的维度,一个是呈现数据载体的维度。对于数据的维度,一维的数据呈现,但是呈现的载体是二维的平面图,比如饼图:

已经能够很清晰地观察到数据的分布情况。数据如果增加一个维度,变成二维,呈现载体依然是二维的平面图:

数据表达依然是清晰的。但是,倘若再增加一维,这个时候就面临了两个问题:

  1. 数据的维度增加,复杂性也增大了;
  2. 计算机发展到现在,绝大多数情况下数据载体依然是二维的平面图,如何展示三维的数据呢?

这两个问题中,第一个问题从本质上说,无法解决。数据的维度越大,理解起来理所当然地,也越来越困难。

但是第二个问题,我们至少有两种解决办法。一种,在当前二维图表的基础上,通过颜色、图形、数值的不同等等,来表示第三个维度的数据。例如,利用颜色不同来表示第三个维度的热图:

在两个维度经度和维度的情况下,第三个维度温度通过颜色的不同来展示了。

另一种,就是绘制3D的图形,把第三个维度展示出来。需要注意的是,绘制3D的图形仅仅是技术上的一种呈现形式,并不意味着它的易懂性要好于上面一种方式。实际上,我们还是需要看看具体的问题是什么。

明确了这些概念以后,我再来介绍两则JavaScript的3D图表,它们都是为了呈现三维的数据,而不仅仅是看起来3D而已,大部分JavaScript的3D图表库都是基于Canvas的,如果你对Canvas不了解请移步参阅这篇文章;其中一些则是支持WebGL的。WebGL是一种3D的绘图标准,有了它,JavaScript就可以实现OpenGL标准能做的事情了,在HTML5 Canvas基础上,WebGL允许硬件3D加速。

webgl-surface-plot

主页点此。特性列表:

  • 纯JavaScript实现,不需要Flash;
  • 鼠标左键拖拽可以翻转图像;
  • 按住Shift键可以缩放;
  • Web GL不可用的时候,可以直接使用Canvas绘制;
  • 自定义坐标轴名称;
  • 自定义颜色梯度和渐变;
  • 包装为Google Visualization API的一部分。

在IE下,借助excanvas可以在VML下得到一样的效果。

对于这个例子,简单过一下重点代码,首先这部分是着色器的代码(片段着色器和顶点着色器),包括坐标轴和纹理:

<script id="shader-fs" type="x-shader/x-fragment">
#ifdef GL_ES precision highp float;
#endif varying vec4 vColor;
varying vec3 vLightWeighting;
void main(void) {
gl_FragColor = vec4(vColor.rgb * vLightWeighting, vColor.a);
}
</script> <script id="shader-vs" type="x-shader/x-vertex">
attribute vec3 aVertexPosition;
attribute vec3 aVertexNormal;
attribute vec4 aVertexColor;
uniform mat4 uMVMatrix;
uniform mat4 uPMatrix;
uniform mat3 uNMatrix;
varying vec4 vColor;
uniform vec3 uAmbientColor;
uniform vec3 uLightingDirection;
uniform vec3 uDirectionalColor;
varying vec3 vLightWeighting;
void main(void) {
gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
vec3 transformedNormal = uNMatrix * aVertexNormal;
float directionalLightWeighting = max(dot(transformedNormal, uLightingDirection), 0.0);
vLightWeighting = uAmbientColor + uDirectionalColor * directionalLightWeighting;
vColor = aVertexColor;
}
</script> <script id="axes-shader-fs" type="x-shader/x-fragment">
precision mediump float;
varying vec4 vColor; void main(void) {
gl_FragColor = vColor;
}
</script> <script id="axes-shader-vs" type="x-shader/x-vertex">
attribute vec3 aVertexPosition;
attribute vec4 aVertexColor;
uniform mat4 uMVMatrix;
uniform mat4 uPMatrix;
varying vec4 vColor;
uniform vec3 uAxesColour;
void main(void) {
gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
vColor = vec4(uAxesColour, 1.0);
}
</script> <script id="texture-shader-fs" type="x-shader/x-fragment">
#ifdef GL_ES
precision highp float;
#endif
varying vec2 vTextureCoord;
uniform sampler2D uSampler;
void main(void) {
gl_FragColor = texture2D(uSampler, vTextureCoord);
}
</script> <script id="texture-shader-vs" type="x-shader/x-vertex">
attribute vec3 aVertexPosition;
attribute vec2 aTextureCoord;
varying vec2 vTextureCoord;
uniform mat4 uMVMatrix;
uniform mat4 uPMatrix;
void main(void) {
gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
vTextureCoord = aTextureCoord;
}
</script>

这个方法用于保持两图步调一致:

function coordinateCharts(){
// Link the two charts for rotation.
plot1 = surfacePlot.getChart();
plot2 = surfacePlot2.getChart();
if (!plot1 || !plot2)
return;
plot1.otherPlots = [plot2];
plot2.otherPlots = [plot1];
}

每发生变化需要重绘的时候,调用:

surfacePlot.draw(data, options, basicPlotOptions, glOptions);
surfacePlot2.draw(data2, options, basicPlotOptions2, glOptions2);

Demoparse主要用来根据用户输入的公式f(x,y)计算z的值:

function Demoparse(ID_result, ID_code, valueArray, toolTips){
var el, expr;
el = document.getElementById(ID_result);
expr = document.getElementById(ID_code).value;
expr = Parser.parse(expr);
var result;
var idx = 0;
var d = 360 / numRows;
for (var x = 0; x < numRows; x++) {
valueArray[x] = new Array();
for (var y = 0; y < numCols; y++) {
result = expr.simplify({
x: x * d,
y: y * d
});
result = result.evaluate();
valueArray[x][y] = result / 4.0 + 0.25;
toolTips[idx] = "x:" + x + ", y:" + y + " = " + result;
idx++;
}
}
}

Canvas 3D Graph

相比前者,Canvas 3D Graph真是太简单了,如果你需要这种风格的柱状图:

demo的代码非常简单:

//Initialise Graph
var g = new canvasGraph('graph'); //define some data gData=new Array();
gData[0]={x:500,y:500,z:500};
gData[1]={x:500,y:400,z:600};
gData[2]={x:500,y:300,z:700};
gData[3]={x:500,y:200,z:800};
gData[4]={x:500,y:100,z:900}; // sort data - draw farest elements first
gData.sort(sortNumByZ); //draw graph
g.drawGraph(gData);

PS:如果你遇到无法显示WebGL图形的问题——它不仅对浏览器,还对硬件有要求。如果你使用Opera浏览器,在地址栏输入about:gpu,以查看你的显卡是否被支持。如果是FireFox,地址栏输入about:config,寻找webgl.force-enabled,双击,将该值改为true即可。

文章系本人原创,转载请保持完整性并注明出自《四火的唠叨》

【转】JavaScript 3D图表的更多相关文章

  1. JavaScript 3D图表

    在说3D图表以前,首先要明确两个概念,一个是数据的维度,一个是呈现数据载体的维度.对于数据的维度,一维的数据呈现,但是呈现的载体是二维的平面图,比如饼图: 已经能够很清晰地观察到数据的分布情况.数据如 ...

  2. 如何在ASP.Net创建各种3D图表

    我们都知道,图表在ASP.NET技术中是一种特别受欢迎而又很重要的工具.图表是表示数据的图形,一般含有X和Y两个坐标轴.我们可以用折线,柱状,块状来表示数据.通过图表控件,我们即能表示数据又能比较各种 ...

  3. 【前端酷站】分享一个纯 Javascript 的图表库与立体像素风制作~

    今天小编为大家推荐一个神奇的酷站.ECharts,一个纯 Javascript 的图表库. 以下是各个几个不错的界面的介绍: 首页:http://echarts.baidu.com/ 在首页有完整的说 ...

  4. Python的可视化包 – Matplotlib 2D图表(点图和线图,.柱状或饼状类型的图),3D图表(曲面图,散点图和柱状图)

    Python的可视化包 – Matplotlib Matplotlib是Python中最常用的可视化工具之一,可以非常方便地创建海量类型地2D图表和一些基本的3D图表.Matplotlib最早是为了可 ...

  5. vis用于做3D图表的js插件

    vis.js用于做3D图表:(浏览网站需要FQ)实例:http://visjs.org/graph3d_examples.html代码下载:https://github.com/almende/vis

  6. FusionCharts使用JavaScript渲染图表(不用Flash)

    FusionCharts可以让用户只使用JavaScript建立图表(而不是使用Flash),只需要添加另一行代码,如下所示: FusionCharts.setCurrentRenderer('jav ...

  7. Mathcad 是一种工程计算软件,主要运算功能:代数运算、线性代数、微积分、符号计算、2D和3D图表、动画、函数、程序编写、逻辑运算、变量与单位的定义和计算等。

    Mathcad软件包Mathcad是由MathSoft公司(2006 年4 月被美国PTC收购)推出的一种交互式数值计算系统. Mathcad 是一种工程计算软件,作为工程计算的全球标准,与专有的计算 ...

  8. LightningChart解决方案:XY和3D图表(Polymer Char GPC-IR&#174;-工程案例)

    LightningChart解决方案:XY和3D图表(Polymer Char GPC-IR-工程案例) 所在行业:石化公司成立时间:1992年LightningChart解决方案:XY和3D图表 P ...

  9. FushionCharts Free 的运用[2D/3D图表处理]

    由于先前在一些论坛中谈论到这个插件的运用,留了一些QQ联系方式,最近老是被一些程序员“骚扰”,说是请教一些关于FushionChart Free图表的处理技术,先前还是比较乐意接受的,但发现后来一些完 ...

随机推荐

  1. hdu 2986 Ballot evaluation (Simulation)

    Problem - 2986 之前在华工赛见过的一道简单的模拟,用map轻松干掉.为了精确,要全程用整型比较.轻松1y~ 代码如下: #include <cstdio> #include ...

  2. mybatis 嵌套查询与懒加载

    懒加载:对于页面有很多静态资源的情况下(比如网商购物页面),为了节省用户流量和提高页面性能,可以在用户浏览到当前资源的时候,再对资源进行请求和加载. fetchType="lazy" ...

  3. C# 传入 params object 长度

    刚刚 LiesAuer 大神问了一个问题,如果在 params object 传入 object 数组,那么拿到的值是的长度是多少 我做了测试在传入不同的值可能拿到不同的长度 先来说总结 传入一个数组 ...

  4. Vue 小实例 跑马灯效果

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  5. H3C 环路避免机制四:定义最大值

  6. UVa 1354 Mobile Computing[暴力枚举]

    **1354 Mobile Computing** There is a mysterious planet called Yaen, whose space is 2-dimensional. Th ...

  7. 超容易理解的call()、apply()、bind()的区别

    call().apply().bind()是用来改变this的指向的. 一 举个例子 一个叫喵喵的猫喜欢吃鱼,一个叫汪汪的小狗喜欢啃骨头,用代码实现如下: 有一天,小狗汪汪和喵喵共进午餐的时候,汪汪说 ...

  8. jQuery 工具类函数-字符串操作函数

    调用名为$.trim的工具函数,能删除字符串中左右两边的空格符,但该函数不能删除字符串中间的空格,调用格式为: $.trim (str); 参数str表示需要删除左右两边空格符的字符串. <bo ...

  9. Linux 内核class_simple 接口

    class_simple 接口意图是易于使用, 以至于没人会抱怨没有暴露至少一个包含设备的被 分配的号的属性. 使用这个接口只不过是一对函数调用, 没有通常的和 Linux 设备模型 关联的样板. 第 ...

  10. LightOJ - 1265 Island of Survival (概率dp)

    You are in a reality show, and the show is way too real that they threw into an island. Only two kin ...