css - 从剪辑迁移到剪辑路径以使用百分比值

标签 css sass css-animations clip-path

我目前正在使用 scss “移动”边界的书面动画。动画主要基于clip .

$box-size-w: 80px;
$box-size-h: 50px;

    @keyframes clipMe {
        0%, 100% {
            clip: rect(0, $box-size-w, $path-width, 0);
        }
        25% {
            clip: rect(0, $path-width, $box-size-h, 0);
        }
        50% {
            clip: rect(resolveCalc($box-size-h, $path-width), $box-size-w, $box-size-h, 0);
        }
        75% {
            clip: rect(0, $box-size-w, $box-size-h, resolveCalc($box-size-w, $path-width));
        }
    }
起初动画只适用于方形块(w === h),然后我对其进行了调整,以便可以单独指定 withheight .
然后需要再次调整脚本,以便它接受 percent值(value)观,不仅pixels .我做了一些研究,发现这篇文章 Clipping and Masking in CSS .从文章看来:
  • 旧语法:clip: rect(10px, 20px, 30px, 40px);
  • 新语法:clip-path: inset(10px 20px 30px 40px);

  • 我进行了更改,似乎以下应该有效:
    $box-size-w: 100%;
    $box-size-h: 100%;
    
        @keyframes clipMe {
            0%, 100% {
                clip-path: inset(0 $box-size-w $path-width 0);
            }
            25% {
                clip-path: inset(0 $path-width $box-size-h 0);
            }
            50% {
                clip-path: inset(resolveCalc($box-size-h, $path-width) $box-size-w $box-size-h 0);
            }
            75% {
                clip-path: inset(0 $box-size-w $box-size-h resolveCalc($box-size-w, $path-width));
            }
        }
    
    但是,此更改后动画不起作用。我试图玩这个,但没有很好的结果,似乎新的 api 也改变了它的工作方式。如何keyframes可以修改,以便它们与 % 一起使用值(value)观?
    scss代码:
        $anime-time: 8s;
    
        $box-size-w: 80px;
        $box-size-h: 50px;
        $path-width: 1px;
    
        $main-color: #000;
    
        @function resolveCalc($s, $f) {
            @return calc(#{$s} - #{$f});
        }
    
        %full-fill {
            position: absolute;
            top: 0;
            bottom: 0;
            left: 0;
            right: 0;
        }
    
        .box {
            width: $box-size-w;
            height: $box-size-h;
            margin: auto;
            color: $main-color;
            box-shadow: inset 0 0 0 1px rgba($main-color, .1);
            position:relative;
    
            &::before,
            &::after {
                @extend %full-fill;
                content: '';
                z-index: -1;
                margin:0;
                box-shadow: inset 0 0 0 $path-width;
            }
    
            &.active {
                &::before {
                    animation: clipMe $anime-time linear infinite;
                    animation-delay: $anime-time * -.5;
                }
                &::after {
                    animation: clipMe $anime-time linear infinite;
                }
    
                // for debug
                &:hover {
                    &::after,
                    &::before {
                        background-color: rgba(#fff, .3);
                    }
                }
            }
    
        }
    
        @keyframes clipMe {
            0%, 100% {
                clip: rect(0, $box-size-w, $path-width, 0);
            }
            25% {
                clip: rect(0, $path-width, $box-size-h, 0);
            }
            50% {
                clip: rect(resolveCalc($box-size-h, $path-width), $box-size-w, $box-size-h, 0);
            }
            75% {
                clip: rect(0, $box-size-w, $box-size-h, resolveCalc($box-size-w, $path-width));
            }
        }
    
        html,
        body {
            height: 100%;
        }
    
        body {
            position: relative;
        }
    
        .wrap {
            width:50%;
            height:25%;
            margin:50px auto;
        }
    
        *,
        *::before,
        *::after {
            box-sizing: border-box;
        }
    
    工作(编译为 css)演示:

    .box::before, .box::after {
      position: absolute;
      top: 0;
      bottom: 0;
      left: 0;
      right: 0;
    }
    
    .box {
      width: 80px;
      height: 50px;
      margin: auto;
      color: #000;
      box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.1);
      position: relative;
    }
    
    .box::before, .box::after {
      content: '';
      z-index: -1;
      margin: 0;
      box-shadow: inset 0 0 0 1px;
    }
    
    .box.active::before {
      animation: clipMe 8s linear infinite;
      animation-delay: -4s;
    }
    
    .box.active::after {
      animation: clipMe 8s linear infinite;
    }
    
    .box.active:hover::after, .box.active:hover::before {
      background-color: rgba(255, 255, 255, 0.3);
    }
    
    @keyframes clipMe {
      0%, 100% {
        clip: rect(0, 80px, 1px, 0);
      }
      25% {
        clip: rect(0, 1px, 50px, 0);
      }
      50% {
        clip: rect(calc(50px - 1px), 80px, 50px, 0);
      }
      75% {
        clip: rect(0, 80px, 50px, calc(80px - 1px));
      }
    }
    
    html,
    body {
      height: 100%;
    }
    
    body {
      position: relative;
    }
    
    .wrap {
      width: 50%;
      height: 25%;
      margin: 10px auto;
    }
    
    *,
    *::before,
    *::after {
      box-sizing: border-box;
    }
    <div class="wrap">
        <div class="box active"></div>
    </div>

    最佳答案

    我会为此使用掩码

    .box {
      width: 40%;
      height: 100px;
      margin: 10px auto;
      color: #000;
      box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.1);
      position: relative;
    }
    
    .box::before, .box::after {
      content: '';
      position: absolute;
      top: 0;
      bottom: 0;
      left: 0;
      right: 0;
      z-index: -1;
      box-shadow: inset 0 0 0 1px;
      -webkit-mask:linear-gradient(#fff 0 0) no-repeat;
      animation: 
        clipMe 2s linear infinite alternate,
        pos    8s linear infinite;
    }
    
    .box::before {
      animation-delay: -4s;
    }
    
    
    @keyframes clipMe {
      0% {
        -webkit-mask-size:100% 2px;
      }
      100% {
        -webkit-mask-size:2px 100%;
      }
    }
    
    @keyframes pos {
      0%,24.9% {
        -webkit-mask-position:top left;
      }
      25%,49.9% {
        -webkit-mask-position:bottom left;
      }
      50%,74.9% {
        -webkit-mask-position:bottom right;
      }
      75%,100% {
        -webkit-mask-position:top right;
      }
    }
    <div class="box"></div>
    
    <div class="box" style="width:50%;height:150px;"></div>

    并与 clip-path你可以像下面这样做:

    .box {
      width: 40%;
      height: 100px;
      margin: 10px auto;
      color: #000;
      box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.1);
      position: relative;
    }
    
    .box::before,
    .box::after {
      content: '';
      position: absolute;
      top: 0;
      bottom: 0;
      left: 0;
      right: 0;
      z-index: -1;
      box-shadow: inset 0 0 0 1px;
      animation: clipMe 4s linear infinite;
    }
    
    .box::before {
      animation-delay: -2s;
    }
    
    @keyframes clipMe {
      0%, 100% {
        clip-path: inset(0 0 calc(100% - 1px) 0);
      }
      25% {
        clip-path: inset(0 calc(100% - 1px) 0 0);
      }
      50% {
        clip-path: inset(calc(100% - 1px) 0 0 0);
      }
      75% {
        clip-path: inset(0 0 0 calc(100% - 1px));
      }
    }
    <div class="box"></div>
    
    <div class="box" style="width:50%;height:150px;"></div>

    关于css - 从剪辑迁移到剪辑路径以使用百分比值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65732461/

    相关文章:

    javascript - 如何暂停一个css动画,然后从暂停点继续运行?

    html - CSS - 防止元素被推

    html - 将 <div> 与不带宽度的显示内联或内联 block 对齐

    css - 如何在 Primeng 组件上放置 img 或 svg 而不是图标?

    css - `JS: Error: Css styling failed: missing ' { nativescript-dev-sass 插件中的 '`

    html - CSS3 - 动画文本左/中/右对齐

    css - 将 CSS 应用于 <body> 和通用选择器 (*) 有什么区别

    html - CSS:卡片翻转效果?

    sass - 差异 : Webpack css-loader and raw-loader

    javascript - 为什么单击时的关键帧动画只触发一次?