使用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;
                }
            }
        }
    }
}
相关推荐
偷光3 小时前
浏览器中的隐藏IDE: Elements (元素) 面板
开发语言·前端·ide·php
DKPT3 小时前
JVM栈溢出和堆溢出哪个先满?
java·开发语言·jvm·笔记·学习
gopyer7 小时前
180课时吃透Go语言游戏后端开发6:Go语言的循环语句
开发语言·游戏·golang·循环语句
千码君20168 小时前
React Native:快速熟悉react 语法和企业级开发
javascript·react native·react.js·vite·hook
楼田莉子9 小时前
Qt开发学习——QtCreator深度介绍/程序运行/开发规范/对象树
开发语言·前端·c++·qt·学习
暮之沧蓝10 小时前
Vue总结
前端·javascript·vue.js
木易 士心10 小时前
Promise深度解析:前端异步编程的核心
前端·javascript
韩立学长10 小时前
【开题答辩实录分享】以《基于python的奶茶店分布数据分析与可视化》为例进行答辩实录分享
开发语言·python·数据分析
Joker Zxc10 小时前
【前端基础】20、CSS属性——transform、translate、transition
前端·css
天若有情67310 小时前
C++空值初始化利器:empty.h使用指南
开发语言·c++