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

如何为React Native动画圆环头部添加边框与阴影/标记

实现Apple Watch风格的活动圆环(超100%重叠+头部标记)

一、解决超100%圆环重叠问题

默认SVG的strokeDasharray设单值时,进度超过100%不会重复绘制。需调整以下逻辑:

  • 将strokeDasharray设置为[circleCircumference, circleCircumference],允许SVG重复渲染圆环段
  • 修改strokeDashoffset的插值规则,通过extrapolate: 'extend'支持超过1的进度值,实现无限延伸的重叠效果

二、添加圆环头部标记(带边框+阴影)

通过计算动画进度对应的坐标,绘制跟随圆环头部的带标记小圆:

  • 基于进度值插值计算头部实时坐标,与圆环动画同步
  • 在SVG的<Defs>中添加阴影滤镜,模拟Apple Watch的标记阴影
  • 绘制带白色边框、渐变填充的动态小圆,覆盖圆环线帽位置

修改后的完整代码

import React from 'react';
import { Animated } from 'react-native';
import Svg, { Defs, LinearGradient, Stop, G, Circle, Filter, FeDropShadow } from 'react-native-svg';

const Ring = ({
  scaledWidth,
  scaledHeight,
  viewBox,
  gradientEndColor,
  gradientStartColor,
  radius,
  bgColor,
  circleCircumference,
  progress, // 传入的Animated.Value,支持超过1的值(如2代表200%)
  customIcon
}) => {
  // 计算支持超100%进度的strokeDashoffset
  const strokeDashoffset = progress.interpolate({
    inputRange: [0, 1],
    outputRange: [circleCircumference, 0],
    extrapolate: 'extend',
  });

  // 计算头部标记的实时坐标(适配旋转后的G坐标系)
  const headX = progress.interpolate({
    inputRange: [0, 1],
    outputRange: [
      90 + radius * Math.cos(0),
      90 + radius * Math.cos(2 * Math.PI)
    ],
    extrapolate: 'extend',
  });

  const headY = progress.interpolate({
    inputRange: [0, 1],
    outputRange: [
      90 + radius * Math.sin(0),
      90 + radius * Math.sin(2 * Math.PI)
    ],
    extrapolate: 'extend',
  });

  return (
    <Svg
      width={scaledWidth}
      height={scaledHeight}
      viewBox={viewBox}
      style={{ position: "absolute" }}
    >
      <Defs>
        <LinearGradient id="gradient" x1="0%" y1="0%" x2="100%" y2="0%">
          <Stop offset="0%" stopColor={gradientEndColor} />
          <Stop offset="100%" stopColor={gradientStartColor} />
        </LinearGradient>
        {/* 头部标记的阴影滤镜 */}
        <Filter id="headShadow" x="-20%" y="-20%" width="140%" height="140%">
          <FeDropShadow dx={0} dy={2} stdDeviation={3} floodColor="rgba(0,0,0,0.3)" />
        </Filter>
      </Defs>
      <G rotation={-90} originX="90" originY="90">
        {/* 外层黑圈 */}
        <Circle
          cx="50%"
          cy="50%"
          r={radius + 5}
          stroke="black"
          fill="transparent"
          strokeWidth={11}
        />
        {/* 背景圆环 */}
        <Circle
          cx="50%"
          cy="50%"
          r={radius}
          stroke={bgColor}
          fill="transparent"
          strokeWidth="19"
        />
        {/* 支持重叠的动画圆环 */}
        <AnimatedCircle
          cx="50%"
          cy="50%"
          r={radius}
          stroke="url(#gradient)"
          fill="transparent"
          strokeWidth="19"
          strokeDasharray={[circleCircumference, circleCircumference]}
          strokeDashoffset={strokeDashoffset}
          strokeLinecap="round"
        />
        {/* 头部标记:带边框和阴影的小圆 */}
        <Animated.Circle
          cx={headX}
          cy={headY}
          r={10}
          stroke="#ffffff"
          strokeWidth={2}
          fill="url(#gradient)"
          filter="url(#headShadow)"
        />
      </G>
      {customIcon(radius)}
    </Svg>
  );
};

export default Ring;

关键说明

  • 超100%重叠:strokeDasharray=[周长, 周长]配合偏移值的无限延伸,让进度超过1时圆环自动重复绘制
  • 头部标记:通过进度值插值实现坐标同步,白色边框+阴影滤镜完全匹配Apple Watch的标记样式
  • 动画同步:头部标记与圆环共享同一个progress动画值,确保运动轨迹完全一致

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 10:17:10