上一篇
html如何实现球体旋转
- 前端开发
- 2025-07-08
- 3895
HTML中,通过CSS设置球体元素的
border-radius
为50%使其呈圆形,再利用
transform-style: preserve-3d
和
animation
属性结合关键帧动画实现旋转
HTML中实现球体旋转,可以通过多种方法来实现,以下是几种常见的实现方式及其详细步骤:
使用CSS3和HTML实现简单球体旋转
创建HTML结构
创建一个基本的HTML结构,用于展示旋转的球体,可以使用一个<div>
元素来代表球体。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0">Rotating Sphere</title> <link rel="stylesheet" href="styles.css"> </head> <body> <div class="sphere"></div> <script src="script.js"></script> </body> </html>
编写CSS样式
使用CSS3来设置球体的外观和旋转动画,通过border-radius
属性将<div>
元素变为圆形,并使用@keyframes
定义旋转动画。
body { display: flex; justify-content: center; align-items: center; height: 100vh; background-color: #f0f0f0; } .sphere { width: 100px; height: 100px; background: radial-gradient(circle, #ff0000 0%, #ff7f00 30%, #ffff00 50%, #7fff00 70%, #00ff00 100%); border-radius: 50%; animation: rotate 4s infinite linear; } @keyframes rotate { from { transform: rotateX(0) rotateY(0); } to { transform: rotateX(360deg) rotateY(360deg); } }
使用JavaScript控制动画(可选)
虽然CSS3的动画已经能够实现旋转效果,但有时可能需要使用JavaScript来控制动画,例如在用户交互时暂停或启动动画。
document.addEventListener('DOMContentLoaded', () => { const sphere = document.querySelector('.sphere'); sphere.addEventListener('click', () => { if (sphere.style.animationPlayState === 'paused') { sphere.style.animationPlayState = 'running'; } else { sphere.style.animationPlayState = 'paused'; } }); });
使用WebGL实现更复杂的3D球体旋转
对于需要更高性能和更复杂效果的场景,可以使用WebGL来实现3D球体旋转,WebGL允许在HTML中渲染3D图形,并结合JavaScript来实现动态效果。
创建HTML和CSS基础结构
创建一个基本的HTML文件和CSS文件,用于包含WebGL画布。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0">WebGL Rotating Sphere</title> <link rel="stylesheet" href="styles.css"> </head> <body> <canvas id="glcanvas" width="600" height="400"></canvas> <script src="script.js"></script> </body> </html>
body { display: flex; justify-content: center; align-items: center; height: 100vh; background-color: #f0f0f0; } canvas { border: 1px solid white; }
初始化WebGL上下文并创建球体几何结构
在JavaScript中,初始化WebGL上下文,并定义球体的顶点和索引。
const canvas = document.getElementById('glcanvas'); const gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl'); if (!gl) { alert('Unable to initialize WebGL. Your browser may not support it.'); } gl.clearColor(0.0, 0.0, 0.0, 1.0); gl.clear(gl.COLOR_BUFFER_BIT); function createSphere(radius, latitudeBands, longitudeBands) { let vertices = []; let indices = []; for (let latNumber = 0; latNumber <= latitudeBands; latNumber++) { let theta = latNumber Math.PI / latitudeBands; let sinTheta = Math.sin(theta); let cosTheta = Math.cos(theta); for (let longNumber = 0; longNumber <= longitudeBands; longNumber++) { let phi = longNumber 2 Math.PI / longitudeBands; let sinPhi = Math.sin(phi); let cosPhi = Math.cos(phi); let x = cosPhi sinTheta; let y = cosTheta; let z = sinPhi sinTheta; let u = 1 (longNumber / longitudeBands); let v = 1 (latNumber / latitudeBands); vertices.push(radius x); vertices.push(radius y); vertices.push(radius z); } } for (let latNumber = 0; latNumber < latitudeBands; latNumber++) { for (let longNumber = 0; longNumber < longitudeBands; longNumber++) { let first = (latNumber (longitudeBands + 1)) + longNumber; let second = first + longitudeBands + 1; indices.push(first); indices.push(second); indices.push(first + 1); indices.push(second); indices.push(second + 1); indices.push(first + 1); } } return { vertices: new Float32Array(vertices), indices: new Uint16Array(indices) }; } const sphere = createSphere(1, 30, 30);
创建WebGL着色器并渲染球体
编写顶点着色器和片段着色器,并将它们链接到WebGL程序中,将球体的顶点和索引数据上传到WebGL缓冲区,并绘制球体。
const vertexShaderSource = ` attribute vec3 aVertexPosition; uniform mat4 uModelViewMatrix; uniform mat4 uProjectionMatrix; void main(void) { gl_Position = uProjectionMatrix uModelViewMatrix vec4(aVertexPosition, 1.0); } `; const fragmentShaderSource = ` void main(void) { gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0); } `; function compileShader(gl, source, type) { const shader = gl.createShader(type); gl.shaderSource(shader, source); gl.compileShader(shader); if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { console.error('An error occurred compiling the shaders: ' + gl.getShaderInfoLog(shader)); gl.deleteShader(shader); return null; } return shader; } const vertexShader = compileShader(gl, vertexShaderSource, gl.VERTEX_SHADER); const fragmentShader = compileShader(gl, fragmentShaderSource, gl.FRAGMENT_SHADER); const shaderProgram = gl.createProgram(); gl.attachShader(shaderProgram, vertexShader); gl.attachShader(shaderProgram, fragmentShader); gl.linkProgram(shaderProgram); if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) { console.error('Unable to initialize the shader program: ' + gl.getProgramInfoLog(shaderProgram)); } gl.useProgram(shaderProgram); const vertexPositionAttribute = gl.getAttribLocation(shaderProgram, 'aVertexPosition'); gl.enableVertexAttribArray(vertexPositionAttribute); const uModelViewMatrix = gl.getUniformLocation(shaderProgram, 'uModelViewMatrix'); const uProjectionMatrix = gl.getUniformLocation(shaderProgram, 'uProjectionMatrix'); const vertexBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer); gl.bufferData(gl.ARRAY_BUFFER, sphere.vertices, gl.STATIC_DRAW); const indexBuffer = gl.createBuffer(); gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer); gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, sphere.indices, gl.STATIC_DRAW);
使用Canvas和JavaScript实现球体旋转
对于需要更多控制或更复杂交互的场景,可以使用Canvas和JavaScript来实现球体旋转,这种方法允许逐帧绘制球体,并实现更复杂的动画效果。
获取Canvas元素和设置初始参数
获取Canvas元素,并根据设备的DPI进行缩放,定义一些全局变量,包括Canvas的宽度、高度、球体旋转的角度和存储所有点的数组。
const canvas = document.querySelector('#scene'); canvas.width = canvas.clientWidth; canvas.height = canvas.clientHeight; const ctx = canvas.getContext('2d'); if (window.devicePixelRatio > 1) { canvas.width = canvas.clientWidth 2; canvas.height = canvas.clientHeight 2; ctx.scale(2, 2); } let width = canvas.clientWidth; let height = canvas.clientHeight; let rotation = 0; let dots = [];
定义点类和创建球体函数
定义一个Dot
类,表示球体上的每个点的属性和方法,编写createDots
函数来生成一定数量的点,并分别标记为不同的颜色。
class Dot { constructor(x, y, z, color) { this.x = x; this.y = y; this.z = z; this.color = color; this.xProject = 0; this.yProject = 0; this.sizeProjection = 0; } project(sin, cos) { const rotX = cos this.x + sin (this.z GLOBE_CENTER_Z); const rotZ = -sin this.x + cos (this.z GLOBE_CENTER_Z) + GLOBE_CENTER_Z; this.sizeProjection = FIELD_OF_VIEW / (FIELD_OF_VIEW rotZ); this.xProject = (rotX this.sizeProjection) + PROJECTION_CENTER_X; this.yProject = (this.y this.sizeProjection) + PROJECTION_CENTER_Y; } draw(sin, cos) { this.project(sin, cos); ctx.beginPath(); ctx.arc(this.xProject, this.yProject, DOT_RADIUS this.sizeProjection, 0, Math.PI 2); ctx.fillStyle = this.color; ctx.closePath(); ctx.fill(); }