likes
comments
collection
share

Less绘制绕盒子的运动光束

作者站长头像
站长
· 阅读数 44

Less绘制绕盒子的运动光束

今天在博客网站上逛的时候,发现了一个比较好看的霓虹灯效果,这里面比较有趣的是内部的运动光束。文章链接:如何用纯 CSS 实现酷炫的霓虹灯效果?

运动光束就是围绕着这一个元素盒子边框不断运动的一条光线,我看了一下该作者是使用了4个div去实现的,但是如果在页面中添加元素过多,很容易造成卡顿,所以能否使用伪类去实现同样的效果呢。

Less绘制绕盒子的运动光束

下面是我写的代码:

实现思路

首先先在Html中将盒子元素编写好,建立一个box1盒子

<div class="border-style">
    <div class="box1 border-css border-css1">
        运动光束
    </div>
</div>

然后将光束绘制好,这里我使用了less,这种预编译的方式能够很好的定义出css的一些样式方法。

光束是元素的::before伪类元素,这里光束的颜色是逐渐透明的,所以使用了linear-gradient进行渐变色的处理。

&::before {
    content: '';
    width: 5px;
    height: 100%;
    display: inline-block;
    position: absolute;
    left: 0%;
    background: linear-gradient(to top,transparent, rgb(51, 255, 0));
}

Less绘制绕盒子的运动光束

这样就是一条运动光束,但目前是静止的,需要给光束增加animation动画, 比如左侧的动画是从下往上的,就需要使用top、left确定好光束的位置。

&::before {
    ...
    animation-name: animate1;
    animation-duration: 0.25s;
    animation-timing-function: linear;
    animation-iteration-count: infinite;
}
@keyframes animate1 {
    0% {
        top: 100%;
        left: 0%;
    }
    100% {
        top: -100%;
        left: 0%;
    }
}

Less绘制绕盒子的运动光束

之后因为元素只有一个::before,所以当前的动画完成后,需要将其通过transform: rotate()进行90deg的转向,变成平行状态,这里还需要使用transform-origin将旋转中心进行改变。

由于旋转后,盒子的宽高并不一定相等,所以光束的height也需要据此而改变,这里使用less的好处就出现了,可以直接对元素用类似方法的形式传入值,之后在最外部调用.border-css();就可以将这些全部改变。

.border-css(@width, @height, @animatename, @color: #f00, @time: 1s) {
    overflow: hidden;
    &::before {
        ...
    }
    ...
    @keyframes animate2 {
        0% {
            height: @width;
            transform: rotate(90deg);
            transform-origin: 0% 0%;
            left: 0%;
        }
        100% {
            height: @width;
            transform: rotate(90deg);
            transform-origin: 0% 0%;
            left: 200%;
        }
    }
}

遇坑

到上面的步骤后,光束的四个方向运动animation肯定能够写出来了,然后可以通过lesseach循环的方式创建4个class: border-css1, border-css2, border-css3, border-css4

但是运动之间应该怎么切换呢?

刚刚开始我是想能否在less中将这些运动动画按顺序进行切换循环,但是发现实在是做不到,必须要通过javascript方法来,不然最后循环一次,就会停止下来。

然后再到javascript方法中,我编写了animationReplay方法,根据获取dom树中的border-css元素, 在元素监听中有一个animationiterationapi方法,这是当CSS Animation运动到最后一帧时触发。

MDN地址:GlobalEventHandlers.onanimationiteration - Web API 接口参考 | MDN (mozilla.org)

通过正则匹配判断当前是哪一个class,来进行class之间的切换,进而实现光束运动的改变。

之前我有想过之间改变伪类的animation,js是没有伪类选择器的,发现需要通过insertRule()将修改插入,然后之前的rule也需要delete,这样比切换class更加麻烦,所以就放弃了。