• JavaScript 3D图表


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

    JavaScript 3D图表

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

    JavaScript 3D图表

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

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

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

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

    JavaScript 3D图表

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

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

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

      webgl-surface-plot

    JavaScript 3D图表

      主页点此。特性列表:

    • 纯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真是太简单了,如果你需要这种风格的柱状图:

    JavaScript 3D图表

      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即可。

  • 相关阅读:
    【EOSS】Windows 环境编译 Apollo 代码
    【配置与安装】CentOS7 升级gcc版本
    【Linux系统】Linux 环境变量 PATH 的增添和删除
    【C++百科】std(标准库)与 stl(标准模板库)的关系
    【C++语法】C ++ 函数后面加 throw() 的作用
    【gtest/gmock】gtest:Google C++ Testing Framework
    【Linux文件系统】inode(索引节点)和 block(块)
    【Linux命令】ls -l显示的内容中total到底是什么?
    【vi】Linux vi/vim 简介
    【DOS命令】color
  • 原文地址:https://www.cnblogs.com/Blog-Yang/p/3282843.html
Copyright © 2020-2023  润新知