圖形可視化與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技術

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