起因
通常,我们做一些数据大屏项目时会使用一些插件来完成特效的制作,比如DataV组件库提供了许多大屏的特效。但是这样ui就不能自由自在的创作了,为了解决此问题,参照着DataV的写法,试试能否实现ui的设计稿。
ui设计稿

思路
- 左上角有个小三角。
- 外框是有path组成。
- 右侧的小方块一个一个画吧。
- 该边框形成一个特定的比例。
- 看左侧和下侧还有光晕,是动画吧。
开搞
定义一个特定的比例
<svg
class="ec-svg-container"
width="697"
height="462"
viewBox="0 0 697 462"
xmlns="http://www.w3.org/2000/svg"
>...</svg>
左上角小三角
<path d="M 5 5 L 20 5 L 5 20 z"
fill="transparent" stroke-linejoin="round" stroke="rgba(19,101,233)" stroke-width="2" />
外框
<path d="M 30 5 L 323 5 L 351 17 L 548 17 L 554 5 L 641 5 L 662 28
L 682 28 L 682 88 L 665 100 L 665 394 L 682 404 L 682 435
L 670 455 L 5 455 L 5 30 z"
fill="rgba(19,101,233,.4)" stroke="rgb(14,80,191)" stroke-width="2" stroke-linejoin="round" />
右侧小方块和小线段
<path d="M 673 102 L 678 102 L 678 122 L 673 122 z" fill="transparent" stroke="rgb(14,80,191)" stroke-width="2" stroke-linejoin="round"/>
<path d="M 673 135 L 678 135 L 678 155 L 673 155 z" fill="transparent" stroke="rgb(14,80,191)" stroke-width="2" stroke-linejoin="round"/>
<path d="M 673 168 L 678 168 L 678 188 L 673 188 z" fill="transparent" stroke="rgb(14,80,191)" stroke-width="2" stroke-linejoin="round"/>
<path d="M 673 201 L 678 201 L 678 221 L 673 221 z" fill="transparent" stroke="rgb(14,80,191)" stroke-width="2" stroke-linejoin="round"/>
<path d="M 673 234 L 678 234 L 678 254 L 673 254 z" fill="transparent" stroke="rgb(14,80,191)" stroke-width="2" stroke-linejoin="round"/>
<path d="M 673 267 L 678 267 L 678 287 L 673 287 z" fill="transparent" stroke="rgb(14,80,191)" stroke-width="2" stroke-linejoin="round"/>
<path d="M 673 300 L 678 300 L 678 320 L 673 320 z" fill="transparent" stroke="rgb(14,80,191)" stroke-width="2" stroke-linejoin="round"/>
<path d="M 673 333 L 678 333 L 678 353 L 673 353 z" fill="transparent" stroke="rgb(14,80,191)" stroke-width="2" stroke-linejoin="round"/>
<path d="M 673 366 L 678 366 L 678 386 L 673 386 z" fill="transparent" stroke="rgb(14,80,191)" stroke-width="2" stroke-linejoin="round"/>
<!-- 右侧小线段-->
<path d="M 680 92 L 680 101" stroke="rgb(14,80,191)" stroke-width="2" stroke-linejoin="round"/>
<path d="M 680 123 L 680 134" stroke="rgb(14,80,191)" stroke-width="2" stroke-linejoin="round"/>
<path d="M 680 156 L 680 167" stroke="rgb(14,80,191)" stroke-width="2" stroke-linejoin="round"/>
<path d="M 680 189 L 680 200" stroke="rgb(14,80,191)" stroke-width="2" stroke-linejoin="round"/>
<path d="M 680 222 L 680 233" stroke="rgb(14,80,191)" stroke-width="2" stroke-linejoin="round"/>
<path d="M 680 255 L 680 266" stroke="rgb(14,80,191)" stroke-width="2" stroke-linejoin="round"/>
<path d="M 680 288 L 680 299" stroke="rgb(14,80,191)" stroke-width="2" stroke-linejoin="round"/>
<path d="M 680 321 L 680 332" stroke="rgb(14,80,191)" stroke-width="2" stroke-linejoin="round"/>
<path d="M 680 354 L 680 365" stroke="rgb(14,80,191)" stroke-width="2" stroke-linejoin="round"/>
<path d="M 680 387 L 680 400" stroke="rgb(14,80,191)" stroke-width="2" stroke-linejoin="round"/>
真是考验耐心,和初中的计算功底呢。
光晕动画
这个是比较难的点,需要好好说说。
- 假设先画一个比较粗的,围绕着外框的光带。
- 一个圆在光带中运动,而我们只能看到圆中的部分。
- 我们看到的部分只有渐变的,咋办呢,那就在mask中加入径向渐变中间实心,外侧透明,这样就有光晕的效果啦。
<defs>
<!-- 第一个光晕的路径-->
<path id="ec-border-box-path-1" d="M 30 5 L 323 5 L 351 17 L 548 17 L 554 5 L 641 5 L 662 28 L 682 28 L 682 88 L 665 100 L 665 394 L 682 404 L 682 435 L 670 455 L 5 455 L 5 30 L 30 5" fill="transparent"></path>
<!-- 第二个光晕的路径-->
<path id="ec-border-box-path-1-c1" d="M 665 394 L 682 404 L 682 435 L 670 455 L 5 455 L 5 30 L 30 5 L 323 5 L 351 17 L 548 17 L 554 5 L 641 5 L 662 28 L 682 28 L 682 88 L 665 100 Z" fill="transparent"></path>
<!-- 定义径向渐变-->
<radialGradient id="ec-border-box-r-1" cx="50%" cy="50%" r="50%">
<stop offset="0%" stop-color="#fff" stop-opacity="1"/>
<stop offset="100%" stop-color="#fff" stop-opacity="0"/>
</radialGradient>
<!-- 定义遮罩-->
<mask id="ec-border-box-mask-1">
<!-- 定义圆,fill使用了径向渐变-->
<circle cx="0" cy="0" r="50" fill="url(#ec-border-box-r-1)">
<!-- 定义运动路径-->
<animateMotion dur="5s" rotate="auto" repeatCount="indefinite">
<mpath xlink:href="#ec-border-box-path-1"></mpath>
</animateMotion>
</circle>
<circle cx="0" cy="0" r="50" fill="url(#ec-border-box-r-1)">
<animateMotion dur="5s" rotate="auto" repeatCount="indefinite">
<mpath xlink:href="#ec-border-box-path-1-c1"></mpath>
</animateMotion>
</circle>
</mask>
</defs>
<use stroke-width="5" xlink:href="#ec-border-box-path-1" mask="url(#ec-border-box-mask-1)" stroke="rgb(19,101,233)"></use>
总的代码
<style>
body{
background-color:rgb(18,19,37)
}
.ec-box{
position:relative;
width: 500px;
height: 400px;
}
.border-box-content{
height: 100%;
}
.ec-svg-container{
position:absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
}
</style>
<div class="ec-box">
<svg
class="ec-svg-container"
width="697"
height="462"
viewBox="0 0 697 462"
xmlns="http://www.w3.org/2000/svg"
>
<defs>
<path id="ec-border-box-path-1" d="M 30 5 L 323 5 L 351 17 L 548 17 L 554 5 L 641 5 L 662 28 L 682 28 L 682 88 L 665 100 L 665 394 L 682 404 L 682 435 L 670 455 L 5 455 L 5 30 L 30 5" fill="transparent"></path>
<path id="ec-border-box-path-1-c1" d="M 665 394 L 682 404 L 682 435 L 670 455 L 5 455 L 5 30 L 30 5 L 323 5 L 351 17 L 548 17 L 554 5 L 641 5 L 662 28 L 682 28 L 682 88 L 665 100 Z" fill="transparent"></path>
<radialGradient id="ec-border-box-r-1" cx="50%" cy="50%" r="50%">
<stop offset="0%" stop-color="#fff" stop-opacity="1"/>
<stop offset="100%" stop-color="#fff" stop-opacity="0"/>
</radialGradient>
<mask id="ec-border-box-mask-1">
<circle cx="0" cy="0" r="50" fill="url(#ec-border-box-r-1)">
<animateMotion dur="5s" rotate="auto" repeatCount="indefinite">
<mpath xlink:href="#ec-border-box-path-1"></mpath>
</animateMotion>
</circle>
<circle cx="0" cy="0" r="50" fill="url(#ec-border-box-r-1)">
<animateMotion dur="5s" rotate="auto" repeatCount="indefinite">
<mpath xlink:href="#ec-border-box-path-1-c1"></mpath>
</animateMotion>
</circle>
</mask>
</defs>
<use stroke-width="5" xlink:href="#ec-border-box-path-1" mask="url(#ec-border-box-mask-1)" stroke="rgb(19,101,233)"></use>
<!-- 三角-->
<path d="M 5 5 L 20 5 L 5 20 z"
fill="transparent" stroke-linejoin="round" stroke="rgba(19,101,233)" stroke-width="2" />
<!-- 外框-->
<path d="M 30 5 L 323 5 L 351 17 L 548 17 L 554 5 L 641 5 L 662 28
L 682 28 L 682 88 L 665 100 L 665 394 L 682 404 L 682 435
L 670 455 L 5 455 L 5 30 z"
fill="rgba(19,101,233,.4)" stroke="rgb(14,80,191)" stroke-width="2" stroke-linejoin="round" />
<!-- 上方的线-->
<path d="M 352 6 L 540 6" stroke="rgb(14,80,191)" stroke-width="3" stroke-linejoin="round"/>
<!-- 右侧小方块-->
<path d="M 673 102 L 678 102 L 678 122 L 673 122 z" fill="transparent" stroke="rgb(14,80,191)" stroke-width="2" stroke-linejoin="round"/>
<path d="M 673 135 L 678 135 L 678 155 L 673 155 z" fill="transparent" stroke="rgb(14,80,191)" stroke-width="2" stroke-linejoin="round"/>
<path d="M 673 168 L 678 168 L 678 188 L 673 188 z" fill="transparent" stroke="rgb(14,80,191)" stroke-width="2" stroke-linejoin="round"/>
<path d="M 673 201 L 678 201 L 678 221 L 673 221 z" fill="transparent" stroke="rgb(14,80,191)" stroke-width="2" stroke-linejoin="round"/>
<path d="M 673 234 L 678 234 L 678 254 L 673 254 z" fill="transparent" stroke="rgb(14,80,191)" stroke-width="2" stroke-linejoin="round"/>
<path d="M 673 267 L 678 267 L 678 287 L 673 287 z" fill="transparent" stroke="rgb(14,80,191)" stroke-width="2" stroke-linejoin="round"/>
<path d="M 673 300 L 678 300 L 678 320 L 673 320 z" fill="transparent" stroke="rgb(14,80,191)" stroke-width="2" stroke-linejoin="round"/>
<path d="M 673 333 L 678 333 L 678 353 L 673 353 z" fill="transparent" stroke="rgb(14,80,191)" stroke-width="2" stroke-linejoin="round"/>
<path d="M 673 366 L 678 366 L 678 386 L 673 386 z" fill="transparent" stroke="rgb(14,80,191)" stroke-width="2" stroke-linejoin="round"/>
<!-- 右侧小线段-->
<path d="M 680 92 L 680 101" stroke="rgb(14,80,191)" stroke-width="2" stroke-linejoin="round"/>
<path d="M 680 123 L 680 134" stroke="rgb(14,80,191)" stroke-width="2" stroke-linejoin="round"/>
<path d="M 680 156 L 680 167" stroke="rgb(14,80,191)" stroke-width="2" stroke-linejoin="round"/>
<path d="M 680 189 L 680 200" stroke="rgb(14,80,191)" stroke-width="2" stroke-linejoin="round"/>
<path d="M 680 222 L 680 233" stroke="rgb(14,80,191)" stroke-width="2" stroke-linejoin="round"/>
<path d="M 680 255 L 680 266" stroke="rgb(14,80,191)" stroke-width="2" stroke-linejoin="round"/>
<path d="M 680 288 L 680 299" stroke="rgb(14,80,191)" stroke-width="2" stroke-linejoin="round"/>
<path d="M 680 321 L 680 332" stroke="rgb(14,80,191)" stroke-width="2" stroke-linejoin="round"/>
<path d="M 680 354 L 680 365" stroke="rgb(14,80,191)" stroke-width="2" stroke-linejoin="round"/>
<path d="M 680 387 L 680 400" stroke="rgb(14,80,191)" stroke-width="2" stroke-linejoin="round"/>
</svg>
</div>
最终效果
