JavaScript - 圖形



在 JavaScript 中,可以使用 Canvas API 建立圖形。但是,開發人員也可以使用其他一些庫,例如 p5.js、chart.js、pllotly.js、Google 圖表等,來繪製各種圖形和圖表。

在這裡,我們將探索其中一些庫,並藉助一些示例來了解它們。

WebGL

WebGL 允許開發人員使用程式碼從頭開始建立圖形,並將其整合到網頁中。它直接與 HTML <canvas> 元素一起操作,允許將物理和影像處理以及效果作為網頁畫布的一部分進行 GPU 加速使用。

WebGL 允許開發各種應用程式,從 2D 遊戲到複雜的 3D 視覺化應用程式。此外,它受大多數現代瀏覽器支援,這使其成為開發人員開發圖形的首選。

示例

在下面的程式碼中,我們使用了 <canvas> 元素來建立畫布,並使用 id 在 JavaScript 中訪問它。接下來,我們使用 getCContext() 方法獲取 WebGL 的上下文。如果瀏覽器不支援,getContext() 方法將返回未定義值。

在 initiateShader() 函式中,我們將著色器原始碼編譯成著色器,將這些著色器附加到程式,然後連結程式以便它可以在 WebGL 上下文中使用。loadShader() 函式載入並編譯著色器程式碼。

在 drawScene() 函式中,我們使用 useProgram() 方法,將圖形資訊作為引數傳遞以在畫布上繪製三角形。在輸出中,您可以看到黑色畫布上的紅色三角形。

<html>
<body>
   <h2> JavaScript - Graphics (WebGL) </h2>
   <canvas id="webgl-canvas" width="600" height="400"></canvas>
   <div id="error"> </div>
   <script>
      // Get the canvas element and its WebGL context
      var canvas = document.getElementById('webgl-canvas');
      let errorDiv = document.getElementById('error');
      // Get context of webgl
      var gl = canvas.getContext('webgl');

      if (!gl) {
         console.error('Your browser may not support WebGL.');
      }

      // Vertex shader program
      var vsSource = `
         attribute vec4 aVertexPosition;
         void main(void) {
            gl_Position = aVertexPosition;
         }
         `;

      // Fragment shader program
      var fsSource = `
      void main(void) {
         gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); // Red color
      }
      `;

      function initShaderProgram(gl, vsSource, fsSource) {
         const vertexShader = loadShader(gl, gl.VERTEX_SHADER, vsSource);
         const fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fsSource);

         // Create the shader program
         const shaderProgram = gl.createProgram();
         gl.attachShader(shaderProgram, vertexShader);
         gl.attachShader(shaderProgram, fragmentShader);
         gl.linkProgram(shaderProgram);

         // If creating the shader program failed, alert
         if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {

            alert('Unable to initialize the shader program: ' + gl.getProgramInfoLog(shaderProgram));
            return null;
         }

         return shaderProgram;
      }

      function loadShader(gl, type, source) {
         const shader = gl.createShader(type);

         // Send the source to the shader object
         gl.shaderSource(shader, source);

         // Compile the shader program
         gl.compileShader(shader);

         // See if it compiled successfully
         if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
            error.innerHTML = 'An error occurred compiling the shaders: ' + gl.getShaderInfoLog(shader);
            gl.deleteShader(shader);
            return null;
         }

         return shader;
      }

      // Initialize a shader program; this is where all the lighting
      // for the vertices and subsequently the creation of the
      // geometry and colors will be established.
      var shaderProgram = initShaderProgram(gl, vsSource, fsSource);

      // Collect all the info needed to use the shader program.
      // Look up which attribute our shader program is using
      // for aVertexPosition and look up uniform locations.
      var programInfo = {
         program: shaderProgram,
         attribLocations: {
            vertexPosition: gl.getAttribLocation(shaderProgram, 'aVertexPosition'),
         },
      };

      // Vertices of the triangle
      var positions = [
         0.0, 1.0,  // Vertex 1 (X, Y)
         -1.0, -1.0, // Vertex 2 (X, Y)
         1.0, -1.0,  // Vertex 3 (X, Y)
      ];
      var positionBuffer = gl.createBuffer();
      gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
      gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);

      // Draw the scene
      function drawScene(gl, programInfo, buffers) {
         gl.clearColor(0.0, 0.0, 0.0, 1.0);  // Clear to black, fully opaque
         gl.clear(gl.COLOR_BUFFER_BIT);
         gl.useProgram(programInfo.program);

         // Tell WebGL how to pull out the positions from the position
         // buffer into the vertexPosition attribute.
         {
            const numComponents = 2;  // pull out 2 values per iteration
            const type = gl.FLOAT;    // the data in the buffer is 32bit floats
            const normalize = false;  // don't normalize
            const stride = 0;         // how many bytes to get from one set to the next
            const offset = 0;         // how many bytes inside the buffer to start from
            gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
            gl.vertexAttribPointer(
               programInfo.attribLocations.vertexPosition,
               numComponents,
               type,
               normalize,
               stride,
               offset);
            gl.enableVertexAttribArray(
               programInfo.attribLocations.vertexPosition);
         }

         // Draw the triangle.
         gl.drawArrays(gl.TRIANGLES, 0, 3);
      }

      drawScene(gl, programInfo, positionBuffer);
   </script>
</body>
</html>

P5.js

P5.js 也是一個非常流行的圖形庫,用於透過編寫程式碼建立各種形狀。它還允許我們為形狀設定動畫,並使它們在視覺上更具吸引力。但是,它不僅限於形狀,還允許我們與音訊、影片等互動。

讓我們透過下面的示例瞭解 P5.js 的用法。

示例

在下面的程式碼中,程式以兩個主要函式開頭:setup() 和 draw()。setup() 函式在程式啟動時執行一次,用於初始設定任務。draw() 函式持續執行其塊中包含的程式碼行,直到程式停止或呼叫 noLoop(),這使其成為動畫的理想選擇。

在 setup() 函式中,我們建立了一個畫布並在其上繪製圓圈。在 draw() 函式中,我們透過重新繪製圓圈來不斷更改圓圈的位置。以下程式碼的輸出顯示了移動的圓圈。

<html>
<head>
   <title>p5.js Example</title>
   <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>
</head>
<body>
   <script>
      // Define variables for the circle's properties
      let x, y; // Position
      let dx = 2; // Speed and direction on x-axis
      let dy = -2; // Speed and direction on y-axis
      let radius = 50; // Circle's radius

      function setup() {
         // Create a canvas that fills the window
         createCanvas(windowWidth, windowHeight);
         // Initialize circle's position to center of the canvas
         x = width / 2;
         y = height / 2;
      }

      function draw() {
         background(220); // Fill the background with a light gray color
         // Draw a circle with a random fill color
         fill(random(255), random(255), random(255));
         ellipse(x, y, radius * 2); // Circle diameter is twice the radius
         // Update the position of the circle
         x += dx;
         y += dy;

         // Check for bouncing
         if (x + radius > width || x - radius < 0) {
            dx = -dx; // Reverse direction on the x-axis
         }
         if (y + radius > height || y - radius < 0) {
            dy = -dy; // Reverse direction on the y-axis
         }
      }

      // Resize the canvas when the window is resized
      function windowResized() {
         resizeCanvas(windowWidth, windowHeight);
      }
   </script>
</body>
</html>

Plotly.js

Plotly.js 是一個 JavaScript 庫,允許開發人員輕鬆建立各種型別的高質量圖形和視覺化效果。我們可以使用它來繪製統計圖表、3D 圖表等。Plotly.js 庫可以整合到各種程式語言和框架中。

示例

在下面的程式碼中,我們建立了 trace1 物件,其中包含 x、y 和 type 屬性。之後,我們使用 newPlot() 方法使用給定的資料點建立折線圖。

<html>
<body>
   <h2> JavaScript - Graphics </h2>
   <div id = "plotlyChart" style="width:600px;height:400px;"> </div>
   <script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
   <script>
      // Create a simple line chart
      var trace1 = {
         x: [1, 2, 3, 4],
         y: [10, 15, 13, 17],
         type: 'scatter'
      };

      var data = [trace1];
      Plotly.newPlot('plotlyChart', data);
   </script>
</body>
</html>

Chart.js

Chart.js 也是一個 JavaScript 庫,允許開發人員繪製各種型別的圖表。它支援六種圖表型別:折線圖、條形圖、雷達圖、環形圖、餅圖和極座標圖。

示例

在下面的程式碼中,我們使用了 chart.js 庫中的 Chart() 建構函式來建立一個新的條形圖。

<html>
<body>
   <h2> JavaScript - Graphics </h2>
   <canvas id="chartjsBarChart" width="600" height="400"></canvas>
   <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
   <script>
      // Get Canvas context
      var ctx = document.getElementById('chartjsBarChart').getContext('2d');
      // Create a chart
      var myChart = new Chart(ctx, {
         type: 'bar',
         data: {
            labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple'],
            datasets: [{
               label: '# of Votes',
               data: [1, 6, 3, 5, 2],
               backgroundColor: [
                  'rgba(255, 99, 132, 0.2)',
                  'rgba(54, 162, 235, 0.2)',
                  'rgba(255, 206, 86, 0.2)',
                  'rgba(75, 192, 192, 0.2)',
                  'rgba(153, 102, 255, 0.2)'
               ],
               borderColor: [
                  'rgba(255, 99, 132, 1)',
                  'rgba(54, 162, 235, 1)',
                  'rgba(255, 206, 86, 1)',
                  'rgba(75, 192, 192, 1)',
                  'rgba(153, 102, 255, 1)'
               ],
               borderWidth: 1
            }]
         },
         options: {
            scales: {
               y: {
                  beginAtZero: true
               }
            }
         }
      });
   </script>
</body>
</html>

Google 圖表

Google 圖表庫還提供各種型別的圖表,包括以下圖表。

  • 散點圖
  • 條形/柱形圖
  • 組織結構圖
  • 面積圖
  • 圓環圖
  • 地圖/地理圖表
  • 折線圖
  • 餅圖

但是,網際網路上還有一些其他的 JavaScript 庫,比如 D3.js,可以用來繪製各種圖形。

廣告