花潮论坛

搜索
热搜: 活动 交友 discuz
查看: 22|回复: 4

CSS相抵路径动画自适应路径设计

[复制链接]
  • TA的每日心情
    奋斗
    2026-7-22 18:40
  • 签到天数: 1877 天

    [LV.Master]伴坛终老

    3283

    主题

    13万

    回帖

    29万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9

    花潮帅哥鼠牛虎兔龙蛇马羊猴鸡狗猪多彩人生星月交辉奔放热烈海样胸怀春风拂面火热情怀优雅迷人神秘浪漫相遇之美鹰傲苍穹花好月圆紫色情节飞龙在天王者至尊大将风范音画大师天籁妙音共看流星风雨同行我心永远幸福快乐喜乐安康侠骨柔肠心想事成开朗大方花潮管理

    发表于 2026-7-22 19:28 | 显示全部楼层 |阅读模式

    请马上登录,朋友们都在花潮里等着你哦:)

    您需要 登录 才可以下载或查看,没有账号?立即注册

    x

    相抵路径CSS动画可以实现元素在任意指定路径上定位或移动,用到两个业已成熟、被现代浏览器广泛支持的CSS属性:

    offset-path CSS 属性指定一个供元素跟随的路径,并决定该元素在其父容器或 SVG 坐标系中的位置。这个路径可以是直线、曲线或几何图形,元素将沿着它定位或移动。在 offset-path 上定位或移动元素,通过 offset-distance CSS 属性实现。

    给元素设置 offset-path,使用 path 函数,函数内的字符串用以描述路径细节,形式与含义等同于SVG <path> 元素的 d 属性值:

    offset-path: path('M 20 100 L200 160 L380 20');

    描述元素在 path 路径上的定位或移动位置,使用 offset-distance 属性,值通常用百分比表示:

    offset-distance: 30%;

    ——这就是所谓的相抵路径动画的核心:约束元素的路径(offset-path)+ 元素在路径上的偏移距离(offset-distance)

    而 offset-path 路径来源于 SVG path 元素的 d 属性,路径描述的数据使用绝对单位(默认px),这样,当元素所在的父元素尺寸可以变大变小,CSS 初始设计的路径就不适用,需要动态改变,这得祭出JS,具体思路是:

    1. 使用 ResizeObserver API 监听父元素尺寸变化
    2. 父元素尺寸发生变化时给子元素动态创建 offset-path 路径
    ResizeObserver 接口允许监视 Element 的内容盒、边框盒或 SVGElement 的边界框尺寸的变化。这个接口提供了一种避免无限回调循环和循环依赖的方法,它通过在后续帧中处理更深层次的 DOM 元素来实现这一点。根据规范,resize 事件应该在绘制前和布局后调用。

    以下实例通过 ResizeObserver 实现对 textarea 元素的尺寸变化实施实时观察,且任何时候任何变化都同步将尺寸展示在 textarea 内。可以尝试拖曳 textarea 右下角改变其尺寸:

    核心代码:

    const myta = document.querySelector('#myta'); // 获取textarea
    
    // 创建尺寸变化观察器
    const Observer = new ResizeObserver(entries => {
        entries.forEach(entry => {
            const { width, height } = entry.contentRect; // 获取宽高
            myta.value = `${width} * ${height}`; // 显示变化结果
        });
    });
    
    // 对 myta 进行监视(实例化观察器)
    Observer.observe(myta);

    上例,ResizeObserver API 的使用并不复杂,就两个步骤:创建监视器用以观察元素尺寸变化并依据变化的尺寸处理逻辑业务、绑定指定元素进行观察。在本例基础上,把业务逻辑换成设置 offset-path 动态路径,就可以实现本文的命题。

    为简化起见,这里设计的路径用Q指令绘制。Q指令继承上一个坐标点,以其为起点绘制一根到达终点的曲线,曲线弧度和朝向由控制点坐标控制,语法结构如下:

    /* M 指令如果省略,Q 指令会以上一个操作的坐标点作为曲线的出发点 */
    [M startX startY ]Q ctrlX ctrlY, endX endY

    这里假设相抵路径从父元素的左上角(20,20)出发,曲线弧面朝下,控制点为(ctrlX,ctrlY),终点是父元素的右上角(endX,20)。其中的几个未知数:

    1. ctrlX :控制点x坐标 = 父元素宽度 ÷ 2
    2. ctrlY :控制点y坐标 = 父元素高度 × 1.8(系数可以微调)
    3. endX :终点x坐标 = 父元素宽度 - 20

    这样设计,相抵路径在水平方向上自始至终保持始于左上角止于右上角的布局安排,曲线弧面永远朝下且基本抵近(有时超越、有时略拉开距离)父元素的下边框(实际应用应根据场景微调系数或设计更为精准的算法)。来看完整的实例演示,该示例可以调整父元素的尺寸,调整过程中子元素的运动路径会实时跟着基本适配父元素的尺寸:

    完整代码:

    <style>
        /* 父元素 */
        #papa {
            width: 600px;
            min-width: 200px;
            height: 300px;
            min-height: 100px;
            border: 1px solid gray;
            overflow: hidden; /* 调整元素尺寸不能使用默认值 visible */
            resize: both; /* 宽高尺寸均可手动调整 */
            position: relative;
            margin: auto;
        }
        /* 子元素 */
        #son {
            position: absolute;
            width: 40px;
            height: 40px;
            background: tan;
            animation: move linear 6s infinite alternate;
        }
        /* 相抵路径动画 */
        @keyframes move {
            0% { offset-distance: 0%; }
            100% { offset-distance: 100%; }
        }
    </style>
    
    <div id="papa">
        <div id="son"></div>
    </div>
    
    <script>
        const papa = document.querySelector('#papa'); // 获取父元素
        const son = document.querySelector('#son'); // 获取子元素
    
        // 创建监视器(观察尺寸变化+设置动态 offset-path 路径)
        const PathObserver = new ResizeObserver(entries => {
            entries.forEach(entry => {
                const { width, height } = entry.contentRect;
                const startX = 20, startY = 20;
                const endX = width - startX, endY = startY;
                const ctrlX = width / 2, ctrlY = height * 1.8;
                son.style.setProperty('offset-path', `path('M ${startX} ${startY} Q ${ctrlX} ${ctrlY},${endX} ${endY}')`);
            });
        });
        
        PathObserver.observe(papa); // 指定 papa 为监视对象
    </script>

    显然上面的演示不够专业,尤其是Q曲线控制点的算法过于粗糙,在垂直方向只实现了大体上的路径适配。这在普通应用场景来说已经足够了。我们只需注意:路径的初始设计时考虑的是基于父元素固定宽高,然后不论父元素的尺寸如何变化,我们都按一定的算法去计算路径的各个参数所需的数据,使之尽可能地适配父元素尺寸。一般来说,路径越复杂,逻辑业务的处理就越琐碎、难弄,需要准备好算法、仔细处理。本文的示例仅作为参考,如果能从中得到启发,善莫大焉。

    评分

    参与人数 2威望 +80 金钱 +160 经验 +80 收起 理由
    红影 + 50 + 100 + 50 匠心独运,细节精致入微!
    梦江南 + 30 + 60 + 30 匠心独运,细节精致入微!

    查看全部评分

  • TA的每日心情
    开心
    2026-7-22 08:13
  • 签到天数: 787 天

    [LV.10]以坛为家III

    555

    主题

    3万

    回帖

    8万

    积分

    贵宾

    Rank: 7Rank: 7Rank: 7Rank: 7Rank: 7Rank: 7Rank: 7

    花潮美女鼠牛虎兔龙蛇马羊猴鸡狗猪缤纷心情心曲飞扬花好月圆飞龙在天音画大师天籁妙音共看流星风雨同行我心永远喜乐安康花潮贵宾

    发表于 2026-7-22 21:09 | 显示全部楼层
    黑黑老师的详细讲解,慢慢学习。晚上嚎!
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2025-12-1 20:32
  • 签到天数: 1052 天

    [LV.10]以坛为家III

    1898

    主题

    33万

    回帖

    40万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9

    花潮美女虎龙狗猪多彩人生星月交辉海样胸怀火热情怀优雅迷人神秘浪漫缤纷心情草莓情怀蝴蝶情怀心曲飞扬星星情怀七彩绚丽活泼开朗女儿情怀相遇之美一往情深花好月圆心香一瓣紫色情节飞龙在天金剪刀天籁妙音妙笔生花风雨同行我心永远天长地久幸福快乐绚丽缤纷喜乐安康中秋征文周年庆指尖上的流年舞会之星分析(喊冤)章总结章杀人王小强章最佳杀刺临屏写诗七夕诗钟活动第五届风云第六届风云情人节花潮管理

    发表于 2026-7-22 22:22 | 显示全部楼层
    子元素的运动轨迹和父元素的宽高直接关联,这样的图形也很特别
     
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    奋斗
    2026-7-22 18:40
  • 签到天数: 1877 天

    [LV.Master]伴坛终老

    3283

    主题

    13万

    回帖

    29万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9

    花潮帅哥鼠牛虎兔龙蛇马羊猴鸡狗猪多彩人生星月交辉奔放热烈海样胸怀春风拂面火热情怀优雅迷人神秘浪漫相遇之美鹰傲苍穹花好月圆紫色情节飞龙在天王者至尊大将风范音画大师天籁妙音共看流星风雨同行我心永远幸福快乐喜乐安康侠骨柔肠心想事成开朗大方花潮管理

     楼主| 发表于 2026-7-22 22:24 | 显示全部楼层
    红影 发表于 2026-7-22 22:22
    子元素的运动轨迹和父元素的宽高直接关联,这样的图形也很特别

    就一个矩形,没啥特别
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    奋斗
    2026-7-22 18:40
  • 签到天数: 1877 天

    [LV.Master]伴坛终老

    3283

    主题

    13万

    回帖

    29万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9

    花潮帅哥鼠牛虎兔龙蛇马羊猴鸡狗猪多彩人生星月交辉奔放热烈海样胸怀春风拂面火热情怀优雅迷人神秘浪漫相遇之美鹰傲苍穹花好月圆紫色情节飞龙在天王者至尊大将风范音画大师天籁妙音共看流星风雨同行我心永远幸福快乐喜乐安康侠骨柔肠心想事成开朗大方花潮管理

     楼主| 发表于 2026-7-22 22:24 | 显示全部楼层
    梦江南 发表于 2026-7-22 21:09
    黑黑老师的详细讲解,慢慢学习。晚上嚎!

    希望能看懂
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    小黑屋|手机版|Archiver|服务支持:DZ动力|huachaowang.com Inc. ( 蜀ICP备17032287号-1 )

    GMT+8, 2026-7-23 02:08 , Processed in 0.081252 second(s), 25 queries .

    Powered by Discuz! X3.4

    © 2001-2013 Comsenz Inc.

    快速回复 返回顶部 返回列表