不用 js实现渐变、虚线、跑马灯、可伸缩边框
最近遇到个需求,要求实现一个渐变色的边框,并且是虚线的,同时还要有动画。
有的朋友可能看到这里就要开骂了,估计要提刀找设计和产品怼回去了。
但其实我是可以理解的,因为这种花哨的边框想要用在一个类似于魔法框的地方,框住一个地方,然后交给 ai 处理。这样的交互设计可以很好的体现科技感,并且我也想尝试一下,就接了这个需求。
单看几个条件都好处理,css 已经支持了 border-image。
再不济用伪元素遮盖一下,clip-path镂空也可以
甚至我看到很多网站是直接放个视频就完了
但是我这次的需求最重要的是虚线,这就不好处理了。因为设置了边框为虚线后会忽略掉 border-image。
其实这个问题看起来很难,做起来也确实难。我搜到了张鑫旭大佬多年前的文章,就是专门讲这件事的
http://www.zhangxinxu.com/wordpress/2…
看完之后我受益匪浅,虽然我不能用他的方案(因为他的方案中,虚线是假的,样式会和浏览器有差异)
我尝试了很多方案,mask、clip-path、背景图等等,效果都不好。
绝望之际我想到了一个救星svg
div 做不到的事情,我 svg 来做。svg 可以设置 stroke,可以设置 fill,可以设置渐变色,渐变色还可以做动画。简直就是完美的符合需求
先写个空标签上去
<style>
.rect{
width: 100px;
height: 100px;
}
</style>
<div class='rect'>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
</svg>
</div>
因为我需要 svg 尺寸跟随父容器变化,所以就不写 viewBox 了,直接设置宽高 100%。同时在里面画一个矩形,也是宽高 100%。
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width='100%' height='100%'>
<rect width="100%" height="100%"></rect>
</svg>
现在长这样
接下来给 rect 设置填充和描边,边框宽度为 4px
<rect
fill="transparent"
stroke="red"
stroke-width="4"
width="100%"
height="100%"
></rect>
接下来我们给border 设置为渐变色,需要在 svg 中定义一个渐变,svg 定义渐变色还是很方便的,都是现成标签和属性直接就可以通过 id 取到。
<svg>
...
<defs>
<linearGradient id="gradient" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stop-color="lightcoral" />
<stop offset="50%" stop-color="lightblue" />
<stop offset="100%" stop-color="lightgreen" />
</linearGradient>
</defs>
</svg>
接下来给红色的 stroke 换成渐变色
<rect
fill="transparent"
stroke="url(#gradient)"
stroke-width="4"
width="100%"
height="100%"
></rect>
接下通过 stroke-dasharray
来设置虚线边框
mdn 上关于 dasharry的介绍在这里 developer.mozilla.org/zh-CN/docs/…
我给 rect 设置 dasharray 为 5,5
<rect
fill="transparent"
stroke="url(#gradient)"
stroke-dasharray="5,5"
stroke-width="4"
width="100%"
height="100%"
></rect>
这样渐变虚线边框就成了
接下来处理动画效果
动画分两种
- 线动,背景色不动
- 线不动,背景色动
这两种效果我都实现了
首先展示线动,背景色不动的情况
这种情况只要能想办法让虚线产生偏移就可以,于是我搜了一下,这不巧了吗,正好有个属性叫 stroke-dashoffset
于是就可以通过 css 动画来修改偏移量
<style>
.dashmove {
animation: dashmove 1s linear infinite;
}
@keyframes dashmove {
0% {
stroke-dashoffset: 0;
}
100% {
stroke-dashoffset: 10;
}
}
</style>
<rect class="dashmove" .... ></rect>
大功告成
接下来处理第二种情况,线不动,背景动
这种情况就更简单了,因为 svg 本身就支持动画
我们只需要在渐变色中增加一个animateTransform标签
<linearGradient id="gradient" x1="0%" y1="0%" x2="100%" y2="0%">
...
<animateTransform
attributeName="gradientTransform"
type="rotat
from="0 0.5 0.5"
to="360 0.5 0.5"
dur="1s"
repeatCount="indefinite"
/>
</linearGradient>
接下来看一下拖拽的效果,这个很重要,因为我们不希望随着容器比例变化,会让边框宽度也变化。
给容器元素加上这三个属性,这个 div 就变成了可拖拽缩放的
.rect{
// ...
resize: both;
position: relative;
overflow: auto;
}
看下效果
完美 🎉🎉🎉
在这里查看完整在线 demo stackblitz.com/edit/stackb…
来源:juejin.cn/post/7502127751572406323