10

我需要 8 种不同的 CSS3 动画,它们太相似了,所以我使用了 LESS。下面是完美运行的代码,有一个小故障 - @name 变量。

.animation_top (@name, @pxFrom, @pxTo) {
    @-moz-keyframes @name {
        0% {
            top: @pxFrom;
            opacity: 0;
        }
        100% {
            top: @pxTo;
            opacity: 1;
        }
    }

    @-webkit-keyframes @name {
        0% {
            top: @pxFrom;
            opacity: 0;
        }
        100% {
            top: @pxTo;
            opacity: 1;
        }
    }

    @-ms-keyframes @name {
        0% {
            top: @pxFrom;
            opacity: 0;
        }
        100% {
            top: @pxTo;
            opacity: 1;
        }
    }
}

因为 css 关键帧是由 @ 符号开始的,所以 LESS 简单地忽略了 @name 的变量。有什么办法可以逃避关键帧@符号或强制LESS以某种方式正确渲染@name?

4

3 回答 3

13

EDIT
(~"@{varname}")选择器的支持将在 LESS 1.4.0 中删除。
要使原始解决方案起作用,只需引入一个临时变量并使用选择器插值(LESS 1.3.1 中的新功能)。
对于前面的示例,这将是:

 @tmp: ~"@{varname}"
 @{tmp} { ... }

下面的解释仍然使用旧的选择器,因为它更简洁。如前所示,用新方法替换旧方法是微不足道的。
不过,我确实更新了代码示例,因为我们很多人都盲目地复制粘贴代码。

预期的语法是 (vendorprefixed) (~"@keyframes @{name}") { ... }。但是,输出不正确(选择器合并到),因为在less源代码@keyframes name 0% { ... } @keyframes name 100% {}中将树语法@keyframes定义为异常。

我巧妙的 mixin 背后的想法是通过选择器添加花括号。

  • 初始选择器将是(~"@keyframes @{name}{") { ... }.
    这呈现为:@keyframes name {{ ... }
  • 由于{{看起来不太好,我添加了一个换行符。我无法直接转义换行符,所以我决定创建一个 variable @newline: `"\n"`;。Less将反引号之间的任何内容解析为 JavaScript,因此结果值是换行符。由于{ ... }需要“选择器”有效,我们选择动画的第一步,0%.
  • 花括号不匹配。为了解决这个问题,我们可以在最后添加一个虚拟选择器,它以(~"} dummy") { .. }. 这很难看,因为添加了一个无用的选择器。
    但是等等,我们已经知道供应商特定的前缀将按顺序添加。所以,让最后的第一个选择器是(~"@{pre}@@{vendor}keyframes @{name} {@{newline}0%")
    @{pre}必须针对第一个关键帧块之后"}@{newline}"的每个关键帧块。
  • 现在我们已经处理了除了最后一个块之外的每个块的右花括号。我们不必使用无用的虚拟选择器,因为我们显然定义了关键帧以便使用它们。animation-name是这样做的财产。我正在使用受保护的 mixin来实现这一点。

该解决方案一开始可能看起来有些尴尬,但它非常简洁。

@newline: `"\n"`; // Newline
.animation_top(@selector, @name, @pxFrom, @pxTo) {
    .Keyframe(@pre, @post, @vendor) {
        @keyframe: ~"@{pre}@@{vendor}keyframes @{name} {@{newline}0%";
        @{keyframe} {
            top: @pxFrom;  
            opacity: 0;  
        }    
        100%  { 
            top: @pxTo;
            opacity: 1;
        }    
        .Local(){}
        .Local() when (@post=1) {
            @local: ~"}@{newline}@{selector}";
            @{local} {
                -moz-animation: @name;
                -webkit-animation: @name;
                -o-animation: @name;
                -ms-animation: @name;
                animation: @name;
            } 
        }    
        .Local;
    } 
    .Keyframe(""            , 0,    "-moz-");
    .Keyframe(~"}@{newline}", 0, "-webkit-");
    .Keyframe(~"}@{newline}", 0,      "-o-");
    .Keyframe(~"}@{newline}", 0,     "-ms-");
    .Keyframe(~"}@{newline}", 1,         ""); // <-- Vendorless w3
} 
.animation_top("#test", hey, 10px, 100px);

呈现为(请注意,关键帧内的缩进减少了一个。这是预期的,因为由于手动添加了大括号,Less 不知道我们在另一个块内)。

使用 LESS 版本 1.3.3 和 1.4.0-b1 确认以下结果。

$ lessc --version
lessc 1.3.3 (LESS Compiler) [JavaScript]
$ lessc so
@-moz-keyframes hey {
0% {
  top: 10px;
  opacity: 0;
}
100% {
  top: 100px;
  opacity: 1;
}
}
@-webkit-keyframes hey {
0% {
  top: 10px;
  opacity: 0;
}
100% {
  top: 100px;
  opacity: 1;
}
}
@-o-keyframes hey {
0% {
  top: 10px;
  opacity: 0;
}
100% {
  top: 100px;
  opacity: 1;
}
}
@-ms-keyframes hey {
0% {
  top: 10px;
  opacity: 0;
}
100% {
  top: 100px;
  opacity: 1;
}
}
@keyframes hey {
0% {
  top: 10px;
  opacity: 0;
}
100% {
  top: 100px;
  opacity: 1;
}
}
#test {
  -moz-animation: hey;
  -webkit-animation: hey;
  -o-animation: hey;
  -ms-animation: hey;
  animation: hey;
}

最后注意事项:

  • 生成有效 CSS 的最短虚拟对象是/**/. 示例:(~"..") {/**/}-> .. {/**/}
于 2012-06-14T07:32:42.167 回答
7

Less 版本 1.7 现在支持一种更好的方法:

米心

.keyframes(@name) { 
    @-webkit-keyframes @name {
        .-frames(-webkit-);
    }
    @-moz-keyframes @name {
        .-frames(-moz-);
    }
    @keyframes @name {
        .-frames();
    }
}

输入

& {
    .keyframes(testanimation);.-frames(@-...){
        0% {
            left: 0;
            @{-}transform: translate(10px, 20px);
        }

        100% {
            left: 100%;
            @{-}transform: translate(100px, 200px);
        }
    }
}
于 2014-02-28T03:11:38.917 回答
0

也许这就是你想要的?如果你定义@name: "ANIM_NAME";那么我想这是这样的:

@-moz-keyframes @{name} {
...
...
}
于 2012-02-06T20:38:39.217 回答