最近用到一个边框动画效果,动画过程是边框从四个端点出发,慢慢变长,最终填满所有边框,动画效果如下图:
这个是用SVG实现的,主要用到的属性是 stroke-dasharray;
stroke-dasharray
MDN官方文档点击可查看,这个属性主要是设置边框(stroke)的实线和间隔的数值,“实线长度[, 间隔长度, 实线长度, 间隔长度, ……]”这种格式;
参数中包含两类值:实线长度、间隔长度;如果设置奇数个值,会自动循环一次补全到偶数个值,作为一个周期进行循环;比如设置 “2, 3, 4″,系统会自动补全为 “2, 3, 4, 2, 3, 4″,然后按照这个值进行循环;
一个400像素的线段,stroke-dasharray设置为 “20, 30, 40, 50″,则表示边框样式为“实线20像素、间隔30像素、实线40像素、间隔50像素、实线20像素、间隔30像素……”一直到结束,如下图,灰色是背景,红色是 stroke-dasharray 的效果,上边的灰色线条是用来做对比的;
思路
了解了stroke-dasharray后,思路就比较简单了:
- 在需要加边框效果的目标元素内添加svg标签,svg绝对定位宽高都设为100%,pointer-events设置为none,不要影响目标元素内的交互;
- 在svg中添加一个path标签,按照边框绘制一个矩形,设置好边框宽度 stroke-width 和边框颜色 stroke,并给 path 添加 transition;
- 设置 stroke-dasharray 的值为 “0, 宽度, 0, 高度, 0, 宽度, 0, 高度”,实线的值都是0,间隔的值是 宽、高、宽、高,四条边上正好都是空白的间隔,所以实际效果图中不会出现边框;
- 给目标元素添加 hover 效果,hover时,path 的 stroke-dasharray 设置为“宽度, 0, 高度, 0, 宽度, 0, 高度, 0”,和上一步中的值正好相反,实线的值从0变成了 宽、高、宽、高,间隔的值变为0,即没有间隔;
有一点需要特别注意,svg 中的 stroke 是居中往两侧扩的,比如 (0, 10) 到 (100, 10) 绘制一条线,设置边框宽度为10,则线会以 y=10 这条线为中心,向上下两侧各扩5像素,即实际看到的边框是以 (0, 5) 开始的;
所以上面的步骤中,宽、高的描述是不准确的,应该分别对应“宽 – 边框宽度/2”、“高 – 边框宽度/2”;0这个值也不准确,应该对应“边框宽度/2”;
这样处理下来,需要计算的地方也不少呢,就这个效果而言,可以采用更简单的边框宽度乘2的方案,边框乘2后,svg可视区内外各有一半边框,可视区外的边框看不到,也就变相实现了该效果;
生成器
计算和设置值比较麻烦,我就做了一个简单的生成器,输入目标元素的长度、宽度和边框宽度,就可以生成对应的 html 结构和 css;