注册
web

抖音自动进入直播间的动画挺有意思的,看看有多少种方式可以实现

在刷抖音的时候,发现有一个直播的专属导航页签,切换到这个页签之后,刷出来的内容全都是直播,不过都是在“门外”观看,没有进入直播间;


短暂的停留之后,会出现一个自动进入直播间的提示,并且有一个描边动画,动画结束之后,就会进入直播间,今天我就尝试通过多种方式来实现这个动画效果。



1. 渐变实现


渐变.gif


效果如上图所示,渐变需要使用到的是conic-gradient锥形渐变,文档地址:conic-gradient


代码如下:


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
html,
body {
height: 100%;
margin: 0;
}

body {
display: flex;
justify-content: center;
align-items: center;
background: linear-gradient(90deg, #1F1C2C 0%, #928DAB 100%);
color: #fff;
}

.wrap {
position: relative;
background-color: rgba(255, 255, 255, 0.2);
width: fit-content;
padding: 10px 20px;
border-radius: calc(1em + 10px);
}

/*使用自定义属性来控制进度*/
@property --offset {
syntax: "<length-percentage>";
inherits: false;
initial-value: 0;
}

.wrap.gradient-animation {
overflow: hidden;
/*和普通 css 变量一样使用即可*/
background-image:
conic-gradient(
#fff 0%,
#fff var(--offset),
transparent var(--offset) 100%
);
}

/*需要使用一个遮挡来挡住多余的部分,只保留描边部分*/
.wrap.gradient-animation::before {
content: ' ';
position: absolute;
top: 2px;
left: 2px;
right: 2px;
bottom: 2px;
background: #1F1C2C;
border-radius: inherit;
z-index: 0;
}

.wrap.gradient-animation:hover {
animation: gradient 5s linear 1 forwards;
}

@keyframes gradient {
0% {
--offset: 0;
}
100% {
--offset: 100%;
}
}

</style>
</head>
<body>
<div class="wrap gradient-animation">
<!-- 需要控制层级显示 -->
<span style="position: relative; z-index: 1;">自动进入直播间</span>
</div>
</body>
</html>

conic-gradient的技术细节就不展开了,感兴趣的可以自行查阅文档,这里主要的技术点在于--offset这个自定义属性,因为渐变本身是不支持动画的,所以需要借助这个自定义属性来实现动画效果,文档地址:@property


这里的效果其并不是很理想,因为conic-gradient的渐变是一个圆形的渐变,而实际效果是边框的一个描边,所以需要使用一个遮罩来挡住多余的部分,只保留描边部分。


由于使用了伪元素来实现遮罩,所以还需要控制层级显示,避免遮罩挡住了文字,并且原效果是透明的背景,这里使用遮罩层之后背景就不能是透明的了,而且动画在每一个部分执行的时间都不连贯。


可以说这种方式有很多的局限性,所以我们来看看下一种方式。


2. 渐变加 mask 实现


mask.gif


渐变加mask的实现思路和上面的类似,主要是解决了上面的背景半透明的问题,文档地址:mask


代码如下:


<div class="wrap gradient-mask">
<span style="position: relative; z-index: 1;">自动进入直播间</span>
</div>

.wrap.gradient-mask::before {
content: ' ';
position: absolute;
inset: 0;
background-color: rgba(255, 255, 255, 0.1);
background-image: conic-gradient(
#fff 0%,
#fff var(--offset),
transparent var(--offset) 100%
);
border-radius: inherit;

mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg'><rect width='150' x='1' y='1' height='40' rx='20' fill='transparent' stroke='red' stroke-width='2' stroke-alignment='outside'/></svg>");
mask-size: 100% 100%;
mask-repeat: no-repeat;
}

.wrap.gradient-mask:hover::before {
animation: gradient 5s linear 1 forwards;
}

这里把效果整体迁移到了::before伪元素上,使用mask-image里面加了一个svg来处理描边的问题,这样就不需要使用遮罩来挡住多余的部分,只保留描边部分。


但是这里的问题也很明显,那就是svg并不能很好的响应式,而且因为svg的其他原因,导致描边的边宽有点被裁剪,这里也只是提供一个思路,并不是最佳实践。


3. 使用 svg 实现


svg.gif


上面都已经使用到了svg作为遮罩,那么直接使用svg更简单直接,这种情况个人也比较推荐,代码如下:


<div class="wrap svg">
<svg xmlns="http://www.w3.org/2000/svg">
<rect width="150" x="1" y="1" height="40" rx="20" stroke="rgba(255, 255, 255, 0.1)" stroke-width="2" />
<rect width="150" x="1" y="1" height="40" rx="20" class="rect" />
</svg>
<span style="position: relative; z-index: 1;">自动进入直播间</span>
</div>

.wrap.svg svg {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
}

.wrap.svg svg > rect {
width: calc(100% - 2px);
height: calc(100% - 2px);
fill: transparent;
stroke-width: 2;
}

.wrap.svg svg > .rect {
stroke-dasharray: 350;
stroke-dashoffset: 350;
stroke: white;
stroke-width: 2;
}

.wrap.svg:hover svg > .rect {
transition: stroke-dashoffset 5s linear;
stroke-dashoffset: 0;
}

svg的描边效果主要是通过stroke-dasharraystroke-dashoffset来实现的,svg描边效果也是一个非常有趣的实现。


stroke-dasharray是用来控制虚线的,这个值越大,虚线之间的间隔也越大,大到一定程度这个虚线就正好将整个形状包裹住。


stroke-dashoffset是用来控制虚线的偏移量,当这个值等于stroke-dasharray的时候,虚线就会完全消失,等于0的时候,虚线就会完全显示。


根据svg的特性,描边是在形状的外部,所以最外层有一个半透明的边框路径显示的并不完全,需要通过一些技巧来处理。


image.png


所以上面的代码会有两个rect,一个是用来描边的,一个是用来做半透明的边框的,这样就可以实现一个比较完美的描边动画效果。


但是上面的描边起点和终点都是在左上角,如果需要在中间的话,可以通过path来实现,感兴趣的可以自行尝试,这里提供path的代码:


<svg viewBox="0 0 600 150" xmlns="http://www.w3.org/2000/svg">
<path d="M 100 0 L 500 0 A 50 50 0 1 1 500 150 L 100 150 A 50 50 0 1 1 100 0 Z" fill="transparent" stroke="rgba(255, 255, 255, 0.1)" stroke-width="2" />
</svg>

path需要微调,因为没有贴边,可以使用一些在线网站来进行调整,比如:svg-path-editor,可自行探索。


总结


这一篇文章通过多种方式来实现一个描边动画效果,主要技术有:



  1. conic-gradient锥形渐变,本身渐变是不支持动画的,但是我们可以通过自定义属性来实现动画效果;
  2. mask遮罩,mask本身其实和背景图的使用方式差不多,但是mask主要用来遮挡多余的部分,在这里我们使用mask来遮挡主要部分,只保留描边部分来实现动画效果;
  3. svg描边,svg描边是一个非常有趣的技术,通过stroke-dasharraystroke-dashoffset来实现描边动画效果,这种方式是最推荐的。

当然肯定还有其他的方式来实现这个效果,这里只是提供了一些思路,希望对大家有所帮助。


作者:田八
来源:juejin.cn/post/7420814883576414259

0 个评论

要回复文章请先登录注册