【前端可视化探索-01】浏览器中实现可视化的几种方式

1,660 阅读3分钟

开启新的专栏:前端可视化探索。欢迎关注!

在浏览器中实现可视化通常有4种方式:HTML+CSS、SVG、Canvas2D和WebGL。下面将逐个介绍这4种方式的特点、优缺点,以及配合代码和效果图进行演示。

浏览器可视化.png

上图中分别对应四种方式,只看图你区分不了是何种方式绘制的。

1 HTML+CSS

传统的HTML+CSS通常用于呈现普通的Web网页。在可视化中,它可以通过CSS的特性来实现简单的样式调整,例如改变颜色、大小、位置等等。下面是使用HTML+CSS实现一个简单的柱状图效果:

<div class="bar" style="height: 50px;"></div>
<div class="bar" style="height: 80px;"></div>
<div class="bar" style="height: 120px;"></div>
.bar {
  width: 30px;
  background-color: blue;
  margin-right: 10px;
  display: inline-block;
}

这段代码可以实现一个简单的柱状图,每个柱子的高度对应着不同的数值。

优点:

  • 简单易用,不需要额外的库或插件。
  • 可以通过CSS的特性来实现简单的样式调整。

缺点:

  • 在绘制复杂图形时,使用HTML+CSS的能力有限。
  • 无法实现动画效果。

2 SVG

SVG和传统的HTML+CSS的绘图方式差别不大。只不过,HTML元素在绘制矢量图形方面的能力有些不足,而SVG恰好弥补了这方面的缺陷。下面是使用SVG实现一个简单的柱状图效果:

<svg width="130" height="130">
    <rect x="0" y="80" width="30" height="50" fill="#009688" />
    <rect x="50" y="50" width="30" height="80" fill="#009688" />
    <rect x="100" y="10" width="30" height="120" fill="#009688" >
</svg>

这段代码可以实现与前面相同的柱状图效果。

优点:

  • 可以实现复杂的矢量图形。
  • 可以通过CSS样式来调整图形的样式。
  • 可以实现动画效果。

缺点:

  • 对于大量数据的展示,性能可能有所不足。
  • 在绘制复杂图形时,需要手动编写SVG代码,较为繁琐。

3 Canvas2D

Canvas2D是浏览器提供的Canvas API中的其中一种上下文,使用它可以非常方便地绘制出基础的几何图形。下面是使用Canvas2D实现一个简单的柱状图效果:

<canvas id="myCanvas" width="130" height="130"></canvas>
const canvas = document.getElementById("myCanvas");
const ctx = canvas.getContext("2d");
ctx.fillStyle = "#009688";
ctx.fillRect(0, 80, 30, 50);
ctx.fillRect(50, 50, 30, 80);
ctx.fillRect(100, 10, 30, 120);

这段代码可以实现与前面相同的柱状图效果。

优点:

  • 可以实现复杂的几何图形。
  • 可以通过JavaScript代码来动态绘制图形。
  • 在绘制大量数据时,性能较好。

缺点:

  • 对于复杂的动画效果,需要手动编写JavaScript代码。

4 WebGL

WebGL是浏览器提供的Canvas API中的另一种上下文,它是OpenGL ES规范在Web端的实现。我们可以通过它,用GPU渲染各种复杂的2D和3D图形。下面是使用WebGL实现一个简单的柱状图效果:

<canvas id="myCanvas2" width="130" height="130"></canvas>
const canvas = document.getElementById("myCanvas2");
const gl = canvas.getContext("webgl");

const vertexShaderSource = `
    attribute vec2 a_position;
    void main() {
        gl_Position = vec4(a_position, 0.0, 1.0);
    }
    `;

const fragmentShaderSource = `
    precision mediump float;
    uniform vec4 u_color;
    void main() {
        gl_FragColor = u_color;
    }
    `;

const vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vertexShaderSource);
gl.compileShader(vertexShader);

const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fragmentShaderSource);
gl.compileShader(fragmentShader);

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

const positionAttributeLocation = gl.getAttribLocation(program, "a_position");
const colorUniformLocation = gl.getUniformLocation(program, "u_color");

const positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);

const positions = [
    -1, -1,
    -0.54, -1,
    -0.54, 0,
    -0.54, 0,
    -1, 0,
    -1, -1,

    -0.23, -1,
    0.23, -1,
    0.23, 0.4,
    0.23, 0.4,
    -0.23, 0.4,
    -0.23, -1,

    0.54, -1,
    1, -1,
    1, 0.8,
    1, 0.8,
    0.54, 0.8,
    0.54, -1,
];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);

gl.enableVertexAttribArray(positionAttributeLocation);
gl.vertexAttribPointer(positionAttributeLocation, 2, gl.FLOAT, false, 0, 0);

gl.uniform4fv(colorUniformLocation, [0.0, 0.6, 0.53, 1]);
gl.drawArrays(gl.TRIANGLES, 0, positions.length / 2);

这段代码可以实现与前面相同的柱状图效果。

优点:

  • 可以实现复杂的2D和3D图形。
  • 利用了GPU并行处理的特性,在处理大量数据展现的时候,性能大大优于前面三种绘图方式。

缺点:

  • 对于初学者来说,学习成本较高。
  • 需要手写大量的GLSL代码。

综上所述,不同的绘图方式各有优缺点,需要根据具体需求来选择合适的方式。在实际应用中,我们也可以根据不同的场景来组合使用这四种方式,以达到最佳的可视化效果。