文章系本人原创,转载请保持完整性并注明出自《四火的唠叨》html
在说3D图表之前,首先要明确两个概念,一个是数据的维度,一个是呈现数据载体的维度。对于数据的维度,一维的数据呈现,可是呈现的载体是二维的平面图,好比饼图:web
已经可以很清晰地观察到数据的分布状况。数据若是增长一个维度,变成二维,呈现载体依然是二维的平面图:canvas
数据表达依然是清晰的。可是,假若再增长一维,这个时候就面临了两个问题:浏览器
这两个问题中,第一个问题从本质上说,没法解决。数据的维度越大,理解起来理所固然地,也愈来愈困难。svn
可是第二个问题,咱们至少有两种解决办法。一种,在当前二维图表的基础上,经过颜色、图形、数值的不一样等等,来表示第三个维度的数据。例如,利用颜色不一样来表示第三个维度的热图:webgl
在两个维度经度和维度的状况下,第三个维度温度经过颜色的不一样来展现了。google
另外一种,就是绘制3D的图形,把第三个维度展现出来。须要注意的是,绘制3D的图形仅仅是技术上的一种呈现形式,并不意味着它的易懂性要好于上面一种方式。实际上,咱们仍是须要看看具体的问题是什么。lua
明确了这些概念之后,我再来介绍两则JavaScript的3D图表,它们都是为了呈现三维的数据,而不单单是看起来3D而已,大部分JavaScript的3D图表库都是基于Canvas的,若是你对Canvas不了解请移步参阅这篇文章;其中一些则是支持WebGL的。WebGL是一种3D的绘图标准,有了它,JavaScript就能够实现OpenGL标准能作的事情了,在HTML5 Canvas基础上,WebGL容许硬件3D加速。spa
webgl-surface-plot.net
主页点此。特性列表:
在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便可。
文章系本人原创,转载请保持完整性并注明出自《四火的唠叨》