You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用HTML/CSS/JS实现环形旋转图片的定点放大与内容切换

解决方案

核心思路

  1. 保留父容器的旋转停顿动画,通过定时检测父容器的旋转角度,给处于右侧(90度位置)的圆形添加放大样式。
  2. 为每个圆形绑定对应的内容区块,默认隐藏,当对应圆形激活时自动切换显示内容。

完整代码实现

HTML 代码

<div id="parent-circle">
    <div class="circle blue" data-content="content-blue">健康档案</div>
    <div class="circle pink" data-content="content-pink">运动记录</div>
    <div class="circle lime" data-content="content-lime">饮食日志</div>
    <div class="circle orange" data-content="content-orange">睡眠数据</div>
</div>
<!-- 对应每个圆形的内容区块 -->
<div class="mt-5 content-container pt-2">
    <div id="content-blue" class="content active">
        <h1>健康档案</h1>
        <p class="w-75">Lorem ipsum dolor sit, amet consectetur adipisicing elit. Dolorum, doloremque!</p>
    </div>
    <div id="content-pink" class="content">
        <h1>运动记录</h1>
        <p class="w-75">记录每日运动时长、步数及消耗卡路里,助你保持活力。</p>
    </div>
    <div id="content-lime" class="content">
        <h1>饮食日志</h1>
        <p class="w-75">追踪每日摄入营养,合理搭配饮食,养成健康饮食习惯。</p>
    </div>
    <div id="content-orange" class="content">
        <h1>睡眠数据</h1>
        <p class="w-75">分析睡眠周期,改善睡眠质量,让你拥有充沛精力。</p>
    </div>
</div>

CSS 代码

body {
    width: 90vw;
    height: 90vh;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    margin: 0;
}

#parent-circle {
    position: relative;
    width: 20vw;
    height: 20vw;
    border: 0.4vw solid rgba(0, 0, 0, 0.4);
    border-radius: 50%;
    animation: rotate 14s infinite linear;
}

#parent-circle .circle {
    display: flex;
    justify-content: center;
    align-items: center;
    position: absolute;
    width: 30%;
    height: 30%;
    margin: -15%;
    border-radius: 50%;
    top: 50%;
    left: 50%;
    color: white;
    font-size: 0.8vw;
    transition: transform 0.3s ease;
    /* 反向旋转保持文字正向 */
    animation: spin-reverse 14s infinite linear;
}

/* 放大激活状态 */
#parent-circle .circle.active {
    transform: scale(1.8);
    z-index: 10;
}

#parent-circle .circle.blue {
    background-color: #416ba9;
    transform: translate(10vw);
}

#parent-circle .circle.pink {
    background-color: #e6427a;
    transform: rotate(90deg) translate(10vw) rotate(-90deg);
}

#parent-circle .circle.lime {
    background-color: #cddb00;
    transform: rotate(180deg) translate(10vw) rotate(-180deg);
}

#parent-circle .circle.orange {
    background-color: #e0592a;
    transform: rotate(270deg) translate(10vw) rotate(-270deg);
}

.content-container {
    margin-top: 2rem;
    width: 60vw;
}

.content {
    display: none;
}

.content.active {
    display: block;
}

/* 父容器旋转动画 */
@keyframes rotate {
    0%, 12.5% { transform: rotate(0deg); }
    12.5%, 25% { transform: rotate(90deg); }
    25%, 37.5% { transform: rotate(90deg); }
    37.5%, 50% { transform: rotate(180deg); }
    50%, 62.5% { transform: rotate(180deg); }
    62.5%, 75% { transform: rotate(270deg); }
    75%, 87.5% { transform: rotate(270deg); }
    87.5%, 100% { transform: rotate(360deg); }
}

/* 子元素反向旋转,保持文字正向 */
@keyframes spin-reverse {
    from { transform: inherit rotate(0deg); }
    to { transform: inherit rotate(-360deg); }
}

JavaScript 代码

const parentCircle = document.getElementById('parent-circle');
const circles = document.querySelectorAll('.circle');
const contents = document.querySelectorAll('.content');
const animationDuration = 14000; // 动画总时长14秒
const intervalTime = animationDuration / 8; // 每个阶段的时长:14s/8=1.75s

// 定义每个旋转角度对应的激活圆形
const angleToCircleMap = {
    0: '.blue',
    90: '.pink',
    180: '.lime',
    270: '.orange',
    360: '.blue'
};

function updateActiveCircle() {
    // 获取当前动画进度,解析旋转角度
    const computedStyle = window.getComputedStyle(parentCircle);
    const transform = computedStyle.getPropertyValue('transform');
    let angle = 0;
    if (transform !== 'none') {
        const matrix = transform.split('(')[1].split(')')[0].split(',');
        const cos = parseFloat(matrix[0]);
        angle = Math.round(Math.acos(cos) * (180 / Math.PI));
        const sin = parseFloat(matrix[1]);
        if (sin < 0) angle = 360 - angle;
    }

    // 匹配当前角度对应的圆形
    let targetCircleSelector = '';
    if (angle >= 0 && angle < 45) targetCircleSelector = angleToCircleMap[0];
    else if (angle >= 45 && angle < 135) targetCircleSelector = angleToCircleMap[90];
    else if (angle >= 135 && angle < 225) targetCircleSelector = angleToCircleMap[180];
    else if (angle >= 225 && angle < 315) targetCircleSelector = angleToCircleMap[270];
    else targetCircleSelector = angleToCircleMap[360];

    // 移除所有激活状态
    circles.forEach(circle => circle.classList.remove('active'));
    contents.forEach(content => content.classList.remove('active'));

    // 添加当前激活状态
    const activeCircle = document.querySelector(targetCircleSelector);
    activeCircle.classList.add('active');
    const contentId = activeCircle.dataset.content;
    document.getElementById(contentId).classList.add('active');
}

// 定时检查更新,间隔略小于阶段时长避免延迟
setInterval(updateActiveCircle, intervalTime - 50);

// 初始执行一次,确保页面加载时状态正确
updateActiveCircle();

代码说明

  1. HTML部分:给每个圆形添加data-content属性绑定对应内容区块ID,新增四个内容区块通过active类控制显示/隐藏。
  2. CSS部分:新增.active类实现圆形放大效果,调整子元素反向旋转动画时长与父容器同步,确保文字始终正向显示。
  3. JavaScript部分:定时检测父容器旋转角度,匹配当前处于右侧的圆形并添加激活状态,同时切换对应内容区块的显示。

内容的提问来源于stack exchange,提问作者Bollampalli Vinaykumar1119

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 01:18:18