当前位置:首页 > 前端开发 > 正文

html如何实现球体旋转

HTML中,通过CSS设置球体元素的 border-radius为50%使其呈圆形,再利用 transform-style: preserve-3danimation属性结合关键帧动画实现旋转

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来控制动画,例如在用户交互时暂停或启动动画。

html如何实现球体旋转  第1张

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();
    }
CSS
0