文章系本人原創,轉載請保持完整性並註明出自《四火的嘮叨》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便可。
文章系本人原創,轉載請保持完整性並註明出自《四火的嘮叨》