原生 JavaScript 实现 Win8 风格旋转圆圈进度条

沿途有光
沿途有光
发布时间:2026-10-14| 5人浏览过
原创

通过面向对象设计与三角函数坐标计算,使用原生 JavaScript 实现类似 Windows 8 风格的旋转加载进度条,包含完整的源码与运行原理说明。

实现原理概述

该进度条的实现主要依赖以下三个核心技术点:

  • 面向对象封装:将每个运动的“圆点”抽象为一个 ProgressBarWin8 类,管理其自身的样式、位置、角度和定时器状态。
  • 三角函数定位:利用正弦(Math.sin)和余弦(Math.cos)函数,根据当前角度和半径实时计算圆点在 X/Y 轴上的像素坐标。
  • 动态定时器延迟:通过判断圆点当前所在的水平位置(相对于圆心),动态调整 setTimeout 的延迟毫秒数,从而模拟出加速(左侧慢)和减速(右侧快)的物理惯性效果。

核心逻辑与参数说明

第1步:定义圆点类结构与样式

首先需要建立圆点的“模板”,规定其半径、颜色、大小以及默认的运动初始角度。

  • radius: 圆的半径,决定轨道大小。
  • angle: 起始角度,默认为 270 度(对应圆周上方)。
  • style: CSS 样式集合,注意必须设置 position: absolute 才能通过修改 left/top 属性来移动元素。

第2步:数学公式映射坐标

在浏览器中,圆形的轨迹计算需将角度转换为弧度。公式如下:

X 轴坐标 = cos(弧度) * 半径 + 圆心X

Y 轴坐标 = sin(弧度) * 半径 + 圆心Y

其中弧度计算公式为:Math.PI * 角度 / 180。

第3步:运动循环与速度调节

这是产生视觉动感的关键。代码逻辑如下:

// 每次调用 run 方法时更新角度
this.angle++;

// 判断当前位置与圆心水平关系的偏移
if (this.position.left < this.fixed.left) {
    // 左半区:增加延迟,模拟减速/起步阻力
    this.delay += 0.5;
} else {
    // 右半区:减少延迟,模拟加速/重力势能转化
    this.delay -= 0.5;
}

// 再次执行 run,形成递归式循环
this.timer = setTimeout(() => {
    scope.run();
}, this.delay);

完整源代码实现

以下是整合后的完整 HTML/JS 代码,可直接保存为 .html 文件在浏览器中运行。

复制代码
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>仿win8等待进度条</title>
<style>
body {
    margin: 0;
    padding: 0;
    background: #333; /* 深色背景使白色圆点更明显 */
    overflow: hidden;
}
</style>
</head>
<body>
<script>
/* 
 * 准备条件:
 * 弧度角度转换公式:弧度=Math.PI*角度/180;
 * 圆x轴坐标: Math.cos(Math.PI * 角度/ 180) * 半径 + 圆心x
 * 圆y轴坐标: Math.sin(Math.PI * 角度/ 180) * 半径 + 圆心y
 */

// 圆点元素类
function ProgressBarWin8() {
    this.fixed = { left: 0, top: 0 };      // 圆心相对屏幕坐标
    this.position = { left: 0, top: 0 };   // 当前圆点坐标
    this.radius = 70;                      // 圆半径
    this.angle = 270;                      // 起始角度(顶部)
    this.delay = 30;                       // 基础定时器延迟
    this.timer = null;
    this.dom = null;
    
    // 圆点样式配置
    this.style = {
        position: "absolute",
        width: "10px",
        height: "10px",
        background: "#fff",
        "border-radius": "5px"
    };
}

ProgressBarWin8.prototype = {
    // 运动主方法
    run: function() {
        if (this.timer) clearTimeout(this.timer);

        // 1. 重新计算坐标
        this.position.left = Math.cos(Math.PI * this.angle / 180) * this.radius + this.fixed.left;
        this.position.top = Math.sin(Math.PI * this.angle / 180) * this.radius + this.fixed.top;
        
        // 2. 应用样式
        this.dom.style.left = this.position.left + "px";
        this.dom.style.top = this.position.top + "px";

        // 3. 角度递增
        this.angle++;

        // 4. 动态调整速度(关键特效逻辑)
        if (this.position.left < this.fixed.left) {
            this.delay += 0.5;
        } else {
            this.delay -= 0.5;
        }

        var scope = this;
        // 5. 延迟执行
        this.timer = setTimeout(function () {
            scope.run();
        }, this.delay);
    },

    // 初始化 DOM 与位置
    defaultSetting: function () {
        this.dom = document.createElement("span");
        for (var property in this.style) {
            this.dom.style[property] = this.style[property];
        }
        
        // 定位到屏幕中心
        this.fixed.left = window.innerWidth / 2;
        this.fixed.top = window.innerHeight / 2;
        
        // 计算并放置初始位置
        this.position.left = Math.cos(Math.PI * this.angle / 180) * this.radius + this.fixed.left;
        this.position.top = Math.sin(Math.PI * this.angle / 180) * this.radius + this.fixed.top;
        this.dom.style.left = this.position.left + "px";
        this.dom.style.top = this.position.top + "px";
        
        document.body.appendChild(this.dom);
        return this;
    }
};

// 全局变量
var progressArray = []; // 存储生成的圆点对象
var tempArray = [];     // 辅助重置数组
var timer = 200;        // 间隔多少毫秒生成一个圆点

// 创建圆点对象实例
for (var i = 0; i < 5; ++i) {
    progressArray.push(new ProgressBarWin8().defaultSetting());
}

// 数组扩展each方法,用于统一处理数组内对象的属性重置
Array.prototype.each = function (fn) {
    for (var i = 0, len = this.length; i < len;) {
        fn.call(this[i++], arguments);
    }
};

// 窗口尺寸改变时,更新所有圆点的圆心坐标以居中
window.onresize = function () {
    tempArray.each(function () {
        this.fixed.left = window.innerWidth / 2;
        this.fixed.top = window.innerHeight / 2;
    });
};

// 启动动画引擎:定时从队列取出一个对象开始运行
var startTimer = setInterval(function () {
    if (progressArray.length <= 0) {
        clearInterval(startTimer);
    } else {
        var entity = progressArray.shift();
        tempArray.push(entity); // 存入暂存区以便resize重算
        entity.run();           // 开始运动
    }
}, timer);

</script>
</body>
</html>

总结

本方案通过纯原生 JavaScript 实现了轻量级的加载动画,未依赖任何第三方库。其优势在于对数学坐标系的理解以及对定时器精度控制的灵活应用,适用于需要自定义加载效果的非重型业务场景。 以上就是原生javascript模仿win8等待提示圆圈进度条的详细内容,更多关于javascript动画资料请关注本站其它相关文章!

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。