用 LESS 写帧动画 LESS LOOP KEYFRAMES ANIMATION SINGLE & DOUBLE LOOP 单层 & 双层 循环

1,861 阅读2分钟

前言

LESS 的循环处理网上资料不多,抄起来比较麻烦 总结了 2 套常用的

多图帧动画

即多张图片形成的帧动画

引用

此处参考了 shawndxl文章

keyframes 代码:

@keyframes fireworks {
    .circle(118);
    .circle(@n, @i:0) when (@i < @n) {
        @j: @i + 1; // 图片从1.png开始,比如 @n 为 45,则最后一张加载的为 45.png

        @a: @n - 1; // 通过 图片数 - 1 算出 0% ~ 100% 中选择器的数目
        @b: 1 / @a * 100; // 小数 * 100 换算成百分数的分子;
        @c: @b * @i; // 具体到各个 % 选择器的分子;
        @x: round(@c, 2); // 使用 less round 函数小数点两位后取整数
        @selector:e('@{x}%'); // 使用 less e 函数变为选择器,注意!!直接套用或者使用 percentage 函数无法识别

        @{selector}{
            background: url('../../../assets/images/qiaqia/overseas/fireworks_@{j}.png') center center / contain no-repeat;
        }
        .circle(@n, (@i + 1));
    }
}

缺点

第一次循环动画 因为一堆图片在短时间内加载,会非常卡顿,此处采用利用 伪元素的 content解决。如下:

.fireworks {
    &:before{
        content: 
            url(1.png)
            url(2.png)
            ...
    }
}

我们这里的动画有上百帧,采用 less 的 merge 解决,less 代码如下:

.loop-content(@n: 118, @i:1, @total: '') when (@i <= @n) {
    content+_: url('../../../assets/images/qiaqia/overseas/title-anim/@{i}.png')  ;
        .loop-content(@n, @i + 1);
    }

    &:before{
        .loop-content();
    }
}

单图帧动画

  • 即图片经过严格处理 类似 CSS Sprites 这样的图片,一张张对齐,贴成 从左到右 从上到下 的一整张图。
    • 缺点是对 贴图 这个步骤的要求非常严格,必须完全对齐,否则动画会有抖动,完全不能用,尤其是有些动画是由 上百帧 组成的,这个工作无论如何交给设计。
    • 优点是不会有 多图动画 的 第一遍循环 卡顿明显的 现象。
      • 当然第一遍加载卡顿的问题,可以利用 content: url(001.png) url(002.png) ...; 这样的方式解决
      • 但你还是要用到 LESS 的字符串循环,这个... 我觉得更麻烦

keyframes 代码

pps :

也是根据 shawndxl文章 改写的

@keyframes firework {
    .circleBig(10, 11);

    .circleBig(@m: 10, @n: 11, @i:0, @j:0) when (@i < @m) and (@j < @n) { // j、n 为个位数,i、m 为十位数
        @tmp1: @m * @n; // 宽高乘积
        @tmp2: @i * @m + @j; // 当前进度
        @x: round(@tmp2 / @tmp1 * 100, 2); // 进度
        @selector: e('@{x}%');
        @tmp3: @j * -100;
        @tmp4: @i * -100;
        @left: e('@{tmp3}%');
        @right: e('@{tmp4}%');
        @jPlus: @j + 1;
        @iPlus: @i + 1;

        @{selector} {
            background-position: @left @right;
        }

        & when (@jPlus >= @n) {
            .circleBig(@m, @n, @iPlus, 0);
        }

        & when (@jPlus < @n) {
            .circleBig(@m, @n, @i, @jPlus);
        }
    }
}

注意事项 & div 定义方法

多图帧动画,下例 div 定义即可。
但是单图,必须定义 div 的宽高,为了适配,我能立刻想到的解决方案是利用 Javascript 算出 div 为了适配 需要 zoom 的值,给加个 zoom ...

&:before{
    /*width: 640px;*/
    /*height: 1106px;*/
    content: '';
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    background: url('../../../assets/images/qiaqia/overseas/firework-anim.png');
    animation: fireworks 5s steps(1) 0s infinite both;
}