JavaScript - 图形



在 JavaScript 中,可以使用 Canvas API 创建图形。但是,开发人员也可以使用其他一些库,如 p5.js、chart.js、pllotly.js、Google 图表等,来绘制各种图形和图表。

在这里,我们将探索其中一些库,并在一些示例的帮助下了解它们

WebGL 协议

WebGL 允许开发人员使用代码从头开始创建图形,并将其集成到 Web 页面中。它直接与 HTML <canvas> 元素进行操作,从而允许以 GPU 加速使用物理和图像处理以及效果作为网页画布的一部分。

WebGL 允许开发从 2D 游戏到复杂的 3D 可视化应用程序的各种应用程序。此外,大多数现代浏览器都支持它,这使其成为开发人员开发图形的首选。

在下面的代码中,我们使用 <canvas> 元素创建了一个画布,并使用 id 在 JavaScript 中访问它。接下来,我们使用 getCContext() 方法来获取 WebGL 的上下文。如果浏览器不支持,则 getContext() 方法将返回 undefined 值。

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 图表库还提供各种类型的图表,包括下面的图表。

  • 散点图
  • 条形图 / 柱状图
  • 組織圖
  • 面积图
  • 圆环图
  • 地图 / 地理图
  • 折线图
  • 饼图

但是,互联网上还有更多可用的 JavaScript 库,例如 D3.js 可用于绘制各种图形。