提供的引用中未提及“cavans3d”,推测可能是“Canvas 3D”。一般来说,在 HTML5 里,单纯的 Canvas 主要用于 2D 绘图,不过借助 WebGL(Web Graphics Library)能在 Canvas 上实现 3D 绘图效果。
### 介绍
HTML5 的 Canvas 本身是一个绘图 API,用于绘制 2D 图形,可在网页上绘制各种复杂图形、图像和动画效果,为网页开发者提供了较大创作自由度,能创造出更生动、有趣且交互性强的网页内容 [^4]。而通过 WebGL 技术,可在 Canvas 上实现 3D 绘图效果,WebGL 是一种 3D 绘图标准,它把 OpenGL ES 2.0 引入到了浏览器中,让网页开发者能在 Canvas 元素上进行硬件加速的 3D 渲染。
### 使用方法
以下是一个简单的使用 WebGL 在 Canvas 上绘制 3D 图形(立方体)的示例代码:
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>WebGL 3D Cube</title>
</head>
<body>
<canvas id="glCanvas" width="640" height="480"></canvas>
<script>
// 获取 canvas 元素
const canvas = document.getElementById('glCanvas');
// 获取 WebGL 上下文
const gl = canvas.getContext('webgl');
if (!gl) {
alert('Unable to initialize WebGL. Your browser or machine may not support it.');
return;
}
// 顶点着色器代码
const vsSource = `
attribute vec4 aVertexPosition;
attribute vec4 aVertexColor;
uniform mat4 uModelViewMatrix;
uniform mat4 uProjectionMatrix;
varying lowp vec4 vColor;
void main(void) {
gl_Position = uProjectionMatrix * uModelViewMatrix * aVertexPosition;
vColor = aVertexColor;
}
`;
// 片元着色器代码
const fsSource = `
varying lowp vec4 vColor;
void main(void) {
gl_FragColor = vColor;
}
`;
// 创建着色器程序
function initShaderProgram(gl, vsSource, fsSource) {
const vertexShader = loadShader(gl, gl.VERTEX_SHADER, vsSource);
const fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fsSource);
const shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertexShader);
gl.attachShader(shaderProgram, fragmentShader);
gl.linkProgram(shaderProgram);
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);
gl.shaderSource(shader, source);
gl.compileShader(shader);
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
alert('An error occurred compiling the shaders: ' + gl.getShaderInfoLog(shader));
gl.deleteShader(shader);
return null;
}
return shader;
}
const shaderProgram = initShaderProgram(gl, vsSource, fsSource);
// 创建缓冲区
function initBuffers(gl) {
const positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
const positions = [
// 前面
-1.0, -1.0, 1.0,
1.0, -1.0, 1.0,
1.0, 1.0, 1.0,
-1.0, 1.0, 1.0,
// 后面
-1.0, -1.0, -1.0,
-1.0, 1.0, -1.0,
1.0, 1.0, -1.0,
1.0, -1.0, -1.0,
// 顶面
-1.0, 1.0, -1.0,
-1.0, 1.0, 1.0,
1.0, 1.0, 1.0,
1.0, 1.0, -1.0,
// 底面
-1.0, -1.0, -1.0,
1.0, -1.0, -1.0,
1.0, -1.0, 1.0,
-1.0, -1.0, 1.0,
// 右面
1.0, -1.0, -1.0,
1.0, 1.0, -1.0,
1.0, 1.0, 1.0,
1.0, -1.0, 1.0,
// 左面
-1.0, -1.0, -1.0,
-1.0, -1.0, 1.0,
-1.0, 1.0, 1.0,
-1.0, 1.0, -1.0
];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);
const colorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
const faceColors = [
[1.0, 1.0, 1.0, 1.0], // 前面:白色
[1.0, 0.0, 0.0, 1.0], // 后面:红色
[0.0, 1.0, 0.0, 1.0], // 顶面:绿色
[0.0, 0.0, 1.0, 1.0], // 底面:蓝色
[1.0, 1.0, 0.0, 1.0], // 右面:黄色
[1.0, 0.0, 1.0, 1.0] // 左面:紫色
];
let colors = [];
for (let j = 0; j < faceColors.length; ++j) {
const c = faceColors[j];
colors = colors.concat(c, c, c, c);
}
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW);
const indexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
const indices = [
0, 1, 2, 0, 2, 3, // 前面
4, 5, 6, 4, 6, 7, // 后面
8, 9, 10, 8, 10, 11, // 顶面
12, 13, 14, 12, 14, 15, // 底面
16, 17, 18, 16, 18, 19, // 右面
20, 21, 22, 20, 22, 23 // 左面
];
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
return {
position: positionBuffer,
color: colorBuffer,
indices: indexBuffer
};
}
const buffers = initBuffers(gl);
function drawScene(gl, programInfo, buffers) {
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clearDepth(1.0);
gl.enable(gl.DEPTH_TEST);
gl.depthFunc(gl.LEQUAL);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
const fieldOfView = 45 * Math.PI / 180;
const aspect = gl.canvas.clientWidth / gl.canvas.clientHeight;
const zNear = 0.1;
const zFar = 100.0;
const projectionMatrix = mat4.create();
mat4.perspective(projectionMatrix,
fieldOfView,
aspect,
zNear,
zFar);
const modelViewMatrix = mat4.create();
mat4.translate(modelViewMatrix,
modelViewMatrix,
[-0.0, 0.0, -6.0]);
{
const numComponents = 3;
const type = gl.FLOAT;
const normalize = false;
const stride = 0;
const offset = 0;
gl.bindBuffer(gl.ARRAY_BUFFER, buffers.position);
gl.vertexAttribPointer(
programInfo.attribLocations.vertexPosition,
numComponents,
type,
normalize,
stride,
offset);
gl.enableVertexAttribArray(
programInfo.attribLocations.vertexPosition);
}
{
const numComponents = 4;
const type = gl.FLOAT;
const normalize = false;
const stride = 0;
const offset = 0;
gl.bindBuffer(gl.ARRAY_BUFFER, buffers.color);
gl.vertexAttribPointer(
programInfo.attribLocations.vertexColor,
numComponents,
type,
normalize,
stride,
offset);
gl.enableVertexAttribArray(
programInfo.attribLocations.vertexColor);
}
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buffers.indices);
gl.useProgram(programInfo.program);
gl.uniformMatrix4fv(
programInfo.uniformLocations.projectionMatrix,
false,
projectionMatrix);
gl.uniformMatrix4fv(
programInfo.uniformLocations.modelViewMatrix,
false,
modelViewMatrix);
{
const vertexCount = 36;
const type = gl.UNSIGNED_SHORT;
const offset = 0;
gl.drawElements(gl.TRIANGLES, vertexCount, type, offset);
}
}
const programInfo = {
program: shaderProgram,
attribLocations: {
vertexPosition: gl.getAttribLocation(shaderProgram, 'aVertexPosition'),
vertexColor: gl.getAttribLocation(shaderProgram, 'aVertexColor')
},
uniformLocations: {
projectionMatrix: gl.getUniformLocation(shaderProgram, 'uProjectionMatrix'),
modelViewMatrix: gl.getUniformLocation(shaderProgram, 'uModelViewMatrix')
}
};
drawScene(gl, programInfo, buffers);
</script>
</body>
</html>
```
上述代码实现了在网页上使用 WebGL 在 Canvas 中绘制一个 3D 立方体,基本步骤为:获取 Canvas 元素和 WebGL 上下文;创建并编译顶点着色器和片元着色器;创建着色器程序;创建并填充缓冲区(顶点、颜色、索引);最后进行绘制操作。
### 应用场景
- **Web 游戏开发**:借助 Canvas 3D 可以创建出具有 3D 效果的游戏场景、角色和道具等,为玩家带来更逼真的游戏体验。
- **数据可视化**:可将数据以 3D 图形的形式展示出来,如 3D 柱状图、3D 散点图等,能更直观地呈现数据之间的关系和趋势。
- **虚拟展示**:在房地产、家居等行业,利用 Canvas 3D 可以创建虚拟样板间,让用户可以 360 度无死角地查看房间布局和装修效果;在工业领域,可用于展示机械产品的 3D 模型和工作原理。
- **教育领域**:在科学、工程等学科的教学中,使用 Canvas 3D 可以创建 3D 模型来展示复杂的结构和过程,如分子结构、天体运动等,帮助学生更好地理解知识。