使用js和css 实现div旋转围绕圆分布排列

记录,以防忘记

围绕圆

复制代码
import React, { useEffect } from 'react';
import './index.scoped.scss';


const Test = () => {


    const arr = Array.from({ length: 28 }, (_, index) => index + 1);

    useEffect(() => {
        const dayTotal = arr.length;

        // 动态设置每个点的旋转角度
        const dots = document.querySelectorAll('.dot') as NodeListOf<HTMLElement>;
        const pDeg = 360 / dayTotal;
        dots.forEach((dot, index) => {
            dot.style.transform = `rotate(${index * pDeg}deg) translate(0, -200px)`;
        });
    }, [arr.length]);


    return <div className='flex items-center justify-center w-full h-[100vh]'>

        <div className='relative bg-gray-700 rounded-full box'>
            {arr.map((item, index) => {
                return <div key={index} className='absolute bg-blue-400 dot'>{item}</div>;
            })}
        </div>
    </div>;
};

export default Test;



// scss


$containSize: 400px;
$ballSize: 20px;

.box {
    width: $containSize;
    height: $containSize;
    position: relative;

    .dot {
        width: $ballSize;
        height: $ballSize;
        position: absolute;
        top: 50%;
        left: 50%;
        margin-left: calc(-1 * $ballSize / 2);
        margin-top: calc(-1 * $ballSize / 2);
        transform-origin: center;
    }
}

进阶 实现loading加载

复制代码
import React, { useEffect } from 'react';
import './index.scoped.scss';


const Test = () => {


    const arr = Array.from({ length: 32 }, (_, index) => index + 1);


    return <div className='flex items-center justify-center w-full h-[100vh] bg-[#5bbff1]'>

        <div className='relative rounded-full loading'>
            {arr.map((item, index) => {
                return <div key={index} className='absolute dot' />;
            })}
        </div>
    </div>;
};

export default Test;



// scss

$containSize: 150px;
$ballSize: 10px;

.loading {
    width: $containSize;
    height: $containSize;

    
    $n: 32; // 小球数量
    $pDeg: calc(360deg / $n);   // 每个小球旋转的角度


    .dot {
        width: $ballSize;
        height: $ballSize;
        top: 0;
        left: 50%;
        margin-left: calc(-1 * $ballSize / 2);
        margin-top: calc(-1 * $ballSize / 2);
        transform-origin: center calc($containSize / 2) + calc($ballSize / 2);
        
        $duration: 2s; // 小球动画总时长

        @for $i from 1 through $n {
            &:nth-child(#{$i}) {
                transform: rotate(calc($i - 1) * $pDeg);

                &::after,
                &::before {
                    animation-delay: -(calc($duration / $n * ($i - 1) * 6));
                }

            }
        }

        &::before,
        &::after {
            content: '';
            position: absolute;
            width: 100%;
            height: 100%;
            border-radius: 100px;
        }

        perspective: 70px;
        transform-style: preserve-3d;

        &::before {
            top: -100%;
            background: #000;
            animation: rotate-black $duration infinite;

            @keyframes rotate-black {
                0% {
                    animation-timing-function: ease-in;
                }

                25% {
                    transform: translate3d(0, 100%, $ballSize);
                    animation-timing-function: ease-out;
                }

                50% {
                    transform: translate3d(0, 200%, 0);
                    animation-timing-function: ease-in;
                }

                75% {
                    transform: translate3d(0, 100%, -$ballSize);
                    animation-timing-function: ease-out;
                }
            }
        }

        &::after {
            top: 100%;
            background: #fff;
            animation: rotate-white $duration infinite;

            @keyframes rotate-white {
                0% {
                    animation-timing-function: ease-in;
                }

                25% {
                    transform: translate3d(0, -100%, -$ballSize);
                    animation-timing-function: ease-out;
                }

                50% {
                    transform: translate3d(0, -200%, 0);
                    animation-timing-function: ease-in;
                }

                75% {
                    transform: translate3d(0, -100%, $ballSize);
                    animation-timing-function: ease-out;
                }
            }
        }
    }
}
相关推荐
初恋叫萱萱7 小时前
构建高性能生成式AI应用:基于Rust Axum与蓝耘DeepSeek-V3.2大模型服务的全栈开发实战
开发语言·人工智能·rust
cyforkk8 小时前
12、Java 基础硬核复习:集合框架(数据容器)的核心逻辑与面试考点
java·开发语言·面试
我材不敲代码12 小时前
Python实现打包贪吃蛇游戏
开发语言·python·游戏
2501_9209317013 小时前
React Native鸿蒙跨平台采用ScrollView的horizontal属性实现横向滚动实现特色游戏轮播和分类导航
javascript·react native·react.js·游戏·ecmascript·harmonyos
身如柳絮随风扬13 小时前
Java中的CAS机制详解
java·开发语言
韩立学长14 小时前
【开题答辩实录分享】以《基于Python的大学超市仓储信息管理系统的设计与实现》为例进行选题答辩实录分享
开发语言·python
东东51615 小时前
智能社区管理系统的设计与实现ssm+vue
前端·javascript·vue.js·毕业设计·毕设
froginwe1115 小时前
Scala 循环
开发语言
catino15 小时前
图片、文件的预览
前端·javascript
m0_7066532315 小时前
C++编译期数组操作
开发语言·c++·算法