图形可视化与Web图像技术介绍

一、SVG:可伸缩的矢量图形(声明式方法:保留模式图形绘制)

SVG 本身是基于 XML 的一种独立的数据格式,用于声明式的 2D 矢量图形。但是,它也可以嵌入到 HTML 文档中,这是所有主流浏览器都支持的。

使用 SVG 绘制一个可调整大小的圆:
<html style="height: 100%; width: 100%">
  <body style="height: 100%; width: 100%; margin: 0px">
    <svg style="height: 100%; width: 100%; display: block" viewBox="0 0 100 100">
      <circle cx="50" cy="50" r="25" fill="red" stroke="black"
              vector-effect="non-scaling-stroke" />
    </svg>
  </body>
</html>

当浏览器窗口调整大小或缩放时,它将重新缩放图像,而不会丢失图像的任何质量(因为图像是根据形状定义的,而不是根据像素定义的)。当 SVG 元素被 JavaScript 代码修改时,它还会自动重新绘制图像,这使得 SVG 特别适合与 **JavaScript 库(如 D3)**一起使用,D3 将数据绑定到 DOM 中的元素,从而能够创建从简单图表到更奇特的交互式数据可视化的任何内容。

二、画布canvas(函数式方法:即时模式图形绘制)

canvas 元素只是在网页上提供了一个可以绘图的区域。使用 JavaScript 代码,首先从画布获取上下文,然后使用提供的 API,定义绘制图像的函数。

const canvas = document.getElementById(id);
const context = canvas.getContext(contextType);

// call some methods on context to draw onto the canvas

当脚本执行时,图像立即绘制成了底层位图的像素,浏览器不保留绘制方式的任何信息。为了更新绘图,需要再次执行脚本。重新缩放图像时,也会触发更新绘图,否则,浏览器只会拉伸原始位图,导致图像明显模糊或像素化。

1.上下文:2D

提供了一个用于在画布上绘制 2D 图形的高级 API。

绘制可调整大小的圆:
<html style="height: 100%; width: 100%">
  <body style="height: 100%; width: 100%; margin: 0px">
    <canvas id="my-canvas" style="height: 100%; width: 100%; display: block"></canvas>
    <script>
      const canvas = document.getElementById("my-canvas");
      const context = canvas.getContext("2d");

      function render() {
        // Size the drawing surface to match the actual element (no stretch).
        canvas.height = canvas.clientHeight;
        canvas.width = canvas.clientWidth;

        context.beginPath();

        // Calculate relative size and position of circle in pixels.
        const x = 0.5 * canvas.width;
        const y = 0.5 * canvas.height;
        const radius = 0.25 * Math.min(canvas.height, canvas.width);

        context.arc(x, y, radius, 0, 2 * Math.PI);

        context.fillStyle = "red";
        context.fill();

        context.strokeStyle = "black";
        context.stroke();
      }

      render();
      addEventListener("resize", render);
    </script>
  </body>
</html>

根据画布的当前大小,以像素为单位计算圆的半径和中心位置。这也意味着必须监听缩放的事件并相应地重新绘制适用于绘制更多对象的、更复杂的动态可视化,比更新 DOM 中的大量元素,并让浏览器来决定何时呈现和呈现什么,带来更好的性能

2.上下文:WebGL

大多数现代浏览器也支持 webgl 上下文。提供了使用 WebGL 标准绘制硬件加速图形的底层 API,尽管这需要 GPU 支持。它可以用来渲染 2D,更重要的是,也可以用来渲染本篇博客所说的 3D 图形。

//渲染圆圈
<html style="height: 100%; width: 100%">
  <body style="height: 100%; width: 100%; margin: 0px">
    <canvas id="my-canvas" style="height: 100%; width: 100%; display: block"></canvas>
    <script>
      const canvas = document.getElementById("my-canvas");
      const context = canvas.getContext("webgl");

      const redColor = new Float32Array([1.0, 0.0, 0.0, 1.0]);
      const blackColor = new Float32Array([0.0, 0.0, 0.0, 1.0]);

      // Use an orthogonal projection matrix as we're rendering in 2D.
      const projectionMatrix = new Float32Array([
        1.0, 0.0, 0.0, 0.0,
        0.0, 1.0, 0.0, 0.0,
        0.0, 0.0, 0.0, 0.0,
        0.0, 0.0, 0.0, 1.0,
      ]);

      // Define positions of the vertices of the circle (in clip space).
      const radius = 0.5;
      const segmentCount = 360;
      const positions = [0.0, 0.0];
      for (let i = 0; i < segmentCount + 1; i++) {
          positions.push(radius * Math.sin(2 * Math.PI * i / segmentCount));
        positions.push(radius * Math.cos(2 * Math.PI * i / segmentCount));
      }

      const positionBuffer = context.createBuffer();
      context.bindBuffer(context.ARRAY_BUFFER, positionBuffer);
      context.bufferData(context.ARRAY_BUFFER, new Float32Array(positions), context.STATIC_DRAW);

      // Create shaders and program.
      const vertexShader = context.createShader(context.VERTEX_SHADER);
      context.shaderSource(vertexShader, `
        attribute vec4 position;
        uniform mat4 projection;

        void main() {
          gl_Position = projection * position;
        }
      `);
      context.compileShader(vertexShader);

      const fragmentShader = context.createShader(context.FRAGMENT_SHADER);
      context.shaderSource(fragmentShader, `
        uniform lowp vec4 color;

        void main() {
          gl_FragColor = color;
        }
      `);
      context.compileShader(fragmentShader);

      const program = context.createProgram();
      context.attachShader(program, vertexShader);
      context.attachShader(program, fragmentShader);
      context.linkProgram(program);

      const positionAttribute = context.getAttribLocation(program, 'position');

      const colorUniform = context.getUniformLocation(program, 'color');
      const projectionUniform = context.getUniformLocation(program, 'projection');

      function render() {
        // Size the drawing surface to match the actual element (no stretch).
        canvas.height = canvas.clientHeight;
        canvas.width = canvas.clientWidth;

        context.viewport(0, 0, canvas.width, canvas.height);

        context.useProgram(program);

        // Scale projection to maintain 1:1 ratio between height and width on canvas.
        projectionMatrix[0] = canvas.width > canvas.height ? canvas.height / canvas.width : 1.0;
        projectionMatrix[5] = canvas.height > canvas.width ? canvas.width / canvas.height : 1.0;
        context.uniformMatrix4fv(projectionUniform, false, projectionMatrix);

        const vertexSize = 2;
        const vertexCount = positions.length / vertexSize;

        context.bindBuffer(context.ARRAY_BUFFER, positionBuffer);
        context.vertexAttribPointer(positionAttribute, vertexSize, context.FLOAT, false, 0, 0);
        context.enableVertexAttribArray(positionAttribute);

        context.uniform4fv(colorUniform, redColor);
        context.drawArrays(context.TRIANGLE_FAN, 0, vertexCount);

        context.uniform4fv(colorUniform, blackColor);
        context.drawArrays(context.LINE_STRIP, 1, vertexCount - 1);
      }

      render();
      addEventListener("resize", render);
    </script>
  </body>
</html>

在渲染任何东西之前,要做很多设置。必须使用顶点列表,将圆定义为由小三角形组成的一个序列。还必须定义一个投影矩阵,将3D 模型(一个平面圆)投影到 2D 画布上。然后,必须编写“着色器”(用一种称为 GLSL 的语言),在 GPU 上编译并运行,以确定顶点的位置和颜色。
但是,额外的复杂性和较底层的 API,确实能够更好地控制 2D 图形绘制的性能。还提供了渲染 3D 可视化的能力

三、X3D:面向声明式的3D图形

参考:X3D:现代Web的声明式3D技术

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章