javascript
JavaScript 3D图表
在說3D圖表以前,首先要明確兩個概念,一個是數據的維度,一個是呈現數據載體的維度。對于數據的維度,一維的數據呈現,但是呈現的載體是二維的平面圖,比如餅圖:
已經能夠很清晰地觀察到數據的分布情況。數據如果增加一個維度,變成二維,呈現載體依然是二維的平面圖:
數據表達依然是清晰的。但是,倘若再增加一維,這個時候就面臨了兩個問題:
這兩個問題中,第一個問題從本質上說,無法解決。數據的維度越大,理解起來理所當然地,也越來越困難。
但是第二個問題,我們至少有兩種解決辦法。一種,在當前二維圖表的基礎上,通過顏色、圖形、數值的不同等等,來表示第三個維度的數據。例如,利用顏色不同來表示第三個維度的熱圖:
在兩個維度經度和維度的情況下,第三個維度溫度通過顏色的不同來展示了。
另一種,就是繪制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下得到一樣的效果。
對于這個例子,簡單過一下重點代碼,首先這部分是著色器的代碼(片段著色器和頂點著色器),包括坐標軸和紋理:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | <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> |
這個方法用于保持兩圖步調一致:
| 1 2 3 4 5 6 7 8 9 10 11 12 | function coordinateCharts(){ ????// Link the two charts for rotation. ????? ????plot1 = surfacePlot.getChart(); ????plot2 = surfacePlot2.getChart(); ????? ????if (!plot1 || !plot2) ????????return; ????? ????plot1.otherPlots = [plot2]; ????plot2.otherPlots = [plot1]; } |
每發生變化需要重繪的時候,調用:
| 1 2 | surfacePlot.draw(data, options, basicPlotOptions, glOptions); surfacePlot2.draw(data2, options, basicPlotOptions2, glOptions2); |
Demoparse主要用來根據用戶輸入的公式f(x,y)計算z的值:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | 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的代碼非常簡單:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | //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即可。
轉載于:https://www.cnblogs.com/Blog-Yang/p/3282843.html
總結
以上是生活随笔為你收集整理的JavaScript 3D图表的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Golang学习 - bufio 包
- 下一篇: win7 telnet命令无法使用